Chromium Code Reviews| 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); |
| } |