Index: src/code-stub-assembler.cc |
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc |
index a72e267f391581a840defb56e0dfe7e5b25a3dc7..6672b15728ffb55be1a26e54ebad3e357d7114a1 100644 |
--- a/src/code-stub-assembler.cc |
+++ b/src/code-stub-assembler.cc |
@@ -4543,11 +4543,11 @@ void CodeStubAssembler::TryProbeStubCacheTable( |
DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() - |
stub_cache->key_reference(table).address()); |
- Node* code = Load(MachineType::Pointer(), key_base, |
- IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))); |
+ Node* handler = Load(MachineType::Pointer(), key_base, |
+ IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))); |
// We found the handler. |
- var_handler->Bind(code); |
+ var_handler->Bind(handler); |
Goto(if_handler); |
} |
@@ -4833,16 +4833,26 @@ void CodeStubAssembler::HandleLoadICHandlerCase( |
const LoadICParameters* p, Node* handler, Label* miss, |
ElementSupport support_elements) { |
Comment("have_handler"); |
- Label call_handler(this); |
- GotoUnless(TaggedIsSmi(handler), &call_handler); |
+ Variable var_holder(this, MachineRepresentation::kTagged); |
+ var_holder.Bind(p->receiver); |
+ Variable var_smi_handler(this, MachineRepresentation::kTagged); |
+ var_smi_handler.Bind(handler); |
+ |
+ Variable* vars[] = {&var_holder, &var_smi_handler}; |
+ Label if_smi_handler(this, 2, vars); |
+ Label try_proto_cell_handler(this), call_handler(this); |
+ |
+ Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_cell_handler); |
// |handler| is a Smi, encoding what to do. See handler-configuration.h |
// for the encoding format. |
+ Bind(&if_smi_handler); |
{ |
Variable var_double_value(this, MachineRepresentation::kFloat64); |
Label rebox_double(this, &var_double_value); |
- Node* handler_word = SmiUntag(handler); |
+ Node* holder = var_holder.value(); |
+ Node* handler_word = SmiUntag(var_smi_handler.value()); |
if (support_elements == kSupportElements) { |
Label property(this); |
Node* handler_type = |
@@ -4853,14 +4863,14 @@ void CodeStubAssembler::HandleLoadICHandlerCase( |
Comment("element_load"); |
Node* intptr_index = TryToIntptr(p->name, miss); |
- Node* elements = LoadElements(p->receiver); |
+ Node* elements = LoadElements(holder); |
Node* is_jsarray = |
WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); |
Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0)); |
Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word); |
Label if_hole(this), unimplemented_elements_kind(this); |
Label* out_of_bounds = miss; |
- EmitElementLoad(p->receiver, elements, elements_kind, intptr_index, |
+ EmitElementLoad(holder, elements, elements_kind, intptr_index, |
is_jsarray_condition, &if_hole, &rebox_double, |
&var_double_value, &unimplemented_elements_kind, |
out_of_bounds, miss); |
@@ -4907,20 +4917,20 @@ void CodeStubAssembler::HandleLoadICHandlerCase( |
GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object); |
GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double); |
- Return(LoadObjectField(p->receiver, offset)); |
+ Return(LoadObjectField(holder, offset)); |
Bind(&inobject_double); |
if (FLAG_unbox_double_fields) { |
var_double_value.Bind( |
- LoadObjectField(p->receiver, offset, MachineType::Float64())); |
+ LoadObjectField(holder, offset, MachineType::Float64())); |
} else { |
- Node* mutable_heap_number = LoadObjectField(p->receiver, offset); |
+ Node* mutable_heap_number = LoadObjectField(holder, offset); |
var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); |
} |
Goto(&rebox_double); |
Bind(&out_of_object); |
- Node* properties = LoadProperties(p->receiver); |
+ Node* properties = LoadProperties(holder); |
Node* value = LoadObjectField(properties, offset); |
GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &out_of_object_double); |
Return(value); |
@@ -4933,14 +4943,40 @@ void CodeStubAssembler::HandleLoadICHandlerCase( |
Return(AllocateHeapNumberWithValue(var_double_value.value())); |
} |
+ Bind(&try_proto_cell_handler); |
+ { |
+ GotoIf(WordNotEqual(LoadMap(handler), LoadRoot(Heap::kTuple3MapRootIndex)), |
+ &call_handler); |
+ Node* validity_cell = LoadObjectField(handler, Tuple3::kValue1Offset); |
+ 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. |
+ Assert(WordNotEqual(holder, IntPtrConstant(0))); |
+ |
+ Node* smi_handler = LoadObjectField(handler, Tuple3::kValue3Offset); |
+ Assert(TaggedIsSmi(smi_handler)); |
+ |
+ var_holder.Bind(holder); |
+ var_smi_handler.Bind(smi_handler); |
+ Goto(&if_smi_handler); |
+ } |
+ |
// |handler| is a heap object. Must be code, call it. |
Bind(&call_handler); |
- typedef LoadWithVectorDescriptor Descriptor; |
- TailCallStub(Descriptor(isolate()), handler, p->context, |
- Arg(Descriptor::kReceiver, p->receiver), |
- Arg(Descriptor::kName, p->name), |
- Arg(Descriptor::kSlot, p->slot), |
- Arg(Descriptor::kVector, p->vector)); |
+ { |
+ typedef LoadWithVectorDescriptor Descriptor; |
+ TailCallStub(Descriptor(isolate()), handler, p->context, |
+ Arg(Descriptor::kReceiver, p->receiver), |
+ Arg(Descriptor::kName, p->name), |
+ Arg(Descriptor::kSlot, p->slot), |
+ Arg(Descriptor::kVector, p->vector)); |
+ } |
} |
void CodeStubAssembler::LoadIC(const LoadICParameters* p) { |