Chromium Code Reviews| Index: src/code-stub-assembler.cc |
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc |
| index e67f982d652bfea6150812959c53bcf7f398b516..da3ccb2a48f71121308124d3b692a5386f96e311 100644 |
| --- a/src/code-stub-assembler.cc |
| +++ b/src/code-stub-assembler.cc |
| @@ -5530,29 +5530,108 @@ void CodeStubAssembler::HandleLoadICProtoHandler( |
| DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); |
| DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); |
| - Node* validity_cell = LoadObjectField(handler, Tuple3::kValue1Offset); |
| + // IC dispatchers rely on these assumptions to be held. |
| + STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset); |
| + DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex), |
| + LoadHandler::kSmiHandlerOffset); |
| + DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kValidityCellIndex), |
| + LoadHandler::kValidityCellOffset); |
| + |
| + // Both FixedArray and Tuple3 handlers have validity cell at the same offset. |
| + Node* validity_cell = |
| + LoadObjectField(handler, LoadHandler::kValidityCellOffset); |
| Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); |
| GotoIf(WordNotEqual(cell_value, |
| SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), |
| miss); |
| - Node* holder = |
| - LoadWeakCellValue(LoadObjectField(handler, Tuple3::kValue2Offset)); |
| - // The |holder| is guaranteed to be alive at this point since we passed |
| - // both the receiver map check and the validity cell check. |
| - CSA_ASSERT(WordNotEqual(holder, IntPtrConstant(0))); |
| - |
| - Node* smi_handler = LoadObjectField(handler, Tuple3::kValue3Offset); |
| + Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset); |
| CSA_ASSERT(TaggedIsSmi(smi_handler)); |
| - var_holder->Bind(holder); |
| - var_smi_handler->Bind(smi_handler); |
| - GotoUnless(IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>( |
| - SmiUntag(smi_handler)), |
| - if_smi_handler); |
| + Label if_negative_lookup_on_receiver(this), if_check_prototypes(this); |
| + Branch(IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>( |
| + SmiUntag(smi_handler)), |
| + &if_negative_lookup_on_receiver, &if_check_prototypes); |
| + |
| + Bind(&if_check_prototypes); |
| + |
| + Node* maybe_holder_cell = |
| + LoadObjectField(handler, LoadHandler::kHolderCellOffset); |
| + Label array_handler(this), tuple_handler(this); |
| + Branch(TaggedIsSmi(maybe_holder_cell), &array_handler, &tuple_handler); |
| + |
| + Bind(&if_negative_lookup_on_receiver); |
|
Jakob Kummerow
2016/10/27 11:30:54
nit: I'd put this above the "Bind(&if_check_protot
Igor Sheludko
2016/10/27 14:55:30
Done.
|
| + { |
| + NameDictionaryNegativeLookup(p->receiver, p->name, miss); |
| + Goto(&if_check_prototypes); |
| + } |
| + |
| + Bind(&tuple_handler); |
| + { |
| + Node* holder = LoadWeakCellValue(maybe_holder_cell); |
| + // The |holder| is guaranteed to be alive at this point since we passed |
| + // both the receiver map check and the validity cell check. |
| + CSA_ASSERT(WordNotEqual(holder, IntPtrConstant(0))); |
| + |
| + var_holder->Bind(holder); |
| + var_smi_handler->Bind(smi_handler); |
| + Goto(if_smi_handler); |
| + } |
| + |
| + Bind(&array_handler); |
| + { |
| + Node* length = SmiUntag(maybe_holder_cell); |
| + BuildFastLoop(MachineType::PointerRepresentation(), |
| + IntPtrConstant(LoadHandler::kFirstPrototypeIndex), length, |
| + [this, p, handler, miss](CodeStubAssembler*, Node* current) { |
| + Node* prototype_cell = LoadFixedArrayElement( |
| + handler, current, 0, INTPTR_PARAMETERS); |
| + CheckPrototype(prototype_cell, p->name, miss); |
| + }, |
| + 1, IndexAdvanceMode::kPost); |
| + |
| + Node* holder_cell = LoadFixedArrayElement( |
| + handler, IntPtrConstant(LoadHandler::kHolderCellIndex), 0, |
| + INTPTR_PARAMETERS); |
| + Node* holder = LoadWeakCellValue(holder_cell); |
| + // The |holder| is guaranteed to be alive at this point since we passed |
| + // the receiver map check, the validity cell check and the prototype chain |
| + // check. |
| + CSA_ASSERT(WordNotEqual(holder, IntPtrConstant(0))); |
| + |
| + var_holder->Bind(holder); |
| + var_smi_handler->Bind(smi_handler); |
| + Goto(if_smi_handler); |
| + } |
| +} |
| + |
| +void CodeStubAssembler::CheckPrototype(Node* prototype_cell, Node* name, |
| + Label* miss) { |
| + Node* maybe_prototype = LoadWeakCellValue(prototype_cell, miss); |
| + |
| + Label done(this); |
| + Label if_property_cell(this), if_dictionary_object(this); |
| + |
| + // |maybe_prototype| is either a PropertyCell or a slow-mode prototype. |
| + Branch(WordEqual(LoadMap(maybe_prototype), |
| + LoadRoot(Heap::kGlobalPropertyCellMapRootIndex)), |
| + &if_property_cell, &if_dictionary_object); |
| + |
| + Bind(&if_dictionary_object); |
| + { |
| + NameDictionaryNegativeLookup(maybe_prototype, name, miss); |
| + Goto(&done); |
| + } |
| - NameDictionaryNegativeLookup(p->receiver, p->name, miss); |
| - Goto(if_smi_handler); |
| + Bind(&if_property_cell); |
| + { |
| + // Ensure the property cell still contains the hole. |
| + Node* value = LoadObjectField(maybe_prototype, PropertyCell::kValueOffset); |
| + Branch(WordEqual(value, LoadRoot(Heap::kTheHoleValueRootIndex)), &done, |
|
Jakob Kummerow
2016/10/27 11:30:53
Is there a reason you prefer this Branch() over "G
Igor Sheludko
2016/10/27 14:55:30
Because it has to be followed by Goto(&done) anywa
|
| + miss); |
| + } |
| + |
| + Bind(&done); |
| } |
| void CodeStubAssembler::NameDictionaryNegativeLookup(Node* object, Node* name, |