Index: src/x64/stub-cache-x64.cc |
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc |
index 14ac003747a971d4bf376aa1a35e94d44bb97666..7a05d8c98756a61edda76d806ed6ba01aa5d9d2e 100644 |
--- a/src/x64/stub-cache-x64.cc |
+++ b/src/x64/stub-cache-x64.cc |
@@ -2607,6 +2607,56 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) { |
} |
+MaybeObject* KeyedStoreStubCompiler::CompileStoreElementWithTransition( |
+ Map* transitioned_map, |
+ Map* untransitioned_map_1, |
+ Map* untransitioned_map_2) { |
+ // ----------- S t a t e ------------- |
+ // -- rax : value |
+ // -- rcx : key |
+ // -- rdx : receiver |
+ // -- rsp[0] : return address |
+ // ----------------------------------- |
+ |
+ // The order of map occurrences in the generated code below is important. |
+ // Both IC code and Crankshaft rely on |transitioned_map| being the first |
+ // map in the stub. |
+ |
+ Code* notransition_stub; |
+ ElementsKind elements_kind = transitioned_map->elements_kind(); |
+ bool is_js_array = transitioned_map->instance_type() == JS_ARRAY_TYPE; |
+ MaybeObject* maybe_stub = |
+ KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); |
+ if (!maybe_stub->To(¬ransition_stub)) return maybe_stub; |
+ |
+ Label just_store, miss; |
+ __ JumpIfSmi(rdx, &miss, Label::kNear); |
+ __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); |
+ // rbx: receiver->map(). |
+ __ Cmp(rbx, Handle<Map>(transitioned_map)); |
+ __ j(equal, &just_store); |
+ ASSERT_NE(untransitioned_map_1, NULL); |
+ __ Cmp(rbx, Handle<Map>(untransitioned_map_1)); |
+ Code* generic_stub = (strict_mode_ == kStrictMode) |
+ ? isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic_Strict) |
+ : isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic); |
+ __ j(equal, Handle<Code>(generic_stub), RelocInfo::CODE_TARGET); |
+ if (untransitioned_map_2 != NULL) { |
+ __ Cmp(rbx, Handle<Map>(untransitioned_map_2)); |
+ __ j(equal, Handle<Code>(generic_stub), RelocInfo::CODE_TARGET); |
+ } |
+ __ bind(&miss); |
+ Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
+ __ jmp(ic, RelocInfo::CODE_TARGET); |
+ |
+ __ bind(&just_store); |
+ __ jmp(Handle<Code>(notransition_stub), RelocInfo::CODE_TARGET); |
+ |
+ // Return the generated code. |
+ return GetCode(NORMAL, NULL, MEGAMORPHIC); |
+} |
+ |
+ |
MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic( |
MapList* receiver_maps, |
CodeList* handler_ics) { |
@@ -3698,7 +3748,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement( |
// -- rdx : receiver |
// -- rsp[0] : return address |
// ----------------------------------- |
- Label miss_force_generic; |
+ Label miss_force_generic, transition_elements_kind; |
// This stub is meant to be tail-jumped to, the receiver must already |
// have been verified by the caller to not be a smi. |
@@ -3721,13 +3771,13 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement( |
__ j(above_equal, &miss_force_generic); |
} |
- // Do the store and update the write barrier. |
if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
- __ JumpIfNotSmi(rax, &miss_force_generic); |
+ __ JumpIfNotSmi(rax, &transition_elements_kind); |
__ SmiToInteger32(rcx, rcx); |
__ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize), |
rax); |
} else { |
+ // Do the store and update the write barrier. |
ASSERT(elements_kind == FAST_ELEMENTS); |
__ SmiToInteger32(rcx, rcx); |
__ lea(rcx, |
@@ -3746,6 +3796,10 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement( |
Handle<Code> ic_force_generic = |
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
+ |
+ __ bind(&transition_elements_kind); |
+ Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
+ __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
} |
@@ -3758,7 +3812,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
// -- rdx : receiver |
// -- rsp[0] : return address |
// ----------------------------------- |
- Label miss_force_generic; |
+ Label miss_force_generic, transition_elements_kind; |
// This stub is meant to be tail-jumped to, the receiver must already |
// have been verified by the caller to not be a smi. |
@@ -3780,7 +3834,8 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
// Handle smi values specially |
__ SmiToInteger32(rcx, rcx); |
- __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, &miss_force_generic); |
+ __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, |
+ &transition_elements_kind); |
__ ret(0); |
// Handle store cache miss, replacing the ic with the generic stub. |
@@ -3788,6 +3843,10 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
Handle<Code> ic_force_generic = |
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
+ |
+ __ bind(&transition_elements_kind); |
+ Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
+ __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
} |