Index: src/ia32/stub-cache-ia32.cc |
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc |
index 9b8f096621b5b2710f5c4f18c726e1ba0f139df4..277f97b0c8b8d74da30348325da635d8f208b3a1 100644 |
--- a/src/ia32/stub-cache-ia32.cc |
+++ b/src/ia32/stub-cache-ia32.cc |
@@ -2759,6 +2759,62 @@ 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 ------------- |
+ // -- eax : value |
+ // -- ecx : key |
+ // -- edx : receiver |
+ // -- esp[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_jsarray = transitioned_map->instance_type() == JS_ARRAY_TYPE; |
+ MaybeObject* maybe_stub = |
+ KeyedStoreElementStub(is_jsarray, elements_kind).TryGetCode(); |
+ if (!maybe_stub->To(¬ransition_stub)) return maybe_stub; |
+ |
+ Label just_store, miss; |
+ __ JumpIfSmi(edx, &miss, Label::kNear); |
+ __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
+ // ebx: receiver->map(). |
+ __ cmp(ebx, Handle<Map>(transitioned_map)); |
+ __ j(equal, &just_store); |
+ ASSERT_NE(untransitioned_map_1, NULL); |
+ __ cmp(ebx, Handle<Map>(untransitioned_map_1)); |
+ // TODO(jkummerow): When we have specialized code to do the transition, |
+ // call that code here, then jump to just_store when the call returns. |
+ // <temporary: just use the generic stub> |
+ 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)); |
+ // </temporary> |
+ if (untransitioned_map_2 != NULL) { |
+ __ cmp(ebx, Handle<Map>(untransitioned_map_2)); |
+ // <temporary: see above, same here> |
+ __ j(equal, Handle<Code>(generic_stub)); |
+ // </temporary> |
+ } |
+ __ 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) { |
@@ -3910,7 +3966,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement( |
// -- edx : receiver |
// -- esp[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. |
@@ -3935,7 +3991,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement( |
} |
if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
- __ JumpIfNotSmi(eax, &miss_force_generic); |
+ __ JumpIfNotSmi(eax, &transition_elements_kind); |
// ecx is a smi, use times_half_pointer_size instead of |
// times_pointer_size |
__ mov(FieldOperand(edi, |
@@ -3965,6 +4021,11 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement( |
Handle<Code> ic_force_generic = |
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
+ |
+ // Handle transition to other elements kinds without using the generic stub. |
+ __ bind(&transition_elements_kind); |
+ Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
+ __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
} |
@@ -3977,7 +4038,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
// -- edx : receiver |
// -- esp[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. |
@@ -4003,7 +4064,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
ecx, |
edx, |
xmm0, |
- &miss_force_generic, |
+ &transition_elements_kind, |
true); |
__ ret(0); |
@@ -4012,6 +4073,11 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
Handle<Code> ic_force_generic = |
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
+ |
+ // Handle transition to other elements kinds without using the generic stub. |
+ __ bind(&transition_elements_kind); |
+ Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
+ __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
} |