Index: src/ia32/ic-ia32.cc |
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc |
index 65ecaeced037e1e2e069d6e6be92a0365de0866f..3c95356642b42a2d90c6a1ec1e9679e870bb1580 100644 |
--- a/src/ia32/ic-ia32.cc |
+++ b/src/ia32/ic-ia32.cc |
@@ -734,7 +734,9 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
// -- edx : receiver |
// -- esp[0] : return address |
// ----------------------------------- |
- Label slow, fast, array, extra; |
+ Label slow, fast_object_with_map_check, fast_object_without_map_check; |
+ Label fast_double_with_map_check, fast_double_without_map_check; |
+ Label check_if_double_array, array, extra; |
// Check that the object isn't a smi. |
__ JumpIfSmi(edx, &slow); |
@@ -761,11 +763,11 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
// eax: value |
// edx: JSObject |
// ecx: key (a smi) |
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
+ // edi: receiver map |
+ __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
// Check that the object is in fast mode and writable. |
- __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK); |
- __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
- __ j(below, &fast); |
+ __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); |
+ __ j(below, &fast_object_with_map_check); |
// Slow case: call runtime. |
__ bind(&slow); |
@@ -778,16 +780,26 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
// eax: value |
// edx: receiver, a JSArray |
// ecx: key, a smi. |
- // edi: receiver->elements, a FixedArray |
+ // ebx: receiver->elements, a FixedArray |
+ // edi: receiver map |
// flags: compare (ecx, edx.length()) |
// do not leave holes in the array: |
__ j(not_equal, &slow); |
- __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
+ __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); |
__ j(above_equal, &slow); |
- // Add 1 to receiver->length, and go to fast array write. |
+ __ CheckMap(ebx, FACTORY->fixed_array_map(), |
+ &check_if_double_array, DONT_DO_SMI_CHECK); |
+ // Add 1 to receiver->length, and go to common element store code for Objects. |
__ add(FieldOperand(edx, JSArray::kLengthOffset), |
Immediate(Smi::FromInt(1))); |
- __ jmp(&fast); |
+ __ jmp(&fast_object_without_map_check); |
+ |
+ __ bind(&check_if_double_array); |
+ __ CheckMap(ebx, FACTORY->fixed_double_array_map(), &slow, DONT_DO_SMI_CHECK); |
+ // Add 1 to receiver->length, and go to common element store code for doubles. |
+ __ add(FieldOperand(edx, JSArray::kLengthOffset), |
+ Immediate(Smi::FromInt(1))); |
+ __ jmp(&fast_double_without_map_check); |
// Array case: Get the length and the elements array from the JS |
// array. Check that the array is in fast mode (and writable); if it |
@@ -796,39 +808,59 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
// eax: value |
// edx: receiver, a JSArray |
// ecx: key, a smi. |
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
- __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK); |
+ // edi: receiver map |
+ __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
- // Check the key against the length in the array, compute the |
- // address to store into and fall through to fast case. |
+ // Check the key against the length in the array and fall through to the |
+ // common store code. |
__ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
__ j(above_equal, &extra); |
- // Fast case: Do the store. |
- __ bind(&fast); |
+ // Fast case: Do the store, could either Object or double. |
+ __ bind(&fast_object_with_map_check); |
// eax: value |
// ecx: key (a smi) |
// edx: receiver |
- // edi: FixedArray receiver->elements |
- |
+ // ebx: FixedArray receiver->elements |
+ // edi: receiver map |
+ __ CheckMap(ebx, FACTORY->fixed_array_map(), |
+ &fast_double_with_map_check, DONT_DO_SMI_CHECK); |
+ __ bind(&fast_object_without_map_check); |
+ // Smi stores don't require further checks. |
Label non_smi_value; |
__ JumpIfNotSmi(eax, &non_smi_value); |
// It's irrelevant whether array is smi-only or not when writing a smi. |
- __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); |
+ __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax); |
__ ret(0); |
__ bind(&non_smi_value); |
if (FLAG_smi_only_arrays) { |
// Escape to slow case when writing non-smi into smi-only array. |
- __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
- __ CheckFastObjectElements(ebx, &slow, Label::kNear); |
+ __ CheckFastObjectElements(edi, &slow, Label::kNear); |
} |
+ |
// Fast elements array, store the value to the elements backing store. |
- __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); |
+ __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax); |
// Update write barrier for the elements array address. |
__ mov(edx, Operand(eax)); // Preserve the value which is returned. |
__ RecordWriteArray( |
- edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
+ ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
+ __ ret(0); |
+ |
+ __ bind(&fast_double_with_map_check); |
+ // Check for fast double array case. If this fails, call through to the |
+ // runtime. |
+ __ CheckMap(ebx, FACTORY->fixed_double_array_map(), &slow, DONT_DO_SMI_CHECK); |
+ __ bind(&fast_double_without_map_check); |
+ // If the value is a number, store it as a double in the FastDoubleElements |
+ // array. |
+ __ StoreNumberToDoubleElements(eax, |
+ ebx, |
+ ecx, |
+ edx, |
+ xmm0, |
+ &slow, |
+ false); |
__ ret(0); |
} |