| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss); | 407 StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss); |
| 408 __ bind(&miss); | 408 __ bind(&miss); |
| 409 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 409 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 410 } | 410 } |
| 411 | 411 |
| 412 | 412 |
| 413 // Checks the receiver for special cases (value type, slow case bits). | 413 // Checks the receiver for special cases (value type, slow case bits). |
| 414 // Falls through for regular JS object. | 414 // Falls through for regular JS object. |
| 415 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, | 415 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, |
| 416 Register receiver, | 416 Register receiver, |
| 417 Register scratch1, | 417 Register map, |
| 418 Register scratch2, | 418 Register scratch, |
| 419 int interceptor_bit, | 419 int interceptor_bit, |
| 420 Label* slow) { | 420 Label* slow) { |
| 421 // Check that the object isn't a smi. | 421 // Check that the object isn't a smi. |
| 422 __ BranchOnSmi(receiver, slow); | 422 __ BranchOnSmi(receiver, slow); |
| 423 // Get the map of the receiver. | 423 // Get the map of the receiver. |
| 424 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 424 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 425 // Check bit field. | 425 // Check bit field. |
| 426 __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset)); | 426 __ ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 427 __ tst(scratch2, | 427 __ tst(scratch, |
| 428 Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); | 428 Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); |
| 429 __ b(nz, slow); | 429 __ b(nz, slow); |
| 430 // Check that the object is some kind of JS object EXCEPT JS Value type. | 430 // Check that the object is some kind of JS object EXCEPT JS Value type. |
| 431 // In the case that the object is a value-wrapper object, | 431 // In the case that the object is a value-wrapper object, |
| 432 // we enter the runtime system to make sure that indexing into string | 432 // we enter the runtime system to make sure that indexing into string |
| 433 // objects work as intended. | 433 // objects work as intended. |
| 434 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 434 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
| 435 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 435 __ ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 436 __ cmp(scratch1, Operand(JS_OBJECT_TYPE)); | 436 __ cmp(scratch, Operand(JS_OBJECT_TYPE)); |
| 437 __ b(lt, slow); | 437 __ b(lt, slow); |
| 438 } | 438 } |
| 439 | 439 |
| 440 | 440 |
| 441 // Loads an indexed element from a fast case array. | 441 // Loads an indexed element from a fast case array. |
| 442 // If not_fast_array is NULL, doesn't perform the elements map check. |
| 442 static void GenerateFastArrayLoad(MacroAssembler* masm, | 443 static void GenerateFastArrayLoad(MacroAssembler* masm, |
| 443 Register receiver, | 444 Register receiver, |
| 444 Register key, | 445 Register key, |
| 445 Register elements, | 446 Register elements, |
| 446 Register scratch1, | 447 Register scratch1, |
| 447 Register scratch2, | 448 Register scratch2, |
| 448 Register result, | 449 Register result, |
| 449 Label* not_fast_array, | 450 Label* not_fast_array, |
| 450 Label* out_of_range) { | 451 Label* out_of_range) { |
| 451 // Register use: | 452 // Register use: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 464 // used by further computation. | 465 // used by further computation. |
| 465 // | 466 // |
| 466 // Scratch registers: | 467 // Scratch registers: |
| 467 // | 468 // |
| 468 // scratch1 - used to hold elements map and elements length. | 469 // scratch1 - used to hold elements map and elements length. |
| 469 // Holds the elements map if not_fast_array branch is taken. | 470 // Holds the elements map if not_fast_array branch is taken. |
| 470 // | 471 // |
| 471 // scratch2 - used to hold the loaded value. | 472 // scratch2 - used to hold the loaded value. |
| 472 | 473 |
| 473 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 474 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 474 // Check that the object is in fast mode (not dictionary). | 475 if (not_fast_array != NULL) { |
| 475 __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); | 476 // Check that the object is in fast mode and writable. |
| 476 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 477 __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); |
| 477 __ cmp(scratch1, ip); | 478 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 478 __ b(ne, not_fast_array); | 479 __ cmp(scratch1, ip); |
| 480 __ b(ne, not_fast_array); |
| 481 } else { |
| 482 __ AssertFastElements(elements); |
| 483 } |
| 479 // Check that the key (index) is within bounds. | 484 // Check that the key (index) is within bounds. |
| 480 __ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 485 __ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 481 __ cmp(key, Operand(scratch1)); | 486 __ cmp(key, Operand(scratch1)); |
| 482 __ b(hs, out_of_range); | 487 __ b(hs, out_of_range); |
| 483 // Fast case: Do the load. | 488 // Fast case: Do the load. |
| 484 __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 489 __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 485 // The key is a smi. | 490 // The key is a smi. |
| 486 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | 491 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 487 __ ldr(scratch2, | 492 __ ldr(scratch2, |
| 488 MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize)); | 493 MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1113 | 1118 |
| 1114 // Check that the key is a smi. | 1119 // Check that the key is a smi. |
| 1115 __ BranchOnNotSmi(key, &check_string); | 1120 __ BranchOnNotSmi(key, &check_string); |
| 1116 __ bind(&index_smi); | 1121 __ bind(&index_smi); |
| 1117 // Now the key is known to be a smi. This place is also jumped to from below | 1122 // Now the key is known to be a smi. This place is also jumped to from below |
| 1118 // where a numeric string is converted to a smi. | 1123 // where a numeric string is converted to a smi. |
| 1119 | 1124 |
| 1120 GenerateKeyedLoadReceiverCheck( | 1125 GenerateKeyedLoadReceiverCheck( |
| 1121 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); | 1126 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); |
| 1122 | 1127 |
| 1128 // Check the "has fast elements" bit in the receiver's map which is |
| 1129 // now in r2. |
| 1130 __ ldrb(r3, FieldMemOperand(r2, Map::kBitField2Offset)); |
| 1131 __ tst(r3, Operand(1 << Map::kHasFastElements)); |
| 1132 __ b(eq, &check_pixel_array); |
| 1133 |
| 1123 GenerateFastArrayLoad( | 1134 GenerateFastArrayLoad( |
| 1124 masm, receiver, key, r4, r3, r2, r0, &check_pixel_array, &slow); | 1135 masm, receiver, key, r4, r3, r2, r0, NULL, &slow); |
| 1125 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3); | 1136 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3); |
| 1126 __ Ret(); | 1137 __ Ret(); |
| 1127 | 1138 |
| 1128 // Check whether the elements is a pixel array. | 1139 // Check whether the elements is a pixel array. |
| 1129 // r0: key | 1140 // r0: key |
| 1130 // r3: elements map | 1141 // r1: receiver |
| 1131 // r4: elements | |
| 1132 __ bind(&check_pixel_array); | 1142 __ bind(&check_pixel_array); |
| 1143 __ ldr(r4, FieldMemOperand(r1, JSObject::kElementsOffset)); |
| 1144 __ ldr(r3, FieldMemOperand(r4, HeapObject::kMapOffset)); |
| 1133 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); | 1145 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); |
| 1134 __ cmp(r3, ip); | 1146 __ cmp(r3, ip); |
| 1135 __ b(ne, &check_number_dictionary); | 1147 __ b(ne, &check_number_dictionary); |
| 1136 __ ldr(ip, FieldMemOperand(r4, PixelArray::kLengthOffset)); | 1148 __ ldr(ip, FieldMemOperand(r4, PixelArray::kLengthOffset)); |
| 1137 __ mov(r2, Operand(key, ASR, kSmiTagSize)); | 1149 __ mov(r2, Operand(key, ASR, kSmiTagSize)); |
| 1138 __ cmp(r2, ip); | 1150 __ cmp(r2, ip); |
| 1139 __ b(hs, &slow); | 1151 __ b(hs, &slow); |
| 1140 __ ldr(ip, FieldMemOperand(r4, PixelArray::kExternalPointerOffset)); | 1152 __ ldr(ip, FieldMemOperand(r4, PixelArray::kExternalPointerOffset)); |
| 1141 __ ldrb(r2, MemOperand(ip, r2)); | 1153 __ ldrb(r2, MemOperand(ip, r2)); |
| 1142 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); // Tag result as smi. | 1154 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); // Tag result as smi. |
| (...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1683 // Check if the object is a JS array or not. | 1695 // Check if the object is a JS array or not. |
| 1684 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 1696 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
| 1685 __ cmp(r4, Operand(JS_ARRAY_TYPE)); | 1697 __ cmp(r4, Operand(JS_ARRAY_TYPE)); |
| 1686 __ b(eq, &array); | 1698 __ b(eq, &array); |
| 1687 // Check that the object is some kind of JS object. | 1699 // Check that the object is some kind of JS object. |
| 1688 __ cmp(r4, Operand(FIRST_JS_OBJECT_TYPE)); | 1700 __ cmp(r4, Operand(FIRST_JS_OBJECT_TYPE)); |
| 1689 __ b(lt, &slow); | 1701 __ b(lt, &slow); |
| 1690 | 1702 |
| 1691 // Object case: Check key against length in the elements array. | 1703 // Object case: Check key against length in the elements array. |
| 1692 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 1704 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 1693 // Check that the object is in fast mode (not dictionary). | 1705 // Check that the object is in fast mode and writable. |
| 1694 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); | 1706 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); |
| 1695 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 1707 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 1696 __ cmp(r4, ip); | 1708 __ cmp(r4, ip); |
| 1697 __ b(ne, &check_pixel_array); | 1709 __ b(ne, &check_pixel_array); |
| 1698 // Check array bounds. Both the key and the length of FixedArray are smis. | 1710 // Check array bounds. Both the key and the length of FixedArray are smis. |
| 1699 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1711 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1700 __ cmp(key, Operand(ip)); | 1712 __ cmp(key, Operand(ip)); |
| 1701 __ b(lo, &fast); | 1713 __ b(lo, &fast); |
| 1702 | 1714 |
| 1703 // Slow case, handle jump to runtime. | 1715 // Slow case, handle jump to runtime. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1741 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1753 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1742 __ cmp(key, Operand(ip)); | 1754 __ cmp(key, Operand(ip)); |
| 1743 __ b(hs, &slow); | 1755 __ b(hs, &slow); |
| 1744 // Calculate key + 1 as smi. | 1756 // Calculate key + 1 as smi. |
| 1745 ASSERT_EQ(0, kSmiTag); | 1757 ASSERT_EQ(0, kSmiTag); |
| 1746 __ add(r4, key, Operand(Smi::FromInt(1))); | 1758 __ add(r4, key, Operand(Smi::FromInt(1))); |
| 1747 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1759 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1748 __ b(&fast); | 1760 __ b(&fast); |
| 1749 | 1761 |
| 1750 // Array case: Get the length and the elements array from the JS | 1762 // Array case: Get the length and the elements array from the JS |
| 1751 // array. Check that the array is in fast mode; if it is the | 1763 // array. Check that the array is in fast mode (and writable); if it |
| 1752 // length is always a smi. | 1764 // is the length is always a smi. |
| 1753 __ bind(&array); | 1765 __ bind(&array); |
| 1754 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 1766 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 1755 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); | 1767 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); |
| 1756 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 1768 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 1757 __ cmp(r4, ip); | 1769 __ cmp(r4, ip); |
| 1758 __ b(ne, &slow); | 1770 __ b(ne, &slow); |
| 1759 | 1771 |
| 1760 // Check the key against the length in the array. | 1772 // Check the key against the length in the array. |
| 1761 __ ldr(ip, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1773 __ ldr(ip, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1762 __ cmp(key, Operand(ip)); | 1774 __ cmp(key, Operand(ip)); |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2210 Register scratch = r3; | 2222 Register scratch = r3; |
| 2211 | 2223 |
| 2212 // Check that the receiver isn't a smi. | 2224 // Check that the receiver isn't a smi. |
| 2213 __ BranchOnSmi(receiver, &miss); | 2225 __ BranchOnSmi(receiver, &miss); |
| 2214 | 2226 |
| 2215 // Check that the object is a JS array. | 2227 // Check that the object is a JS array. |
| 2216 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); | 2228 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); |
| 2217 __ b(ne, &miss); | 2229 __ b(ne, &miss); |
| 2218 | 2230 |
| 2219 // Check that elements are FixedArray. | 2231 // Check that elements are FixedArray. |
| 2232 // We rely on StoreIC_ArrayLength below to deal with all types of |
| 2233 // fast elements (including COW). |
| 2220 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 2234 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 2221 __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE); | 2235 __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE); |
| 2222 __ b(ne, &miss); | 2236 __ b(ne, &miss); |
| 2223 | 2237 |
| 2224 // Check that value is a smi. | 2238 // Check that value is a smi. |
| 2225 __ BranchOnNotSmi(value, &miss); | 2239 __ BranchOnNotSmi(value, &miss); |
| 2226 | 2240 |
| 2227 // Prepare tail call to StoreIC_ArrayLength. | 2241 // Prepare tail call to StoreIC_ArrayLength. |
| 2228 __ Push(receiver, value); | 2242 __ Push(receiver, value); |
| 2229 | 2243 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2256 GenerateMiss(masm); | 2270 GenerateMiss(masm); |
| 2257 } | 2271 } |
| 2258 | 2272 |
| 2259 | 2273 |
| 2260 #undef __ | 2274 #undef __ |
| 2261 | 2275 |
| 2262 | 2276 |
| 2263 } } // namespace v8::internal | 2277 } } // namespace v8::internal |
| 2264 | 2278 |
| 2265 #endif // V8_TARGET_ARCH_ARM | 2279 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |