Index: src/mips/ic-mips.cc |
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc |
index 3f2ecb88a528249c7ea95b9be067df3cb340e4ae..88fc816868257402b2402d06137e6b849b324997 100644 |
--- a/src/mips/ic-mips.cc |
+++ b/src/mips/ic-mips.cc |
@@ -1189,6 +1189,145 @@ void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
} |
+static void KeyedStoreGenerateGenericHelper( |
+ MacroAssembler* masm, |
+ Label* fast_object, |
+ Label* fast_double, |
+ Label* slow, |
+ KeyedStoreCheckMap check_map, |
+ KeyedStoreIncrementLength increment_length, |
+ Register value, |
+ Register key, |
+ Register receiver, |
+ Register receiver_map, |
+ Register elements_map, |
+ Register elements) { |
+ Label transition_smi_elements; |
+ Label finish_object_store, non_double_value, transition_double_elements; |
+ Label fast_double_without_map_check; |
+ |
+ // Fast case: Do the store, could be either Object or double. |
+ __ bind(fast_object); |
+ Register scratch_value = t0; |
+ Register address = t1; |
+ if (check_map == kCheckMap) { |
+ __ lw(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
+ __ Branch(fast_double, ne, elements_map, |
+ Operand(masm->isolate()->factory()->fixed_array_map())); |
+ } |
+ // Smi stores don't require further checks. |
+ Label non_smi_value; |
+ __ JumpIfNotSmi(value, &non_smi_value); |
+ |
+ if (increment_length == kIncrementLength) { |
+ // Add 1 to receiver->length. |
+ __ Addu(scratch_value, key, Operand(Smi::FromInt(1))); |
+ __ sw(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
+ } |
+ // It's irrelevant whether array is smi-only or not when writing a smi. |
+ __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
+ __ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize); |
+ __ Addu(address, address, scratch_value); |
+ __ sw(value, MemOperand(address)); |
+ __ Ret(); |
+ |
+ __ bind(&non_smi_value); |
+ // Escape to elements kind transition case. |
+ __ CheckFastObjectElements(receiver_map, scratch_value, |
+ &transition_smi_elements); |
+ |
+ // Fast elements array, store the value to the elements backing store. |
+ __ bind(&finish_object_store); |
+ if (increment_length == kIncrementLength) { |
+ // Add 1 to receiver->length. |
+ __ Addu(scratch_value, key, Operand(Smi::FromInt(1))); |
+ __ sw(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
+ } |
+ __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
+ __ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize); |
+ __ Addu(address, address, scratch_value); |
+ __ sw(value, MemOperand(address)); |
+ // Update write barrier for the elements array address. |
+ __ mov(scratch_value, value); // Preserve the value which is returned. |
+ __ RecordWrite(elements, |
+ address, |
+ scratch_value, |
+ kRAHasNotBeenSaved, |
+ kDontSaveFPRegs, |
+ EMIT_REMEMBERED_SET, |
+ OMIT_SMI_CHECK); |
+ __ Ret(); |
+ |
+ __ bind(fast_double); |
+ if (check_map == kCheckMap) { |
+ // Check for fast double array case. If this fails, call through to the |
+ // runtime. |
+ __ LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); |
+ __ Branch(slow, ne, elements_map, Operand(at)); |
+ } |
+ __ bind(&fast_double_without_map_check); |
+ __ StoreNumberToDoubleElements(value, |
+ key, |
+ receiver, |
+ elements, |
+ a3, |
+ t0, |
+ t1, |
+ t2, |
+ &transition_double_elements); |
+ if (increment_length == kIncrementLength) { |
+ // Add 1 to receiver->length. |
+ __ Addu(scratch_value, key, Operand(Smi::FromInt(1))); |
+ __ sw(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
+ } |
+ __ Ret(); |
+ |
+ __ bind(&transition_smi_elements); |
+ // Transition the array appropriately depending on the value type. |
+ __ lw(t0, FieldMemOperand(value, HeapObject::kMapOffset)); |
+ __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
+ __ Branch(&non_double_value, ne, t0, Operand(at)); |
+ |
+ // Value is a double. Transition FAST_SMI_ELEMENTS -> |
+ // FAST_DOUBLE_ELEMENTS and complete the store. |
+ __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, |
+ FAST_DOUBLE_ELEMENTS, |
+ receiver_map, |
+ t0, |
+ slow); |
+ ASSERT(receiver_map.is(a3)); // Transition code expects map in a3 |
+ ElementsTransitionGenerator::GenerateSmiToDouble(masm, slow); |
+ __ lw(elements, FieldMemOperand(receiver, 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, |
+ receiver_map, |
+ t0, |
+ slow); |
+ ASSERT(receiver_map.is(a3)); // Transition code expects map in a3 |
+ ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm); |
+ __ lw(elements, FieldMemOperand(receiver, 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 |
+ __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, |
+ FAST_ELEMENTS, |
+ receiver_map, |
+ t0, |
+ slow); |
+ ASSERT(receiver_map.is(a3)); // Transition code expects map in a3 |
+ ElementsTransitionGenerator::GenerateDoubleToObject(masm, slow); |
+ __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
+ __ jmp(&finish_object_store); |
+} |
+ |
+ |
void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
StrictModeFlag strict_mode) { |
// ---------- S t a t e -------------- |
@@ -1197,11 +1336,9 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
// -- a2 : receiver |
// -- ra : return address |
// ----------------------------------- |
- Label slow, array, extra, check_if_double_array; |
- Label fast_object_with_map_check, fast_object_without_map_check; |
- Label fast_double_with_map_check, fast_double_without_map_check; |
- Label transition_smi_elements, finish_object_store, non_double_value; |
- Label transition_double_elements; |
+ Label slow, fast_object, fast_object_grow; |
+ Label fast_double, fast_double_grow; |
+ Label array, extra, check_if_double_array; |
// Register usage. |
Register value = a0; |
@@ -1233,7 +1370,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
__ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
// Check array bounds. Both the key and the length of FixedArray are smis. |
__ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
- __ Branch(&fast_object_with_map_check, lo, key, Operand(t0)); |
+ __ Branch(&fast_object, lo, key, Operand(t0)); |
// Slow case, handle jump to runtime. |
__ bind(&slow); |
@@ -1258,19 +1395,11 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
__ Branch( |
&check_if_double_array, ne, elements_map, Heap::kFixedArrayMapRootIndex); |
- // Calculate key + 1 as smi. |
- STATIC_ASSERT(kSmiTag == 0); |
- __ Addu(t0, key, Operand(Smi::FromInt(1))); |
- __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
- __ Branch(&fast_object_without_map_check); |
+ __ jmp(&fast_object_grow); |
__ bind(&check_if_double_array); |
__ Branch(&slow, ne, elements_map, Heap::kFixedDoubleArrayMapRootIndex); |
- // Add 1 to key, and go to common element store code for doubles. |
- STATIC_ASSERT(kSmiTag == 0); |
- __ Addu(t0, key, Operand(Smi::FromInt(1))); |
- __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
- __ 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 |
@@ -1281,110 +1410,15 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
// Check the key against the length in the array. |
__ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
__ Branch(&extra, hs, key, Operand(t0)); |
- // Fall through to fast case. |
- |
- __ bind(&fast_object_with_map_check); |
- Register scratch_value = t0; |
- Register address = t1; |
- __ lw(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
- __ Branch(&fast_double_with_map_check, |
- ne, |
- elements_map, |
- Heap::kFixedArrayMapRootIndex); |
- __ bind(&fast_object_without_map_check); |
- // Smi stores don't require further checks. |
- Label non_smi_value; |
- __ JumpIfNotSmi(value, &non_smi_value); |
- // It's irrelevant whether array is smi-only or not when writing a smi. |
- __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
- __ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize); |
- __ Addu(address, address, scratch_value); |
- __ sw(value, MemOperand(address)); |
- __ Ret(USE_DELAY_SLOT); |
- __ mov(v0, value); |
- |
- __ bind(&non_smi_value); |
- // Escape to elements kind transition case. |
- __ CheckFastObjectElements(receiver_map, scratch_value, |
- &transition_smi_elements); |
- // Fast elements array, store the value to the elements backing store. |
- __ bind(&finish_object_store); |
- __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
- __ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize); |
- __ Addu(address, address, scratch_value); |
- __ sw(value, MemOperand(address)); |
- // Update write barrier for the elements array address. |
- __ mov(v0, value); // Preserve the value which is returned. |
- __ RecordWrite(elements, |
- address, |
- value, |
- kRAHasNotBeenSaved, |
- kDontSaveFPRegs, |
- EMIT_REMEMBERED_SET, |
- OMIT_SMI_CHECK); |
- __ Ret(); |
- __ bind(&fast_double_with_map_check); |
- // Check for fast double array case. If this fails, call through to the |
- // runtime. |
- __ Branch(&slow, ne, elements_map, Heap::kFixedDoubleArrayMapRootIndex); |
- __ bind(&fast_double_without_map_check); |
- __ StoreNumberToDoubleElements(value, |
- key, |
- receiver, |
- elements, |
- a3, |
- t0, |
- t1, |
- t2, |
- &transition_double_elements); |
- __ Ret(USE_DELAY_SLOT); |
- __ mov(v0, value); |
- |
- __ bind(&transition_smi_elements); |
- // Transition the array appropriately depending on the value type. |
- __ lw(t0, FieldMemOperand(value, HeapObject::kMapOffset)); |
- __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
- __ Branch(&non_double_value, ne, t0, Operand(at)); |
- |
- |
- // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS |
- // and complete the store. |
- __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, |
- FAST_DOUBLE_ELEMENTS, |
- receiver_map, |
- t0, |
- &slow); |
- ASSERT(receiver_map.is(a3)); // Transition code expects map in a3 |
- ElementsTransitionGenerator::GenerateSmiToDouble(masm, &slow); |
- __ lw(elements, FieldMemOperand(receiver, 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, |
- receiver_map, |
- t0, |
- &slow); |
- ASSERT(receiver_map.is(a3)); // Transition code expects map in a3 |
- ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm); |
- __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
- __ jmp(&finish_object_store); |
- |
- __ bind(&transition_double_elements); |
- // Elements are double, but value is an Object that's not a HeapNumber. Make |
- // sure that the receiver is a Array with Object elements and transition array |
- // from double elements to Object elements. |
- __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, |
- FAST_ELEMENTS, |
- receiver_map, |
- t0, |
- &slow); |
- ASSERT(receiver_map.is(a3)); // Transition code expects map in a3 |
- ElementsTransitionGenerator::GenerateDoubleToObject(masm, &slow); |
- __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
- __ jmp(&finish_object_store); |
+ KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, |
+ &slow, kCheckMap, kDontIncrementLength, |
danno
2012/10/16 08:27:48
nit: spacing. I'll fix when I land.
|
+ value, key, receiver, receiver_map, |
+ elements_map, elements); |
+ KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, |
+ &slow, kDontCheckMap, kIncrementLength, |
+ value, key, receiver, receiver_map, |
+ elements_map, elements); |
} |