Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: src/arm/ic-arm.cc

Issue 3144002: Copy-on-write arrays. (Closed)
Patch Set: Review fixes. Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/arm/full-codegen-arm.cc ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/full-codegen-arm.cc ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698