Index: src/mips/ic-mips.cc |
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc |
index f494590c2626752bb7e1eb472b0e32c247ae0d9e..2efbd18713e0ba24d74ed5fe85577f414f761fe1 100644 |
--- a/src/mips/ic-mips.cc |
+++ b/src/mips/ic-mips.cc |
@@ -1205,116 +1205,144 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
// -- a2 : receiver |
// -- ra : return address |
// ----------------------------------- |
- |
- Label slow, fast, array, extra, exit; |
+ 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; |
// Register usage. |
Register value = a0; |
Register key = a1; |
Register receiver = a2; |
Register elements = a3; // Elements array of the receiver. |
- // t0 is used as ip in the arm version. |
- // t3-t4 are used as temporaries. |
+ Register elements_map = t2; |
+ Register receiver_map = t3; |
+ // t0 and t1 are used as general scratch registers. |
// Check that the key is a smi. |
__ JumpIfNotSmi(key, &slow); |
// Check that the object isn't a smi. |
__ JumpIfSmi(receiver, &slow); |
- |
// Get the map of the object. |
- __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
+ __ lw(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
// Check that the receiver does not require access checks. We need |
// to do this because this generic stub does not perform map checks. |
- __ lbu(t0, FieldMemOperand(t3, Map::kBitFieldOffset)); |
+ __ lbu(t0, FieldMemOperand(receiver_map, Map::kBitFieldOffset)); |
__ And(t0, t0, Operand(1 << Map::kIsAccessCheckNeeded)); |
__ Branch(&slow, ne, t0, Operand(zero_reg)); |
// Check if the object is a JS array or not. |
- __ lbu(t3, FieldMemOperand(t3, Map::kInstanceTypeOffset)); |
- |
- __ Branch(&array, eq, t3, Operand(JS_ARRAY_TYPE)); |
+ __ lbu(t0, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset)); |
+ __ Branch(&array, eq, t0, Operand(JS_ARRAY_TYPE)); |
// Check that the object is some kind of JSObject. |
- __ Branch(&slow, lt, t3, Operand(FIRST_JS_RECEIVER_TYPE)); |
- __ Branch(&slow, eq, t3, Operand(JS_PROXY_TYPE)); |
- __ Branch(&slow, eq, t3, Operand(JS_FUNCTION_PROXY_TYPE)); |
+ __ Branch(&slow, lt, t0, Operand(FIRST_JS_OBJECT_TYPE)); |
// Object case: Check key against length in the elements array. |
__ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
- // Check that the object is in fast mode and writable. |
- __ lw(t3, FieldMemOperand(elements, HeapObject::kMapOffset)); |
- __ LoadRoot(t0, Heap::kFixedArrayMapRootIndex); |
- __ Branch(&slow, ne, t3, Operand(t0)); |
// Check array bounds. Both the key and the length of FixedArray are smis. |
__ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
- __ Branch(&fast, lo, key, Operand(t0)); |
- // Fall thru to slow if un-tagged index >= length. |
+ __ Branch(&fast_object_with_map_check, lo, key, Operand(t0)); |
// Slow case, handle jump to runtime. |
__ bind(&slow); |
- |
// Entry registers are intact. |
// a0: value. |
// a1: key. |
// a2: receiver. |
- |
GenerateRuntimeSetProperty(masm, strict_mode); |
// Extra capacity case: Check if there is extra capacity to |
// perform the store and update the length. Used for adding one |
// element to the array by writing to array[array.length]. |
- |
__ bind(&extra); |
- // Only support writing to array[array.length]. |
+ // Condition code from comparing key and array length is still available. |
+ // Only support writing to writing to array[array.length]. |
__ Branch(&slow, ne, key, Operand(t0)); |
// Check for room in the elements backing store. |
// Both the key and the length of FixedArray are smis. |
__ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
__ Branch(&slow, hs, key, Operand(t0)); |
+ __ lw(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
+ __ Branch(&check_if_double_array, ne, elements_map, |
+ Operand(masm->isolate()->factory()->fixed_array_map())); |
// Calculate key + 1 as smi. |
- STATIC_ASSERT(0 == kSmiTag); |
- __ Addu(t3, key, Operand(Smi::FromInt(1))); |
- __ sw(t3, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
- __ Branch(&fast); |
- |
+ STATIC_ASSERT(kSmiTag == 0); |
+ __ Addu(t0, key, Operand(Smi::FromInt(1))); |
+ __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
+ __ Branch(&fast_object_without_map_check); |
+ |
+ __ bind(&check_if_double_array); |
+ __ Branch(&slow, ne, elements_map, |
+ Operand(masm->isolate()->factory()->fixed_double_array_map())); |
+ // 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); |
// 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 |
// is the length is always a smi. |
- |
__ bind(&array); |
__ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
- __ lw(t3, FieldMemOperand(elements, HeapObject::kMapOffset)); |
- __ LoadRoot(t0, Heap::kFixedArrayMapRootIndex); |
- __ Branch(&slow, ne, t3, Operand(t0)); |
// 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); |
+ __ bind(&fast_object_with_map_check); |
Register scratch_value = t0; |
Register address = t1; |
- // Fast case, store the value to the elements backing store. |
+ __ lw(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
+ __ Branch(&fast_double_with_map_check, ne, elements_map, |
+ Operand(masm->isolate()->factory()->fixed_array_map())); |
+ __ 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)); |
- // Skip write barrier if the written value is a smi. |
- __ JumpIfSmi(value, &exit); |
+ __ Ret(USE_DELAY_SLOT); |
+ __ mov(v0, value); |
+ __ bind(&non_smi_value); |
+ // Escape to slow case when writing non-smi into smi-only array. |
+ __ CheckFastObjectElements(receiver_map, scratch_value, &slow); |
+ // Fast elements array, store the value to the elements backing 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(scratch_value, value); // Preserve the value which is returned. |
+ __ mov(v0, value); // Preserve the value which is returned. |
__ RecordWrite(elements, |
address, |
- scratch_value, |
+ value, |
kRAHasNotBeenSaved, |
kDontSaveFPRegs, |
EMIT_REMEMBERED_SET, |
OMIT_SMI_CHECK); |
- __ bind(&exit); |
- |
- __ mov(v0, a0); // Return the value written. |
__ 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, |
+ Operand(masm->isolate()->factory()->fixed_double_array_map())); |
+ __ bind(&fast_double_without_map_check); |
+ __ StoreNumberToDoubleElements(value, |
+ key, |
+ receiver, |
+ elements, |
+ t0, |
+ t1, |
+ t2, |
+ t3, |
+ &slow); |
+ __ Ret(USE_DELAY_SLOT); |
+ __ mov(v0, value); |
} |