Commit 937b8cb6 authored by ishell's avatar ishell Committed by Commit bot

[ic] Support data handlers in LoadGlobalIC.

Also fixed handling of load non-existent handlers outside typeof.

BUG=v8:5561, chromium:662854

Review-Url: https://codereview.chromium.org/2511603002
Cr-Commit-Position: refs/heads/master@{#41073}
parent 48bbd1a7
...@@ -439,9 +439,6 @@ Handle<Code> TurboFanCodeStub::GenerateCode() { ...@@ -439,9 +439,6 @@ Handle<Code> TurboFanCodeStub::GenerateCode() {
ACCESSOR_ASSEMBLER(LoadIC) ACCESSOR_ASSEMBLER(LoadIC)
ACCESSOR_ASSEMBLER(LoadICTrampoline) ACCESSOR_ASSEMBLER(LoadICTrampoline)
ACCESSOR_ASSEMBLER(LoadICProtoArray)
ACCESSOR_ASSEMBLER(LoadGlobalIC)
ACCESSOR_ASSEMBLER(LoadGlobalICTrampoline)
ACCESSOR_ASSEMBLER(KeyedLoadICTF) ACCESSOR_ASSEMBLER(KeyedLoadICTF)
ACCESSOR_ASSEMBLER(KeyedLoadICTrampolineTF) ACCESSOR_ASSEMBLER(KeyedLoadICTrampolineTF)
ACCESSOR_ASSEMBLER(StoreIC) ACCESSOR_ASSEMBLER(StoreIC)
...@@ -449,16 +446,28 @@ ACCESSOR_ASSEMBLER(StoreICTrampoline) ...@@ -449,16 +446,28 @@ ACCESSOR_ASSEMBLER(StoreICTrampoline)
#undef ACCESSOR_ASSEMBLER #undef ACCESSOR_ASSEMBLER
void LoadICProtoArrayStub::GenerateAssembly(CodeAssemblerState* state) const {
AccessorAssembler::GenerateLoadICProtoArray(
state, throw_reference_error_if_nonexistent());
}
void LoadGlobalICStub::GenerateAssembly(CodeAssemblerState* state) const {
AccessorAssembler::GenerateLoadGlobalIC(state, typeof_mode());
}
void LoadGlobalICTrampolineStub::GenerateAssembly(
CodeAssemblerState* state) const {
AccessorAssembler::GenerateLoadGlobalICTrampoline(state, typeof_mode());
}
void KeyedStoreICTrampolineTFStub::GenerateAssembly( void KeyedStoreICTrampolineTFStub::GenerateAssembly(
CodeAssemblerState* state) const { CodeAssemblerState* state) const {
LanguageMode language_mode = StoreICState::GetLanguageMode(GetExtraICState()); AccessorAssembler::GenerateKeyedStoreICTrampolineTF(state, language_mode());
AccessorAssembler::GenerateKeyedStoreICTrampolineTF(state, language_mode);
} }
void KeyedStoreICTFStub::GenerateAssembly( void KeyedStoreICTFStub::GenerateAssembly(
compiler::CodeAssemblerState* state) const { compiler::CodeAssemblerState* state) const {
LanguageMode language_mode = StoreICState::GetLanguageMode(GetExtraICState()); AccessorAssembler::GenerateKeyedStoreICTF(state, language_mode());
AccessorAssembler::GenerateKeyedStoreICTF(state, language_mode);
} }
void StoreMapStub::GenerateAssembly(compiler::CodeAssemblerState* state) const { void StoreMapStub::GenerateAssembly(compiler::CodeAssemblerState* state) const {
......
...@@ -1956,6 +1956,11 @@ class LoadGlobalICTrampolineStub : public TurboFanCodeStub { ...@@ -1956,6 +1956,11 @@ class LoadGlobalICTrampolineStub : public TurboFanCodeStub {
Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; } Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
TypeofMode typeof_mode() const {
LoadGlobalICState state(GetExtraICState());
return state.typeof_mode();
}
ExtraICState GetExtraICState() const final { ExtraICState GetExtraICState() const final {
return static_cast<ExtraICState>(minor_key_); return static_cast<ExtraICState>(minor_key_);
} }
...@@ -2022,6 +2027,10 @@ class KeyedStoreICTrampolineTFStub : public StoreICTrampolineStub { ...@@ -2022,6 +2027,10 @@ class KeyedStoreICTrampolineTFStub : public StoreICTrampolineStub {
Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; } Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
LanguageMode language_mode() const {
return StoreICState(GetExtraICState()).language_mode();
}
DEFINE_TURBOFAN_CODE_STUB(KeyedStoreICTrampolineTF, StoreICTrampolineStub); DEFINE_TURBOFAN_CODE_STUB(KeyedStoreICTrampolineTF, StoreICTrampolineStub);
}; };
...@@ -2059,7 +2068,23 @@ class LoadICStub : public TurboFanCodeStub { ...@@ -2059,7 +2068,23 @@ class LoadICStub : public TurboFanCodeStub {
class LoadICProtoArrayStub : public TurboFanCodeStub { class LoadICProtoArrayStub : public TurboFanCodeStub {
public: public:
explicit LoadICProtoArrayStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit LoadICProtoArrayStub(Isolate* isolate,
bool throw_reference_error_if_nonexistent)
: TurboFanCodeStub(isolate) {
minor_key_ = ThrowReferenceErrorIfNonexistentBits::encode(
throw_reference_error_if_nonexistent);
}
bool throw_reference_error_if_nonexistent() const {
return ThrowReferenceErrorIfNonexistentBits::decode(minor_key_);
}
ExtraICState GetExtraICState() const final {
return static_cast<ExtraICState>(minor_key_);
}
private:
class ThrowReferenceErrorIfNonexistentBits : public BitField<bool, 0, 1> {};
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadICProtoArray); DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadICProtoArray);
DEFINE_TURBOFAN_CODE_STUB(LoadICProtoArray, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(LoadICProtoArray, TurboFanCodeStub);
...@@ -2074,6 +2099,11 @@ class LoadGlobalICStub : public TurboFanCodeStub { ...@@ -2074,6 +2099,11 @@ class LoadGlobalICStub : public TurboFanCodeStub {
Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; } Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
TypeofMode typeof_mode() const {
LoadGlobalICState state(GetExtraICState());
return state.typeof_mode();
}
ExtraICState GetExtraICState() const final { ExtraICState GetExtraICState() const final {
return static_cast<ExtraICState>(minor_key_); return static_cast<ExtraICState>(minor_key_);
} }
...@@ -2099,6 +2129,11 @@ class StoreICStub : public TurboFanCodeStub { ...@@ -2099,6 +2129,11 @@ class StoreICStub : public TurboFanCodeStub {
} }
Code::Kind GetCodeKind() const override { return Code::STORE_IC; } Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
LanguageMode language_mode() const {
return StoreICState(GetExtraICState()).language_mode();
}
ExtraICState GetExtraICState() const final { ExtraICState GetExtraICState() const final {
return static_cast<ExtraICState>(minor_key_); return static_cast<ExtraICState>(minor_key_);
} }
...@@ -2136,6 +2171,10 @@ class KeyedStoreICTFStub : public StoreICStub { ...@@ -2136,6 +2171,10 @@ class KeyedStoreICTFStub : public StoreICStub {
Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; } Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
LanguageMode language_mode() const {
return StoreICState(GetExtraICState()).language_mode();
}
DEFINE_TURBOFAN_CODE_STUB(KeyedStoreICTF, StoreICStub); DEFINE_TURBOFAN_CODE_STUB(KeyedStoreICTF, StoreICStub);
}; };
......
...@@ -508,6 +508,7 @@ void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, ...@@ -508,6 +508,7 @@ void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
proxy->VariableFeedbackSlot()); proxy->VariableFeedbackSlot());
Handle<Code> code = CodeFactory::LoadGlobalIC(isolate(), typeof_mode).code(); Handle<Code> code = CodeFactory::LoadGlobalIC(isolate(), typeof_mode).code();
__ Call(code, RelocInfo::CODE_TARGET); __ Call(code, RelocInfo::CODE_TARGET);
RestoreContext();
} }
void FullCodeGenerator::VisitSloppyBlockFunctionStatement( void FullCodeGenerator::VisitSloppyBlockFunctionStatement(
......
...@@ -314,26 +314,24 @@ inline std::ostream& operator<<(std::ostream& os, const LanguageMode& mode) { ...@@ -314,26 +314,24 @@ inline std::ostream& operator<<(std::ostream& os, const LanguageMode& mode) {
return os; return os;
} }
inline bool is_sloppy(LanguageMode language_mode) { inline bool is_sloppy(LanguageMode language_mode) {
return language_mode == SLOPPY; return language_mode == SLOPPY;
} }
inline bool is_strict(LanguageMode language_mode) { inline bool is_strict(LanguageMode language_mode) {
return language_mode != SLOPPY; return language_mode != SLOPPY;
} }
inline bool is_valid_language_mode(int language_mode) { inline bool is_valid_language_mode(int language_mode) {
return language_mode == SLOPPY || language_mode == STRICT; return language_mode == SLOPPY || language_mode == STRICT;
} }
inline LanguageMode construct_language_mode(bool strict_bit) { inline LanguageMode construct_language_mode(bool strict_bit) {
return static_cast<LanguageMode>(strict_bit); return static_cast<LanguageMode>(strict_bit);
} }
enum TypeofMode : int { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
// This constant is used as an undefined value when passing source positions. // This constant is used as an undefined value when passing source positions.
const int kNoSourcePosition = -1; const int kNoSourcePosition = -1;
......
...@@ -19,16 +19,13 @@ using compiler::Node; ...@@ -19,16 +19,13 @@ using compiler::Node;
#define ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE(V) \ #define ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE(V) \
V(LoadIC) \ V(LoadIC) \
V(LoadICTrampoline) \ V(LoadICTrampoline) \
V(LoadICProtoArray) \
V(LoadGlobalIC) \
V(LoadGlobalICTrampoline) \
V(KeyedLoadICTF) \ V(KeyedLoadICTF) \
V(KeyedLoadICTrampolineTF) \ V(KeyedLoadICTrampolineTF) \
V(KeyedLoadICMegamorphic) \ V(KeyedLoadICMegamorphic) \
V(StoreIC) \ V(StoreIC) \
V(StoreICTrampoline) V(StoreICTrampoline)
// KeyedStoreIC and KeyedStoreICTrampoline need custom handling because of // The other IC entry points need custom handling because of additional
// their "language_mode" parameter. // parameters like "typeof_mode" or "language_mode".
class AccessorAssemblerImpl : public CodeStubAssembler { class AccessorAssemblerImpl : public CodeStubAssembler {
public: public:
...@@ -40,6 +37,11 @@ class AccessorAssemblerImpl : public CodeStubAssembler { ...@@ -40,6 +37,11 @@ class AccessorAssemblerImpl : public CodeStubAssembler {
ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE(DECLARE_PUBLIC_METHOD) ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE(DECLARE_PUBLIC_METHOD)
#undef DECLARE_PUBLIC_METHOD #undef DECLARE_PUBLIC_METHOD
void GenerateLoadICProtoArray(bool throw_reference_error_if_nonexistent);
void GenerateLoadGlobalIC(TypeofMode typeof_mode);
void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
void GenerateKeyedStoreICTF(LanguageMode language_mode); void GenerateKeyedStoreICTF(LanguageMode language_mode);
void GenerateKeyedStoreICTrampolineTF(LanguageMode language_mode); void GenerateKeyedStoreICTrampolineTF(LanguageMode language_mode);
...@@ -88,8 +90,9 @@ class AccessorAssemblerImpl : public CodeStubAssembler { ...@@ -88,8 +90,9 @@ class AccessorAssemblerImpl : public CodeStubAssembler {
// Stub generation entry points. // Stub generation entry points.
void LoadIC(const LoadICParameters* p); void LoadIC(const LoadICParameters* p);
void LoadICProtoArray(const LoadICParameters* p, Node* handler); void LoadICProtoArray(const LoadICParameters* p, Node* handler,
void LoadGlobalIC(const LoadICParameters* p); bool throw_reference_error_if_nonexistent);
void LoadGlobalIC(const LoadICParameters* p, TypeofMode typeof_mode);
void KeyedLoadIC(const LoadICParameters* p); void KeyedLoadIC(const LoadICParameters* p);
void KeyedLoadICGeneric(const LoadICParameters* p); void KeyedLoadICGeneric(const LoadICParameters* p);
void StoreIC(const StoreICParameters* p); void StoreIC(const StoreICParameters* p);
...@@ -120,13 +123,22 @@ class AccessorAssemblerImpl : public CodeStubAssembler { ...@@ -120,13 +123,22 @@ class AccessorAssemblerImpl : public CodeStubAssembler {
Node* smi_handler, Label* miss, Node* smi_handler, Label* miss,
ElementSupport support_elements); ElementSupport support_elements);
void HandleLoadICProtoHandler(const LoadICParameters* p, Node* handler, void HandleLoadICProtoHandlerCase(const LoadICParameters* p, Node* handler,
Variable* var_holder, Variable* var_smi_handler, Variable* var_holder,
Label* if_smi_handler, Label* miss); Variable* var_smi_handler,
Label* if_smi_handler, Label* miss,
bool throw_reference_error_if_nonexistent);
Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler, Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler,
Node* handler_length, Node* handler_flags, Node* handler_length, Node* handler_flags,
Label* miss); Label* miss,
bool throw_reference_error_if_nonexistent);
// LoadGlobalIC implementation.
void HandleLoadGlobalICHandlerCase(const LoadICParameters* p, Node* handler,
Label* miss,
bool throw_reference_error_if_nonexistent);
// StoreIC implementation. // StoreIC implementation.
......
...@@ -166,8 +166,8 @@ void AccessorAssemblerImpl::HandleLoadICHandlerCase( ...@@ -166,8 +166,8 @@ void AccessorAssemblerImpl::HandleLoadICHandlerCase(
Bind(&try_proto_handler); Bind(&try_proto_handler);
{ {
GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler, HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler,
&if_smi_handler, miss); &if_smi_handler, miss, false);
} }
Bind(&call_handler); Bind(&call_handler);
...@@ -304,9 +304,10 @@ void AccessorAssemblerImpl::HandleLoadICSmiHandlerCase( ...@@ -304,9 +304,10 @@ void AccessorAssemblerImpl::HandleLoadICSmiHandlerCase(
} }
} }
void AccessorAssemblerImpl::HandleLoadICProtoHandler( void AccessorAssemblerImpl::HandleLoadICProtoHandlerCase(
const LoadICParameters* p, Node* handler, Variable* var_holder, const LoadICParameters* p, Node* handler, Variable* var_holder,
Variable* var_smi_handler, Label* if_smi_handler, Label* miss) { Variable* var_smi_handler, Label* if_smi_handler, Label* miss,
bool throw_reference_error_if_nonexistent) {
DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep());
DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep());
...@@ -339,6 +340,8 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler( ...@@ -339,6 +340,8 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler(
IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>(handler_flags), IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>(handler_flags),
&check_prototypes); &check_prototypes);
{ {
CSA_ASSERT(this, Word32BinaryNot(
HasInstanceType(p->receiver, JS_GLOBAL_OBJECT_TYPE)));
// We have a dictionary receiver, do a negative lookup check. // We have a dictionary receiver, do a negative lookup check.
NameDictionaryNegativeLookup(p->receiver, p->name, miss); NameDictionaryNegativeLookup(p->receiver, p->name, miss);
Goto(&check_prototypes); Goto(&check_prototypes);
...@@ -355,7 +358,11 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler( ...@@ -355,7 +358,11 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler(
Label load_existent(this); Label load_existent(this);
GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent);
// This is a handler for a load of a non-existent value. // This is a handler for a load of a non-existent value.
Return(UndefinedConstant()); if (throw_reference_error_if_nonexistent) {
TailCallRuntime(Runtime::kThrowReferenceError, p->context, p->name);
} else {
Return(UndefinedConstant());
}
Bind(&load_existent); Bind(&load_existent);
Node* holder = LoadWeakCellValue(maybe_holder_cell); Node* holder = LoadWeakCellValue(maybe_holder_cell);
...@@ -371,7 +378,7 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler( ...@@ -371,7 +378,7 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler(
Bind(&array_handler); Bind(&array_handler);
{ {
typedef LoadICProtoArrayDescriptor Descriptor; typedef LoadICProtoArrayDescriptor Descriptor;
LoadICProtoArrayStub stub(isolate()); LoadICProtoArrayStub stub(isolate(), throw_reference_error_if_nonexistent);
Node* target = HeapConstant(stub.GetCode()); Node* target = HeapConstant(stub.GetCode());
TailCallStub(Descriptor(isolate()), target, p->context, TailCallStub(Descriptor(isolate()), target, p->context,
Arg(Descriptor::kReceiver, p->receiver), Arg(Descriptor::kReceiver, p->receiver),
...@@ -384,7 +391,8 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler( ...@@ -384,7 +391,8 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler(
Node* AccessorAssemblerImpl::EmitLoadICProtoArrayCheck( Node* AccessorAssemblerImpl::EmitLoadICProtoArrayCheck(
const LoadICParameters* p, Node* handler, Node* handler_length, const LoadICParameters* p, Node* handler, Node* handler_length,
Node* handler_flags, Label* miss) { Node* handler_flags, Label* miss,
bool throw_reference_error_if_nonexistent) {
Variable start_index(this, MachineType::PointerRepresentation()); Variable start_index(this, MachineType::PointerRepresentation());
start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex)); start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex));
...@@ -430,7 +438,11 @@ Node* AccessorAssemblerImpl::EmitLoadICProtoArrayCheck( ...@@ -430,7 +438,11 @@ Node* AccessorAssemblerImpl::EmitLoadICProtoArrayCheck(
Label load_existent(this); Label load_existent(this);
GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent);
// This is a handler for a load of a non-existent value. // This is a handler for a load of a non-existent value.
Return(UndefinedConstant()); if (throw_reference_error_if_nonexistent) {
TailCallRuntime(Runtime::kThrowReferenceError, p->context, p->name);
} else {
Return(UndefinedConstant());
}
Bind(&load_existent); Bind(&load_existent);
Node* holder = LoadWeakCellValue(maybe_holder_cell); Node* holder = LoadWeakCellValue(maybe_holder_cell);
...@@ -441,6 +453,25 @@ Node* AccessorAssemblerImpl::EmitLoadICProtoArrayCheck( ...@@ -441,6 +453,25 @@ Node* AccessorAssemblerImpl::EmitLoadICProtoArrayCheck(
return holder; return holder;
} }
void AccessorAssemblerImpl::HandleLoadGlobalICHandlerCase(
const LoadICParameters* pp, Node* handler, Label* miss,
bool throw_reference_error_if_nonexistent) {
LoadICParameters p = *pp;
DCHECK_NULL(p.receiver);
Node* native_context = LoadNativeContext(p.context);
p.receiver = LoadContextElement(native_context, Context::EXTENSION_INDEX);
Variable var_holder(this, MachineRepresentation::kTagged);
Variable var_smi_handler(this, MachineRepresentation::kTagged);
Label if_smi_handler(this);
HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler,
&if_smi_handler, miss,
throw_reference_error_if_nonexistent);
Bind(&if_smi_handler);
HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(),
miss, kOnlyProperties);
}
void AccessorAssemblerImpl::HandleStoreICHandlerCase(const StoreICParameters* p, void AccessorAssemblerImpl::HandleStoreICHandlerCase(const StoreICParameters* p,
Node* handler, Node* handler,
Label* miss) { Label* miss) {
...@@ -1120,8 +1151,9 @@ void AccessorAssemblerImpl::LoadIC(const LoadICParameters* p) { ...@@ -1120,8 +1151,9 @@ void AccessorAssemblerImpl::LoadIC(const LoadICParameters* p) {
} }
} }
void AccessorAssemblerImpl::LoadICProtoArray(const LoadICParameters* p, void AccessorAssemblerImpl::LoadICProtoArray(
Node* handler) { const LoadICParameters* p, Node* handler,
bool throw_reference_error_if_nonexistent) {
Label miss(this); Label miss(this);
CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler)));
CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler))); CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler)));
...@@ -1131,8 +1163,9 @@ void AccessorAssemblerImpl::LoadICProtoArray(const LoadICParameters* p, ...@@ -1131,8 +1163,9 @@ void AccessorAssemblerImpl::LoadICProtoArray(const LoadICParameters* p,
Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler); Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler);
Node* holder = EmitLoadICProtoArrayCheck(p, handler, handler_length, Node* holder =
handler_flags, &miss); EmitLoadICProtoArrayCheck(p, handler, handler_length, handler_flags,
&miss, throw_reference_error_if_nonexistent);
HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, kOnlyProperties); HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, kOnlyProperties);
...@@ -1143,8 +1176,9 @@ void AccessorAssemblerImpl::LoadICProtoArray(const LoadICParameters* p, ...@@ -1143,8 +1176,9 @@ void AccessorAssemblerImpl::LoadICProtoArray(const LoadICParameters* p,
} }
} }
void AccessorAssemblerImpl::LoadGlobalIC(const LoadICParameters* p) { void AccessorAssemblerImpl::LoadGlobalIC(const LoadICParameters* p,
Label try_handler(this), miss(this); TypeofMode typeof_mode) {
Label try_handler(this), call_handler(this), miss(this);
Node* weak_cell = Node* weak_cell =
LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS);
CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE)); CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE));
...@@ -1157,15 +1191,24 @@ void AccessorAssemblerImpl::LoadGlobalIC(const LoadICParameters* p) { ...@@ -1157,15 +1191,24 @@ void AccessorAssemblerImpl::LoadGlobalIC(const LoadICParameters* p) {
GotoIf(WordEqual(value, TheHoleConstant()), &miss); GotoIf(WordEqual(value, TheHoleConstant()), &miss);
Return(value); Return(value);
Node* handler;
Bind(&try_handler); Bind(&try_handler);
{ {
Node* handler = handler =
LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS); LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS);
CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler)));
GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)), GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
&miss); &miss);
GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
// In this case {handler} must be a Code object. bool throw_reference_error_if_nonexistent =
CSA_ASSERT(this, HasInstanceType(handler, CODE_TYPE)); typeof_mode == NOT_INSIDE_TYPEOF;
HandleLoadGlobalICHandlerCase(p, handler, &miss,
throw_reference_error_if_nonexistent);
}
Bind(&call_handler);
{
LoadWithVectorDescriptor descriptor(isolate()); LoadWithVectorDescriptor descriptor(isolate());
Node* native_context = LoadNativeContext(p->context); Node* native_context = LoadNativeContext(p->context);
Node* receiver = Node* receiver =
...@@ -1551,7 +1594,8 @@ void AccessorAssemblerImpl::GenerateLoadICTrampoline() { ...@@ -1551,7 +1594,8 @@ void AccessorAssemblerImpl::GenerateLoadICTrampoline() {
LoadIC(&p); LoadIC(&p);
} }
void AccessorAssemblerImpl::GenerateLoadICProtoArray() { void AccessorAssemblerImpl::GenerateLoadICProtoArray(
bool throw_reference_error_if_nonexistent) {
typedef LoadICProtoArrayStub::Descriptor Descriptor; typedef LoadICProtoArrayStub::Descriptor Descriptor;
Node* receiver = Parameter(Descriptor::kReceiver); Node* receiver = Parameter(Descriptor::kReceiver);
...@@ -1562,10 +1606,10 @@ void AccessorAssemblerImpl::GenerateLoadICProtoArray() { ...@@ -1562,10 +1606,10 @@ void AccessorAssemblerImpl::GenerateLoadICProtoArray() {
Node* context = Parameter(Descriptor::kContext); Node* context = Parameter(Descriptor::kContext);
LoadICParameters p(context, receiver, name, slot, vector); LoadICParameters p(context, receiver, name, slot, vector);
LoadICProtoArray(&p, handler); LoadICProtoArray(&p, handler, throw_reference_error_if_nonexistent);
} }
void AccessorAssemblerImpl::GenerateLoadGlobalIC() { void AccessorAssemblerImpl::GenerateLoadGlobalIC(TypeofMode typeof_mode) {
typedef LoadGlobalICStub::Descriptor Descriptor; typedef LoadGlobalICStub::Descriptor Descriptor;
Node* name = Parameter(Descriptor::kName); Node* name = Parameter(Descriptor::kName);
...@@ -1574,10 +1618,11 @@ void AccessorAssemblerImpl::GenerateLoadGlobalIC() { ...@@ -1574,10 +1618,11 @@ void AccessorAssemblerImpl::GenerateLoadGlobalIC() {
Node* context = Parameter(Descriptor::kContext); Node* context = Parameter(Descriptor::kContext);
LoadICParameters p(context, nullptr, name, slot, vector); LoadICParameters p(context, nullptr, name, slot, vector);
LoadGlobalIC(&p); LoadGlobalIC(&p, typeof_mode);
} }
void AccessorAssemblerImpl::GenerateLoadGlobalICTrampoline() { void AccessorAssemblerImpl::GenerateLoadGlobalICTrampoline(
TypeofMode typeof_mode) {
typedef LoadGlobalICTrampolineStub::Descriptor Descriptor; typedef LoadGlobalICTrampolineStub::Descriptor Descriptor;
Node* name = Parameter(Descriptor::kName); Node* name = Parameter(Descriptor::kName);
...@@ -1586,7 +1631,7 @@ void AccessorAssemblerImpl::GenerateLoadGlobalICTrampoline() { ...@@ -1586,7 +1631,7 @@ void AccessorAssemblerImpl::GenerateLoadGlobalICTrampoline() {
Node* vector = LoadTypeFeedbackVectorForStub(); Node* vector = LoadTypeFeedbackVectorForStub();
LoadICParameters p(context, nullptr, name, slot, vector); LoadICParameters p(context, nullptr, name, slot, vector);
LoadGlobalIC(&p); LoadGlobalIC(&p, typeof_mode);
} }
void AccessorAssemblerImpl::GenerateKeyedLoadICTF() { void AccessorAssemblerImpl::GenerateKeyedLoadICTF() {
...@@ -1696,6 +1741,24 @@ void AccessorAssemblerImpl::GenerateKeyedStoreICTrampolineTF( ...@@ -1696,6 +1741,24 @@ void AccessorAssemblerImpl::GenerateKeyedStoreICTrampolineTF(
ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE(DISPATCH_TO_IMPL) ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE(DISPATCH_TO_IMPL)
#undef DISPATCH_TO_IMPL #undef DISPATCH_TO_IMPL
void AccessorAssembler::GenerateLoadICProtoArray(
CodeAssemblerState* state, bool throw_reference_error_if_nonexistent) {
AccessorAssemblerImpl assembler(state);
assembler.GenerateLoadICProtoArray(throw_reference_error_if_nonexistent);
}
void AccessorAssembler::GenerateLoadGlobalIC(CodeAssemblerState* state,
TypeofMode typeof_mode) {
AccessorAssemblerImpl assembler(state);
assembler.GenerateLoadGlobalIC(typeof_mode);
}
void AccessorAssembler::GenerateLoadGlobalICTrampoline(
CodeAssemblerState* state, TypeofMode typeof_mode) {
AccessorAssemblerImpl assembler(state);
assembler.GenerateLoadGlobalICTrampoline(typeof_mode);
}
void AccessorAssembler::GenerateKeyedStoreICTF(CodeAssemblerState* state, void AccessorAssembler::GenerateKeyedStoreICTF(CodeAssemblerState* state,
LanguageMode language_mode) { LanguageMode language_mode) {
AccessorAssemblerImpl assembler(state); AccessorAssemblerImpl assembler(state);
......
...@@ -18,10 +18,13 @@ class AccessorAssembler { ...@@ -18,10 +18,13 @@ class AccessorAssembler {
public: public:
static void GenerateLoadIC(compiler::CodeAssemblerState* state); static void GenerateLoadIC(compiler::CodeAssemblerState* state);
static void GenerateLoadICTrampoline(compiler::CodeAssemblerState* state); static void GenerateLoadICTrampoline(compiler::CodeAssemblerState* state);
static void GenerateLoadICProtoArray(compiler::CodeAssemblerState* state); static void GenerateLoadICProtoArray(
static void GenerateLoadGlobalIC(compiler::CodeAssemblerState* state); compiler::CodeAssemblerState* state,
bool throw_reference_error_if_nonexistent);
static void GenerateLoadGlobalIC(compiler::CodeAssemblerState* state,
TypeofMode typeof_mode);
static void GenerateLoadGlobalICTrampoline( static void GenerateLoadGlobalICTrampoline(
compiler::CodeAssemblerState* state); compiler::CodeAssemblerState* state, TypeofMode typeof_mode);
static void GenerateKeyedLoadICTF(compiler::CodeAssemblerState* state); static void GenerateKeyedLoadICTF(compiler::CodeAssemblerState* state);
static void GenerateKeyedLoadICTrampolineTF( static void GenerateKeyedLoadICTrampolineTF(
compiler::CodeAssemblerState* state); compiler::CodeAssemblerState* state);
......
...@@ -564,7 +564,7 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, ...@@ -564,7 +564,7 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
nexus->ConfigureMonomorphic(map, handler); nexus->ConfigureMonomorphic(map, handler);
} else if (kind() == Code::LOAD_GLOBAL_IC) { } else if (kind() == Code::LOAD_GLOBAL_IC) {
LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>(); LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
nexus->ConfigureHandlerMode(Handle<Code>::cast(handler)); nexus->ConfigureHandlerMode(handler);
} else if (kind() == Code::KEYED_LOAD_IC) { } else if (kind() == Code::KEYED_LOAD_IC) {
KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
nexus->ConfigureMonomorphic(name, map, handler); nexus->ConfigureMonomorphic(name, map, handler);
...@@ -794,6 +794,7 @@ void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { ...@@ -794,6 +794,7 @@ void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
DCHECK(IsHandler(*handler)); DCHECK(IsHandler(*handler));
// Currently only LoadIC and KeyedLoadIC support non-code handlers. // Currently only LoadIC and KeyedLoadIC support non-code handlers.
DCHECK_IMPLIES(!handler->IsCode(), kind() == Code::LOAD_IC || DCHECK_IMPLIES(!handler->IsCode(), kind() == Code::LOAD_IC ||
kind() == Code::LOAD_GLOBAL_IC ||
kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_LOAD_IC ||
kind() == Code::STORE_IC || kind() == Code::STORE_IC ||
kind() == Code::KEYED_STORE_IC); kind() == Code::KEYED_STORE_IC);
...@@ -858,10 +859,6 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map, ...@@ -858,10 +859,6 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
Handle<Name> name, int first_index) { Handle<Name> name, int first_index) {
DCHECK(holder.is_null() || holder->HasFastProperties()); DCHECK(holder.is_null() || holder->HasFastProperties());
// The following kinds of receiver maps require custom handler compilation.
if (receiver_map->IsJSGlobalObjectMap()) {
return -1;
}
// We don't encode the requirement to check access rights because we already // We don't encode the requirement to check access rights because we already
// passed the access check for current native context and the access // passed the access check for current native context and the access
// can't be revoked. // can't be revoked.
...@@ -882,6 +879,17 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map, ...@@ -882,6 +879,17 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
native_context->self_weak_cell()); native_context->self_weak_cell());
} }
checks_count++; checks_count++;
} else if (receiver_map->IsJSGlobalObjectMap()) {
if (fill_array) {
Handle<JSGlobalObject> global = isolate->global_object();
Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
global, name, PropertyCellType::kInvalidated);
DCHECK(cell->value()->IsTheHole(isolate));
Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
array->set(LoadHandler::kFirstPrototypeIndex + checks_count, *weak_cell);
}
checks_count++;
} }
// Create/count entries for each global or dictionary prototype appeared in // Create/count entries for each global or dictionary prototype appeared in
...@@ -937,14 +945,14 @@ Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map, ...@@ -937,14 +945,14 @@ Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
Handle<Object> smi_handler) { Handle<Object> smi_handler) {
int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder); int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder);
DCHECK_LE(0, checks_count); DCHECK_LE(0, checks_count);
DCHECK(!receiver_map->IsJSGlobalObjectMap());
if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) { if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
DCHECK(!receiver_map->is_dictionary_map()); DCHECK(!receiver_map->is_dictionary_map());
DCHECK_LE(1, checks_count); // For native context. DCHECK_LE(1, checks_count); // For native context.
smi_handler = smi_handler =
LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler); LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler);
} else if (receiver_map->is_dictionary_map()) { } else if (receiver_map->is_dictionary_map() &&
!receiver_map->IsJSGlobalObjectMap()) {
smi_handler = smi_handler =
LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler); LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler);
} }
...@@ -975,10 +983,11 @@ Handle<Object> LoadIC::LoadNonExistent(Handle<Map> receiver_map, ...@@ -975,10 +983,11 @@ Handle<Object> LoadIC::LoadNonExistent(Handle<Map> receiver_map,
Handle<JSObject> holder; // null handle Handle<JSObject> holder; // null handle
int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder); int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder);
DCHECK_LE(0, checks_count); DCHECK_LE(0, checks_count);
DCHECK(!receiver_map->IsJSGlobalObjectMap());
Handle<Object> smi_handler = LoadHandler::LoadNonExistent( bool do_negative_lookup_on_receiver =
isolate(), receiver_map->is_dictionary_map()); receiver_map->is_dictionary_map() && !receiver_map->IsJSGlobalObjectMap();
Handle<Object> smi_handler =
LoadHandler::LoadNonExistent(isolate(), do_negative_lookup_on_receiver);
if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) { if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
DCHECK(!receiver_map->is_dictionary_map()); DCHECK(!receiver_map->is_dictionary_map());
...@@ -1066,14 +1075,16 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) { ...@@ -1066,14 +1075,16 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
lookup->state() == LookupIterator::ACCESS_CHECK) { lookup->state() == LookupIterator::ACCESS_CHECK) {
code = slow_stub(); code = slow_stub();
} else if (!lookup->IsFound()) { } else if (!lookup->IsFound()) {
if (kind() == Code::LOAD_IC) { if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH); if (FLAG_tf_load_ic_stub) {
code = LoadNonExistent(receiver_map(), lookup->name()); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
} else if (kind() == Code::LOAD_GLOBAL_IC) { code = LoadNonExistent(receiver_map(), lookup->name());
code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), } else {
receiver_map()); code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(),
// TODO(jkummerow/verwaest): Introduce a builtin that handles this case. receiver_map());
if (code.is_null()) code = slow_stub(); // TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
if (code.is_null()) code = slow_stub();
}
} else { } else {
code = slow_stub(); code = slow_stub();
} }
...@@ -1394,7 +1405,7 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { ...@@ -1394,7 +1405,7 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
if (receiver_is_holder) { if (receiver_is_holder) {
return smi_handler; return smi_handler;
} }
if (FLAG_tf_load_ic_stub && kind() != Code::LOAD_GLOBAL_IC) { if (FLAG_tf_load_ic_stub) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
return LoadFromPrototype(map, holder, lookup->name(), smi_handler); return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
} }
...@@ -1410,10 +1421,8 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { ...@@ -1410,10 +1421,8 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
return smi_handler; return smi_handler;
} }
if (kind() != Code::LOAD_GLOBAL_IC) { TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH); return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
}
} else { } else {
if (receiver_is_holder) { if (receiver_is_holder) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
......
...@@ -181,10 +181,6 @@ enum KeyedAccessStoreMode { ...@@ -181,10 +181,6 @@ enum KeyedAccessStoreMode {
STORE_NO_TRANSITION_HANDLE_COW STORE_NO_TRANSITION_HANDLE_COW
}; };
enum TypeofMode : int { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
enum MutableMode { enum MutableMode {
MUTABLE, MUTABLE,
IMMUTABLE IMMUTABLE
......
...@@ -713,7 +713,7 @@ void LoadGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) { ...@@ -713,7 +713,7 @@ void LoadGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
SKIP_WRITE_BARRIER); SKIP_WRITE_BARRIER);
} }
void LoadGlobalICNexus::ConfigureHandlerMode(Handle<Code> handler) { void LoadGlobalICNexus::ConfigureHandlerMode(Handle<Object> handler) {
SetFeedback(GetIsolate()->heap()->empty_weak_cell()); SetFeedback(GetIsolate()->heap()->empty_weak_cell());
SetFeedbackExtra(*handler); SetFeedbackExtra(*handler);
} }
......
...@@ -555,7 +555,7 @@ class LoadGlobalICNexus : public FeedbackNexus { ...@@ -555,7 +555,7 @@ class LoadGlobalICNexus : public FeedbackNexus {
void ConfigureUninitialized() override; void ConfigureUninitialized() override;
void ConfigurePropertyCellMode(Handle<PropertyCell> cell); void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
void ConfigureHandlerMode(Handle<Code> handler); void ConfigureHandlerMode(Handle<Object> handler);
InlineCacheState StateFromFeedback() const override; InlineCacheState StateFromFeedback() const override;
}; };
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function f() {
typeof boom;
boom;
}
assertThrows(()=>f());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment