Chromium Code Reviews| Index: src/ic/accessor-assembler.cc |
| diff --git a/src/ic/accessor-assembler.cc b/src/ic/accessor-assembler.cc |
| index 2f1a97ec172b571c1af7028eb8596f60a60540ad..dafb055cad70b79b076cc39b6834c436091ea5df 100644 |
| --- a/src/ic/accessor-assembler.cc |
| +++ b/src/ic/accessor-assembler.cc |
| @@ -166,8 +166,8 @@ void AccessorAssemblerImpl::HandleLoadICHandlerCase( |
| Bind(&try_proto_handler); |
| { |
| GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); |
| - HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler, |
| - &if_smi_handler, miss); |
| + HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler, |
| + &if_smi_handler, miss, false); |
| } |
| Bind(&call_handler); |
| @@ -304,9 +304,10 @@ void AccessorAssemblerImpl::HandleLoadICSmiHandlerCase( |
| } |
| } |
| -void AccessorAssemblerImpl::HandleLoadICProtoHandler( |
| +void AccessorAssemblerImpl::HandleLoadICProtoHandlerCase( |
| 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_smi_handler->rep()); |
| @@ -339,6 +340,8 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler( |
| IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>(handler_flags), |
| &check_prototypes); |
| { |
| + CSA_ASSERT(this, Word32BinaryNot( |
| + HasInstanceType(p->receiver, JS_GLOBAL_OBJECT_TYPE))); |
|
Igor Sheludko
2016/11/17 11:32:08
The catcher.
|
| // We have a dictionary receiver, do a negative lookup check. |
| NameDictionaryNegativeLookup(p->receiver, p->name, miss); |
| Goto(&check_prototypes); |
| @@ -355,7 +358,11 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler( |
| Label load_existent(this); |
| GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); |
| // 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); |
| Node* holder = LoadWeakCellValue(maybe_holder_cell); |
| @@ -371,7 +378,7 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler( |
| Bind(&array_handler); |
| { |
| typedef LoadICProtoArrayDescriptor Descriptor; |
| - LoadICProtoArrayStub stub(isolate()); |
| + LoadICProtoArrayStub stub(isolate(), throw_reference_error_if_nonexistent); |
| Node* target = HeapConstant(stub.GetCode()); |
| TailCallStub(Descriptor(isolate()), target, p->context, |
| Arg(Descriptor::kReceiver, p->receiver), |
| @@ -384,7 +391,8 @@ void AccessorAssemblerImpl::HandleLoadICProtoHandler( |
| Node* AccessorAssemblerImpl::EmitLoadICProtoArrayCheck( |
| 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()); |
| start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex)); |
| @@ -430,7 +438,11 @@ Node* AccessorAssemblerImpl::EmitLoadICProtoArrayCheck( |
| Label load_existent(this); |
| GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); |
| // 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); |
| Node* holder = LoadWeakCellValue(maybe_holder_cell); |
| @@ -441,6 +453,25 @@ Node* AccessorAssemblerImpl::EmitLoadICProtoArrayCheck( |
| 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, |
| Node* handler, |
| Label* miss) { |
| @@ -1120,8 +1151,9 @@ void AccessorAssemblerImpl::LoadIC(const LoadICParameters* p) { |
| } |
| } |
| -void AccessorAssemblerImpl::LoadICProtoArray(const LoadICParameters* p, |
| - Node* handler) { |
| +void AccessorAssemblerImpl::LoadICProtoArray( |
| + const LoadICParameters* p, Node* handler, |
| + bool throw_reference_error_if_nonexistent) { |
| Label miss(this); |
| CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); |
| CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler))); |
| @@ -1131,8 +1163,9 @@ void AccessorAssemblerImpl::LoadICProtoArray(const LoadICParameters* p, |
| Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler); |
| - Node* holder = EmitLoadICProtoArrayCheck(p, handler, handler_length, |
| - handler_flags, &miss); |
| + Node* holder = |
| + EmitLoadICProtoArrayCheck(p, handler, handler_length, handler_flags, |
| + &miss, throw_reference_error_if_nonexistent); |
| HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, kOnlyProperties); |
| @@ -1143,8 +1176,9 @@ void AccessorAssemblerImpl::LoadICProtoArray(const LoadICParameters* p, |
| } |
| } |
| -void AccessorAssemblerImpl::LoadGlobalIC(const LoadICParameters* p) { |
| - Label try_handler(this), miss(this); |
| +void AccessorAssemblerImpl::LoadGlobalIC(const LoadICParameters* p, |
| + TypeofMode typeof_mode) { |
| + Label try_handler(this), call_handler(this), miss(this); |
| Node* weak_cell = |
| LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); |
| CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE)); |
| @@ -1157,15 +1191,24 @@ void AccessorAssemblerImpl::LoadGlobalIC(const LoadICParameters* p) { |
| GotoIf(WordEqual(value, TheHoleConstant()), &miss); |
| Return(value); |
| + Node* handler; |
| Bind(&try_handler); |
| { |
| - Node* handler = |
| + handler = |
| LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS); |
| + CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); |
| GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)), |
| &miss); |
| + GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); |
| - // In this case {handler} must be a Code object. |
| - CSA_ASSERT(this, HasInstanceType(handler, CODE_TYPE)); |
| + bool throw_reference_error_if_nonexistent = |
| + typeof_mode == NOT_INSIDE_TYPEOF; |
| + HandleLoadGlobalICHandlerCase(p, handler, &miss, |
| + throw_reference_error_if_nonexistent); |
| + } |
| + |
| + Bind(&call_handler); |
| + { |
| LoadWithVectorDescriptor descriptor(isolate()); |
| Node* native_context = LoadNativeContext(p->context); |
| Node* receiver = |
| @@ -1551,7 +1594,8 @@ void AccessorAssemblerImpl::GenerateLoadICTrampoline() { |
| LoadIC(&p); |
| } |
| -void AccessorAssemblerImpl::GenerateLoadICProtoArray() { |
| +void AccessorAssemblerImpl::GenerateLoadICProtoArray( |
| + bool throw_reference_error_if_nonexistent) { |
| typedef LoadICProtoArrayStub::Descriptor Descriptor; |
| Node* receiver = Parameter(Descriptor::kReceiver); |
| @@ -1562,10 +1606,10 @@ void AccessorAssemblerImpl::GenerateLoadICProtoArray() { |
| Node* context = Parameter(Descriptor::kContext); |
| 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; |
| Node* name = Parameter(Descriptor::kName); |
| @@ -1574,10 +1618,11 @@ void AccessorAssemblerImpl::GenerateLoadGlobalIC() { |
| Node* context = Parameter(Descriptor::kContext); |
| 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; |
| Node* name = Parameter(Descriptor::kName); |
| @@ -1586,7 +1631,7 @@ void AccessorAssemblerImpl::GenerateLoadGlobalICTrampoline() { |
| Node* vector = LoadTypeFeedbackVectorForStub(); |
| LoadICParameters p(context, nullptr, name, slot, vector); |
| - LoadGlobalIC(&p); |
| + LoadGlobalIC(&p, typeof_mode); |
| } |
| void AccessorAssemblerImpl::GenerateKeyedLoadICTF() { |
| @@ -1696,6 +1741,24 @@ void AccessorAssemblerImpl::GenerateKeyedStoreICTrampolineTF( |
| ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE(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, |
| LanguageMode language_mode) { |
| AccessorAssemblerImpl assembler(state); |