Index: src/arm/ic-arm.cc |
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc |
index 1fd70982542a2a2058c72790d0fbbc13c7ea0040..ca7cc13c65b84e5ee8a5ebda63a298ed5150462a 100644 |
--- a/src/arm/ic-arm.cc |
+++ b/src/arm/ic-arm.cc |
@@ -414,17 +414,17 @@ void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { |
// Falls through for regular JS object. |
static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, |
Register receiver, |
- Register scratch1, |
- Register scratch2, |
+ Register map, |
+ Register scratch, |
int interceptor_bit, |
Label* slow) { |
// Check that the object isn't a smi. |
__ BranchOnSmi(receiver, slow); |
// Get the map of the receiver. |
- __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
+ __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
// Check bit field. |
- __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset)); |
- __ tst(scratch2, |
+ __ ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); |
+ __ tst(scratch, |
Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); |
__ b(nz, slow); |
// Check that the object is some kind of JS object EXCEPT JS Value type. |
@@ -432,13 +432,14 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, |
// we enter the runtime system to make sure that indexing into string |
// objects work as intended. |
ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
- __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
- __ cmp(scratch1, Operand(JS_OBJECT_TYPE)); |
+ __ ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
+ __ cmp(scratch, Operand(JS_OBJECT_TYPE)); |
__ b(lt, slow); |
} |
// Loads an indexed element from a fast case array. |
+// If not_fast_array is NULL, doesn't perform the elements map check. |
static void GenerateFastArrayLoad(MacroAssembler* masm, |
Register receiver, |
Register key, |
@@ -471,11 +472,15 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, |
// scratch2 - used to hold the loaded value. |
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
- // Check that the object is in fast mode (not dictionary). |
- __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); |
- __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
- __ cmp(scratch1, ip); |
- __ b(ne, not_fast_array); |
+ if (not_fast_array != NULL) { |
+ // Check that the object is in fast mode and writable. |
+ __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); |
+ __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
+ __ cmp(scratch1, ip); |
+ __ b(ne, not_fast_array); |
+ } else { |
+ __ AssertFastElements(elements); |
+ } |
// Check that the key (index) is within bounds. |
__ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
__ cmp(key, Operand(scratch1)); |
@@ -1120,16 +1125,23 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
GenerateKeyedLoadReceiverCheck( |
masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); |
+ // Check the "has fast elements" bit in the receiver's map which is |
+ // now in r2. |
+ __ ldrb(r3, FieldMemOperand(r2, Map::kBitField2Offset)); |
+ __ tst(r3, Operand(1 << Map::kHasFastElements)); |
+ __ b(eq, &check_pixel_array); |
+ |
GenerateFastArrayLoad( |
- masm, receiver, key, r4, r3, r2, r0, &check_pixel_array, &slow); |
+ masm, receiver, key, r4, r3, r2, r0, NULL, &slow); |
__ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3); |
__ Ret(); |
// Check whether the elements is a pixel array. |
// r0: key |
- // r3: elements map |
- // r4: elements |
+ // r1: receiver |
__ bind(&check_pixel_array); |
+ __ ldr(r4, FieldMemOperand(r1, JSObject::kElementsOffset)); |
+ __ ldr(r3, FieldMemOperand(r4, HeapObject::kMapOffset)); |
__ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); |
__ cmp(r3, ip); |
__ b(ne, &check_number_dictionary); |
@@ -1690,7 +1702,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
// Object case: Check key against length in the elements array. |
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
- // Check that the object is in fast mode (not dictionary). |
+ // Check that the object is in fast mode and writable. |
__ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); |
__ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
__ cmp(r4, ip); |
@@ -1748,8 +1760,8 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
__ b(&fast); |
// Array case: Get the length and the elements array from the JS |
- // array. Check that the array is in fast mode; if it is the |
- // length is always a smi. |
+ // array. Check that the array is in fast mode (and writable); if it |
+ // is the length is always a smi. |
__ bind(&array); |
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
__ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); |
@@ -2217,6 +2229,8 @@ void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
__ b(ne, &miss); |
// Check that elements are FixedArray. |
+ // We rely on StoreIC_ArrayLength below to deal with all types of |
+ // fast elements (including COW). |
__ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
__ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE); |
__ b(ne, &miss); |