| Index: src/ia32/ic-ia32.cc
|
| diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
|
| index 52d8fa1452ef3a937409bf3242ebf0e46867d2c2..6945bc0237d92b2e758bacdd6452c0fda9eaa276 100644
|
| --- a/src/ia32/ic-ia32.cc
|
| +++ b/src/ia32/ic-ia32.cc
|
| @@ -747,6 +747,124 @@ void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| +static void KeyedStoreGenerateGenericHelper(MacroAssembler* masm,
|
| + Label* fast_object,
|
| + Label* fast_double,
|
| + Label* slow,
|
| + bool check_map,
|
| + bool increment_length) {
|
| + Label transition_smi_elements;
|
| + Label finish_object_store, non_double_value, transition_double_elements;
|
| + Label fast_double_without_map_check;
|
| + // eax: value
|
| + // ecx: key (a smi)
|
| + // edx: receiver
|
| + // ebx: FixedArray receiver->elements
|
| + // edi: receiver map
|
| + // Fast case: Do the store, could either Object or double.
|
| + __ bind(fast_object);
|
| + if (check_map) {
|
| + __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
|
| + __ cmp(edi, masm->isolate()->factory()->fixed_array_map());
|
| + __ j(not_equal, fast_double);
|
| + }
|
| + // Smi stores don't require further checks.
|
| + Label non_smi_value;
|
| + __ JumpIfNotSmi(eax, &non_smi_value);
|
| + if (increment_length) {
|
| + // Add 1 to receiver->length.
|
| + __ add(FieldOperand(edx, JSArray::kLengthOffset),
|
| + Immediate(Smi::FromInt(1)));
|
| + }
|
| + // It's irrelevant whether array is smi-only or not when writing a smi.
|
| + __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
|
| + __ ret(0);
|
| +
|
| + __ bind(&non_smi_value);
|
| + // Escape to elements kind transition case.
|
| + __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
|
| + __ CheckFastObjectElements(edi, &transition_smi_elements);
|
| +
|
| + // Fast elements array, store the value to the elements backing store.
|
| + __ bind(&finish_object_store);
|
| + if (increment_length) {
|
| + // Add 1 to receiver->length.
|
| + __ add(FieldOperand(edx, JSArray::kLengthOffset),
|
| + Immediate(Smi::FromInt(1)));
|
| + }
|
| + __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
|
| + // Update write barrier for the elements array address.
|
| + __ mov(edx, eax); // Preserve the value which is returned.
|
| + __ RecordWriteArray(
|
| + ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
| + __ ret(0);
|
| +
|
| + __ bind(fast_double);
|
| + if (check_map) {
|
| + // Check for fast double array case. If this fails, call through to the
|
| + // runtime.
|
| + __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
|
| + __ j(not_equal, slow);
|
| + // If the value is a number, store it as a double in the FastDoubleElements
|
| + // array.
|
| + }
|
| + __ bind(&fast_double_without_map_check);
|
| + __ StoreNumberToDoubleElements(eax, ebx, ecx, edi, xmm0,
|
| + &transition_double_elements, false);
|
| + if (increment_length) {
|
| + // Add 1 to receiver->length.
|
| + __ add(FieldOperand(edx, JSArray::kLengthOffset),
|
| + Immediate(Smi::FromInt(1)));
|
| + }
|
| + __ ret(0);
|
| +
|
| + __ bind(&transition_smi_elements);
|
| + __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
|
| +
|
| + // Transition the array appropriately depending on the value type.
|
| + __ CheckMap(eax,
|
| + masm->isolate()->factory()->heap_number_map(),
|
| + &non_double_value,
|
| + DONT_DO_SMI_CHECK);
|
| +
|
| + // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS
|
| + // and complete the store.
|
| + __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
|
| + FAST_DOUBLE_ELEMENTS,
|
| + ebx,
|
| + edi,
|
| + slow);
|
| + ElementsTransitionGenerator::GenerateSmiToDouble(masm, slow);
|
| + __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
|
| + __ jmp(&fast_double_without_map_check);
|
| +
|
| + __ bind(&non_double_value);
|
| + // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
|
| + __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
|
| + FAST_ELEMENTS,
|
| + ebx,
|
| + edi,
|
| + slow);
|
| + ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm);
|
| + __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
|
| + __ jmp(&finish_object_store);
|
| +
|
| + __ bind(&transition_double_elements);
|
| + // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
|
| + // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
|
| + // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
|
| + __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
|
| + __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
|
| + FAST_ELEMENTS,
|
| + ebx,
|
| + edi,
|
| + slow);
|
| + ElementsTransitionGenerator::GenerateDoubleToObject(masm, slow);
|
| + __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
|
| + __ jmp(&finish_object_store);
|
| +}
|
| +
|
| +
|
| void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
| StrictModeFlag strict_mode) {
|
| // ----------- S t a t e -------------
|
| @@ -755,10 +873,9 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
| // -- edx : receiver
|
| // -- esp[0] : return address
|
| // -----------------------------------
|
| - 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, transition_smi_elements;
|
| - Label finish_object_store, non_double_value, transition_double_elements;
|
| + Label slow, fast_object, fast_object_grow;
|
| + Label fast_double, fast_double_grow;
|
| + Label array, extra, check_if_double_array;
|
|
|
| // Check that the object isn't a smi.
|
| __ JumpIfSmi(edx, &slow);
|
| @@ -785,7 +902,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
| __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
|
| // Check array bounds. Both the key and the length of FixedArray are smis.
|
| __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
|
| - __ j(below, &fast_object_with_map_check);
|
| + __ j(below, &fast_object);
|
|
|
| // Slow case: call runtime.
|
| __ bind(&slow);
|
| @@ -808,18 +925,12 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
| __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
|
| __ cmp(edi, masm->isolate()->factory()->fixed_array_map());
|
| __ j(not_equal, &check_if_double_array);
|
| - // 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_object_without_map_check);
|
| + __ jmp(&fast_object_grow);
|
|
|
| __ bind(&check_if_double_array);
|
| __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
|
| __ j(not_equal, &slow);
|
| - // 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);
|
| + __ jmp(&fast_double_grow);
|
|
|
| // 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
|
| @@ -836,94 +947,10 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
| __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis.
|
| __ j(above_equal, &extra);
|
|
|
| - // Fast case: Do the store, could either Object or double.
|
| - __ bind(&fast_object_with_map_check);
|
| - // eax: value
|
| - // ecx: key (a smi)
|
| - // edx: receiver
|
| - // ebx: FixedArray receiver->elements
|
| - // edi: receiver map
|
| - __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
|
| - __ cmp(edi, masm->isolate()->factory()->fixed_array_map());
|
| - __ j(not_equal, &fast_double_with_map_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(ebx, ecx), eax);
|
| - __ ret(0);
|
| -
|
| - __ bind(&non_smi_value);
|
| - // Escape to elements kind transition case.
|
| - __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
|
| - __ CheckFastObjectElements(edi, &transition_smi_elements);
|
| -
|
| - // Fast elements array, store the value to the elements backing store.
|
| - __ bind(&finish_object_store);
|
| - __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
|
| - // Update write barrier for the elements array address.
|
| - __ mov(edx, eax); // Preserve the value which is returned.
|
| - __ RecordWriteArray(
|
| - 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.
|
| - __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
|
| - __ j(not_equal, &slow);
|
| - __ 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,
|
| - &transition_double_elements, false);
|
| - __ ret(0);
|
| -
|
| - __ bind(&transition_smi_elements);
|
| - __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
|
| -
|
| - // Transition the array appropriately depending on the value type.
|
| - __ CheckMap(eax,
|
| - masm->isolate()->factory()->heap_number_map(),
|
| - &non_double_value,
|
| - DONT_DO_SMI_CHECK);
|
| -
|
| - // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS
|
| - // and complete the store.
|
| - __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
|
| - FAST_DOUBLE_ELEMENTS,
|
| - ebx,
|
| - edi,
|
| - &slow);
|
| - ElementsTransitionGenerator::GenerateSmiToDouble(masm, &slow);
|
| - __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
|
| - __ jmp(&fast_double_without_map_check);
|
| -
|
| - __ bind(&non_double_value);
|
| - // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
|
| - __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
|
| - FAST_ELEMENTS,
|
| - ebx,
|
| - edi,
|
| - &slow);
|
| - ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm);
|
| - __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
|
| - __ jmp(&finish_object_store);
|
| -
|
| - __ bind(&transition_double_elements);
|
| - // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
|
| - // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
|
| - // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
|
| - __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
|
| - __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
|
| - FAST_ELEMENTS,
|
| - ebx,
|
| - edi,
|
| - &slow);
|
| - ElementsTransitionGenerator::GenerateDoubleToObject(masm, &slow);
|
| - __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
|
| - __ jmp(&finish_object_store);
|
| + KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, &slow,
|
| + true, false);
|
| + KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
|
| + &slow, false, true);
|
| }
|
|
|
|
|
|
|