| Index: src/code-stub-assembler.cc
|
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
|
| index e67f982d652bfea6150812959c53bcf7f398b516..4e18e34bbaaab4a567a44bbd3eed24ba97e2ebd8 100644
|
| --- a/src/code-stub-assembler.cc
|
| +++ b/src/code-stub-assembler.cc
|
| @@ -5086,7 +5086,7 @@ void CodeStubAssembler::TryProbeStubCacheTable(
|
|
|
| DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() -
|
| stub_cache->key_reference(table).address());
|
| - Node* handler = Load(MachineType::Pointer(), key_base,
|
| + Node* handler = Load(MachineType::TaggedPointer(), key_base,
|
| IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize)));
|
|
|
| // We found the handler.
|
| @@ -5530,29 +5530,106 @@ 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);
|
|
|
| + Label check_prototypes(this);
|
| GotoUnless(IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>(
|
| SmiUntag(smi_handler)),
|
| - if_smi_handler);
|
| + &check_prototypes);
|
| + {
|
| + // We have a dictionary receiver, do a negative lookup check.
|
| + NameDictionaryNegativeLookup(p->receiver, p->name, miss);
|
| + Goto(&check_prototypes);
|
| + }
|
| +
|
| + Bind(&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(&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);
|
| + GotoIf(WordNotEqual(value, LoadRoot(Heap::kTheHoleValueRootIndex)), miss);
|
| + Goto(&done);
|
| + }
|
| +
|
| + Bind(&done);
|
| }
|
|
|
| void CodeStubAssembler::NameDictionaryNegativeLookup(Node* object, Node* name,
|
|
|