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 |