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, |