| Index: src/ic/accessor-assembler.cc
|
| diff --git a/src/ic/accessor-assembler.cc b/src/ic/accessor-assembler.cc
|
| index d3379ab6d26f2d4713b1d338f7ddab0defce36ef..56da24790cf1b1c537d44a5424131528d1fe9d15 100644
|
| --- a/src/ic/accessor-assembler.cc
|
| +++ b/src/ic/accessor-assembler.cc
|
| @@ -1194,7 +1194,8 @@ void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map,
|
| void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
|
| Node* instance_type, Node* key,
|
| const LoadICParameters* p,
|
| - Label* slow) {
|
| + Label* slow,
|
| + UseStubCache use_stub_cache) {
|
| Comment("key is unique name");
|
| Label if_found_on_receiver(this), if_property_dictionary(this),
|
| lookup_prototype_chain(this);
|
| @@ -1220,8 +1221,10 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
|
|
|
| Label if_descriptor_found(this), stub_cache(this);
|
| Variable var_name_index(this, MachineType::PointerRepresentation());
|
| + Label* notfound =
|
| + use_stub_cache == kUseStubCache ? &stub_cache : &lookup_prototype_chain;
|
| DescriptorLookup(key, descriptors, bitfield3, &if_descriptor_found,
|
| - &var_name_index, &stub_cache);
|
| + &var_name_index, notfound);
|
|
|
| Bind(&if_descriptor_found);
|
| {
|
| @@ -1231,8 +1234,8 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
|
| Goto(&if_found_on_receiver);
|
| }
|
|
|
| - Bind(&stub_cache);
|
| - {
|
| + if (use_stub_cache == kUseStubCache) {
|
| + Bind(&stub_cache);
|
| Comment("stub cache probe for fast property load");
|
| Variable var_handler(this, MachineRepresentation::kTagged);
|
| Label found_handler(this, &var_handler), stub_cache_miss(this);
|
| @@ -1452,6 +1455,7 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) {
|
| // TODO(ishell): defer blocks when it works.
|
| Label if_handler(this, &var_handler), try_polymorphic(this),
|
| try_megamorphic(this /*, Label::kDeferred*/),
|
| + try_uninitialized(this /*, Label::kDeferred*/),
|
| miss(this /*, Label::kDeferred*/);
|
|
|
| Node* receiver_map = LoadReceiverMap(p->receiver);
|
| @@ -1478,13 +1482,77 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) {
|
| {
|
| // Check megamorphic case.
|
| GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
|
| - &miss);
|
| + &try_uninitialized);
|
|
|
| TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name,
|
| &if_handler, &var_handler, &miss);
|
| }
|
| + Bind(&try_uninitialized);
|
| + {
|
| + // Check uninitialized case.
|
| + GotoIfNot(
|
| + WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
|
| + &miss);
|
| + TailCallStub(CodeFactory::LoadIC_Uninitialized(isolate()), p->context,
|
| + p->receiver, p->name, p->slot, p->vector);
|
| + }
|
| + Bind(&miss);
|
| + {
|
| + TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name,
|
| + p->slot, p->vector);
|
| + }
|
| +}
|
| +
|
| +void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) {
|
| + Label miss(this);
|
| + Node* receiver = p->receiver;
|
| + GotoIf(TaggedIsSmi(receiver), &miss);
|
| + Node* receiver_map = LoadMap(receiver);
|
| + Node* instance_type = LoadMapInstanceType(receiver_map);
|
| +
|
| + // Optimistically write the state transition to the vector.
|
| + StoreFixedArrayElement(p->vector, p->slot,
|
| + LoadRoot(Heap::kpremonomorphic_symbolRootIndex),
|
| + SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
|
| +
|
| + Label not_function_prototype(this);
|
| + GotoIf(Word32NotEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)),
|
| + ¬_function_prototype);
|
| + GotoIfNot(WordEqual(p->name, LoadRoot(Heap::kprototype_stringRootIndex)),
|
| + ¬_function_prototype);
|
| + Node* bit_field = LoadMapBitField(receiver_map);
|
| + GotoIf(IsSetWord32(bit_field, 1 << Map::kHasNonInstancePrototype),
|
| + ¬_function_prototype);
|
| + // Function.prototype load.
|
| + {
|
| + // TODO(jkummerow): Unify with LoadIC_FunctionPrototype builtin
|
| + // (when we have a shared CSA base class for all builtins).
|
| + Node* proto_or_map =
|
| + LoadObjectField(receiver, JSFunction::kPrototypeOrInitialMapOffset);
|
| + GotoIf(IsTheHole(proto_or_map), &miss);
|
| +
|
| + Variable var_result(this, MachineRepresentation::kTagged, proto_or_map);
|
| + Label done(this, &var_result);
|
| + GotoIfNot(IsMap(proto_or_map), &done);
|
| +
|
| + var_result.Bind(LoadMapPrototype(proto_or_map));
|
| + Goto(&done);
|
| +
|
| + Bind(&done);
|
| + Return(var_result.value());
|
| + }
|
| + Bind(¬_function_prototype);
|
| +
|
| + GenericPropertyLoad(receiver, receiver_map, instance_type, p->name, p, &miss,
|
| + kDontUseStubCache);
|
| +
|
| Bind(&miss);
|
| {
|
| + // Undo the optimistic state transition.
|
| + StoreFixedArrayElement(p->vector, p->slot,
|
| + LoadRoot(Heap::kuninitialized_symbolRootIndex),
|
| + SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
|
| +
|
| TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name,
|
| p->slot, p->vector);
|
| }
|
| @@ -1856,6 +1924,19 @@ void AccessorAssembler::GenerateLoadIC() {
|
| LoadIC(&p);
|
| }
|
|
|
| +void AccessorAssembler::GenerateLoadIC_Uninitialized() {
|
| + typedef LoadWithVectorDescriptor Descriptor;
|
| +
|
| + Node* receiver = Parameter(Descriptor::kReceiver);
|
| + Node* name = Parameter(Descriptor::kName);
|
| + Node* slot = Parameter(Descriptor::kSlot);
|
| + Node* vector = Parameter(Descriptor::kVector);
|
| + Node* context = Parameter(Descriptor::kContext);
|
| +
|
| + LoadICParameters p(context, receiver, name, slot, vector);
|
| + LoadIC_Uninitialized(&p);
|
| +}
|
| +
|
| void AccessorAssembler::GenerateLoadICTrampoline() {
|
| typedef LoadDescriptor Descriptor;
|
|
|
|
|