Chromium Code Reviews| Index: src/code-stub-assembler.cc |
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc |
| index e44e52f428419b0f46d7541ae56978ac10ff0aee..1bb1493ea809ed483f18620e57fa4bd5ecbfe680 100644 |
| --- a/src/code-stub-assembler.cc |
| +++ b/src/code-stub-assembler.cc |
| @@ -4728,6 +4728,47 @@ void CodeStubAssembler::HandlePolymorphicCase( |
| } |
| } |
| +void CodeStubAssembler::HandleKeyedStorePolymorphicCase( |
|
Jakob Kummerow
2016/10/18 19:11:11
This is a more complex version of the method above
Igor Sheludko
2016/10/18 21:12:20
I think it's fine to keep them separate.
|
| + compiler::Node* receiver_map, compiler::Node* feedback, Label* if_handler, |
| + Variable* var_handler, Label* if_transition_handler, |
| + Variable* var_transition_map_cell, Label* if_miss) { |
| + DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
|
Igor Sheludko
2016/10/18 21:12:20
Please add the same check for var_transition_map_c
Jakob Kummerow
2016/10/19 09:14:45
Done.
|
| + |
| + const int kEntrySize = 3; |
| + |
| + Variable var_index(this, MachineType::PointerRepresentation()); |
| + Label loop(this, &var_index); |
| + var_index.Bind(IntPtrConstant(0)); |
| + Node* length = LoadAndUntagFixedArrayBaseLength(feedback); |
| + Goto(&loop); |
|
Igor Sheludko
2016/10/18 21:12:20
Consider using BuildFastLoop() machinery.
Jakob Kummerow
2016/10/19 09:14:45
In a follow-up CL, as discussed.
|
| + Bind(&loop); |
| + { |
| + Node* index = var_index.value(); |
| + GotoIf(UintPtrGreaterThanOrEqual(index, length), if_miss); |
| + |
| + Node* cached_map = LoadWeakCellValue( |
| + LoadFixedArrayElement(feedback, index, 0, INTPTR_PARAMETERS)); |
| + |
| + Label next_entry(this); |
| + GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
| + |
| + Node* maybe_transition_map_cell = |
| + LoadFixedArrayElement(feedback, index, kPointerSize, INTPTR_PARAMETERS); |
| + |
| + var_handler->Bind(LoadFixedArrayElement(feedback, index, 2 * kPointerSize, |
| + INTPTR_PARAMETERS)); |
| + GotoIf(WordEqual(maybe_transition_map_cell, |
| + LoadRoot(Heap::kUndefinedValueRootIndex)), |
| + if_handler); |
| + var_transition_map_cell->Bind(maybe_transition_map_cell); |
| + Goto(if_transition_handler); |
| + |
| + Bind(&next_entry); |
| + var_index.Bind(IntPtrAdd(index, IntPtrConstant(kEntrySize))); |
| + Goto(&loop); |
| + } |
| +} |
| + |
| compiler::Node* CodeStubAssembler::StubCachePrimaryOffset(compiler::Node* name, |
| compiler::Node* map) { |
| // See v8::internal::StubCache::PrimaryOffset(). |
| @@ -5569,6 +5610,85 @@ void CodeStubAssembler::StoreIC(const StoreICParameters* p) { |
| } |
| } |
| +void CodeStubAssembler::KeyedStoreIC(const StoreICParameters* p, |
| + LanguageMode language_mode) { |
| + Variable var_handler(this, MachineRepresentation::kTagged); |
| + // TODO(ishell): defer blocks when it works. |
| + Label if_handler(this, &var_handler), try_polymorphic(this), |
| + try_megamorphic(this /*, Label::kDeferred*/), |
| + try_polymorphic_name(this /*, Label::kDeferred*/), |
| + miss(this /*, Label::kDeferred*/); |
| + |
| + Node* receiver_map = LoadReceiverMap(p->receiver); |
| + |
| + // Check monomorphic case. |
| + Node* feedback = |
| + TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| + &var_handler, &try_polymorphic); |
| + Bind(&if_handler); |
| + { |
| + Comment("KeyedStoreIC_if_handler"); |
| + StoreWithVectorDescriptor descriptor(isolate()); |
| + TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, |
| + p->name, p->value, p->slot, p->vector); |
| + } |
| + |
| + Bind(&try_polymorphic); |
| + { |
| + // CheckPolymorphic case. |
| + Comment("KeyedStoreIC_try_polymorphic"); |
| + GotoUnless( |
| + WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
| + &try_megamorphic); |
| + Label if_transition_call(this); |
|
Igor Sheludko
2016/10/18 21:12:20
Probably if_transition_handler is a better name.
Jakob Kummerow
2016/10/19 09:14:45
Done. (Agreed -- "_call" was a legacy name from ha
|
| + Variable var_transition_map_cell(this, MachineRepresentation::kTagged); |
| + HandleKeyedStorePolymorphicCase(receiver_map, feedback, &if_handler, |
| + &var_handler, &if_transition_call, |
| + &var_transition_map_cell, &miss); |
| + Bind(&if_transition_call); |
| + Comment("KeyedStoreIC_polymorphic_transition"); |
| + Node* transition_map = |
| + LoadWeakCellValue(var_transition_map_cell.value(), &miss); |
| + StoreTransitionDescriptor descriptor(isolate()); |
| + TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, |
| + p->name, transition_map, p->value, p->slot, p->vector); |
| + } |
| + |
| + Bind(&try_megamorphic); |
| + { |
| + // Check megamorphic case. |
| + Comment("KeyedStoreIC_try_megamorphic"); |
| + GotoUnless( |
| + WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
| + &try_polymorphic_name); |
| + TailCallStub( |
| + CodeFactory::KeyedStoreIC_Megamorphic(isolate(), language_mode), |
| + p->context, p->receiver, p->name, p->value, p->slot, p->vector); |
| + } |
| + |
| + Bind(&try_polymorphic_name); |
| + { |
| + // We might ahve a name in feedback, and a fixed array in the next slot. |
|
Igor Sheludko
2016/10/18 21:12:20
s/ahve/have/
Jakob Kummerow
2016/10/19 09:14:45
Done.
|
| + Comment("KeyedStoreIC_try_polymorphic_name"); |
| + GotoUnless(WordEqual(feedback, p->name), &miss); |
| + // If the name comparison succeeded, we know we have a FixedArray with |
| + // at least one map/handler pair. |
| + Node* offset = ElementOffsetFromIndex( |
| + p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS, |
| + FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag); |
| + Node* array = Load(MachineType::AnyTagged(), p->vector, offset); |
| + HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss, |
| + 1); |
| + } |
| + |
| + Bind(&miss); |
| + { |
| + Comment("KeyedStoreIC_miss"); |
| + TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, |
| + p->vector, p->receiver, p->name); |
| + } |
| +} |
| + |
| void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) { |
| Label try_handler(this), miss(this); |
| Node* weak_cell = |