Index: src/ia32/ic-ia32.cc |
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc |
index 2cd41a15bbc42f3ed64bc17f6b6e5f889c6af506..283ae4dcbf6fe9da9e6874a063e5c4688cdb7330 100644 |
--- a/src/ia32/ic-ia32.cc |
+++ b/src/ia32/ic-ia32.cc |
@@ -452,6 +452,7 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, |
// 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, |
@@ -468,8 +469,12 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, |
// we fall through. |
__ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); |
- // Check that the object is in fast mode (not dictionary). |
- __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true); |
+ if (not_fast_array != NULL) { |
+ // Check that the object is in fast mode and writable. |
+ __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true); |
+ } else { |
+ __ AssertFastElements(scratch); |
+ } |
// Check that the key (index) is within bounds. |
__ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); |
__ j(above_equal, out_of_range); |
@@ -558,12 +563,18 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
GenerateKeyedLoadReceiverCheck( |
masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); |
+ // Check the "has fast elements" bit in the receiver's map which is |
+ // now in ecx. |
+ __ test_b(FieldOperand(ecx, Map::kBitField2Offset), |
+ 1 << Map::kHasFastElements); |
+ __ j(zero, &check_pixel_array, not_taken); |
+ |
GenerateFastArrayLoad(masm, |
edx, |
eax, |
ecx, |
eax, |
- &check_pixel_array, |
+ NULL, |
&slow); |
__ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
__ ret(0); |
@@ -572,7 +583,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
// Check whether the elements is a pixel array. |
// edx: receiver |
// eax: key |
- // ecx: elements |
+ __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
__ mov(ebx, eax); |
__ SmiUntag(ebx); |
__ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); |
@@ -967,7 +978,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
// edx: JSObject |
// ecx: key (a smi) |
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
- // Check that the object is in fast mode (not dictionary). |
+ // Check that the object is in fast mode and writable. |
__ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); |
__ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
__ j(below, &fast, taken); |
@@ -1023,8 +1034,8 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
__ jmp(&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); |
// eax: value |
// edx: receiver, a JSArray |
@@ -1872,6 +1883,8 @@ void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
__ j(not_equal, &miss, not_taken); |
// Check that elements are FixedArray. |
+ // We rely on StoreIC_ArrayLength below to deal with all types of |
+ // fast elements (including COW). |
__ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); |
__ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); |
__ j(not_equal, &miss, not_taken); |