| 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 Register key, | 154 Register key, |
| 155 Register t0, | 155 Register t0, |
| 156 Register t1, | 156 Register t1, |
| 157 Register t2) { | 157 Register t2) { |
| 158 // Register use: | 158 // Register use: |
| 159 // | 159 // |
| 160 // elements - holds the slow-case elements of the receiver and is unchanged. | 160 // elements - holds the slow-case elements of the receiver and is unchanged. |
| 161 // | 161 // |
| 162 // key - holds the smi key on entry and is unchanged if a branch is | 162 // key - holds the smi key on entry and is unchanged if a branch is |
| 163 // performed to the miss label. | 163 // performed to the miss label. |
| 164 // Holds the result on exit if the load succeeded. |
| 164 // | 165 // |
| 165 // Scratch registers: | 166 // Scratch registers: |
| 166 // | 167 // |
| 167 // t0 - holds the untagged key on entry and holds the hash once computed. | 168 // t0 - holds the untagged key on entry and holds the hash once computed. |
| 168 // Holds the result on exit if the load succeeded. | |
| 169 // | 169 // |
| 170 // t1 - used to hold the capacity mask of the dictionary | 170 // t1 - used to hold the capacity mask of the dictionary |
| 171 // | 171 // |
| 172 // t2 - used for the index into the dictionary. | 172 // t2 - used for the index into the dictionary. |
| 173 Label done; | 173 Label done; |
| 174 | 174 |
| 175 // Compute the hash code from the untagged key. This must be kept in sync | 175 // Compute the hash code from the untagged key. This must be kept in sync |
| 176 // with ComputeIntegerHash in utils.h. | 176 // with ComputeIntegerHash in utils.h. |
| 177 // | 177 // |
| 178 // hash = ~hash + (hash << 15); | 178 // hash = ~hash + (hash << 15); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 // t2: elements + (index * kPointerSize) | 226 // t2: elements + (index * kPointerSize) |
| 227 const int kDetailsOffset = | 227 const int kDetailsOffset = |
| 228 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; | 228 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
| 229 __ ldr(t1, FieldMemOperand(t2, kDetailsOffset)); | 229 __ ldr(t1, FieldMemOperand(t2, kDetailsOffset)); |
| 230 __ tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask()))); | 230 __ tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask()))); |
| 231 __ b(ne, miss); | 231 __ b(ne, miss); |
| 232 | 232 |
| 233 // Get the value at the masked, scaled index and return. | 233 // Get the value at the masked, scaled index and return. |
| 234 const int kValueOffset = | 234 const int kValueOffset = |
| 235 NumberDictionary::kElementsStartOffset + kPointerSize; | 235 NumberDictionary::kElementsStartOffset + kPointerSize; |
| 236 __ ldr(t0, FieldMemOperand(t2, kValueOffset)); | 236 __ ldr(key, FieldMemOperand(t2, kValueOffset)); |
| 237 } | 237 } |
| 238 | 238 |
| 239 | 239 |
| 240 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | 240 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
| 241 // ----------- S t a t e ------------- | 241 // ----------- S t a t e ------------- |
| 242 // -- r2 : name | 242 // -- r2 : name |
| 243 // -- lr : return address | 243 // -- lr : return address |
| 244 // -- r0 : receiver | 244 // -- r0 : receiver |
| 245 // -- sp[0] : receiver | 245 // -- sp[0] : receiver |
| 246 // ----------------------------------- | 246 // ----------------------------------- |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 // In the case that the object is a value-wrapper object, | 732 // In the case that the object is a value-wrapper object, |
| 733 // we enter the runtime system to make sure that indexing into string | 733 // we enter the runtime system to make sure that indexing into string |
| 734 // objects work as intended. | 734 // objects work as intended. |
| 735 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 735 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
| 736 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 736 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
| 737 __ cmp(r2, Operand(JS_OBJECT_TYPE)); | 737 __ cmp(r2, Operand(JS_OBJECT_TYPE)); |
| 738 __ b(lt, &slow); | 738 __ b(lt, &slow); |
| 739 | 739 |
| 740 // Check that the key is a smi. | 740 // Check that the key is a smi. |
| 741 __ BranchOnNotSmi(key, &slow); | 741 __ BranchOnNotSmi(key, &slow); |
| 742 // Untag key into r2.. | |
| 743 __ mov(r2, Operand(key, ASR, kSmiTagSize)); | |
| 744 | |
| 745 // Get the elements array of the object. | 742 // Get the elements array of the object. |
| 746 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 743 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 747 // Check that the object is in fast mode (not dictionary). | 744 // Check that the object is in fast mode (not dictionary). |
| 748 __ ldr(r3, FieldMemOperand(r4, HeapObject::kMapOffset)); | 745 __ ldr(r3, FieldMemOperand(r4, HeapObject::kMapOffset)); |
| 749 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 746 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 750 __ cmp(r3, ip); | 747 __ cmp(r3, ip); |
| 751 __ b(ne, &check_pixel_array); | 748 __ b(ne, &check_pixel_array); |
| 752 // Check that the key (index) is within bounds. | 749 // Check that the key (index) is within bounds. |
| 753 __ ldr(r3, FieldMemOperand(r4, Array::kLengthOffset)); | 750 __ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset)); |
| 754 __ cmp(r2, r3); | 751 __ cmp(key, Operand(r3)); |
| 755 __ b(hs, &slow); | 752 __ b(hs, &slow); |
| 756 // Fast case: Do the load. | 753 // Fast case: Do the load. |
| 757 __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 754 __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 758 __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2)); | 755 // The key is a smi. |
| 756 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 757 __ ldr(r2, MemOperand(r3, key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 759 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 758 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 760 __ cmp(r2, ip); | 759 __ cmp(r2, ip); |
| 761 // In case the loaded value is the_hole we have to consult GetProperty | 760 // In case the loaded value is the_hole we have to consult GetProperty |
| 762 // to ensure the prototype chain is searched. | 761 // to ensure the prototype chain is searched. |
| 763 __ b(eq, &slow); | 762 __ b(eq, &slow); |
| 764 __ mov(r0, r2); | 763 __ mov(r0, r2); |
| 765 __ Ret(); | 764 __ Ret(); |
| 766 | 765 |
| 767 // Check whether the elements is a pixel array. | 766 // Check whether the elements is a pixel array. |
| 768 // r0: key | 767 // r0: key |
| 769 // r2: untagged index | |
| 770 // r3: elements map | 768 // r3: elements map |
| 771 // r4: elements | 769 // r4: elements |
| 772 __ bind(&check_pixel_array); | 770 __ bind(&check_pixel_array); |
| 773 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); | 771 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); |
| 774 __ cmp(r3, ip); | 772 __ cmp(r3, ip); |
| 775 __ b(ne, &check_number_dictionary); | 773 __ b(ne, &check_number_dictionary); |
| 776 __ ldr(ip, FieldMemOperand(r4, PixelArray::kLengthOffset)); | 774 __ ldr(ip, FieldMemOperand(r4, PixelArray::kLengthOffset)); |
| 775 __ mov(r2, Operand(key, ASR, kSmiTagSize)); |
| 777 __ cmp(r2, ip); | 776 __ cmp(r2, ip); |
| 778 __ b(hs, &slow); | 777 __ b(hs, &slow); |
| 779 __ ldr(ip, FieldMemOperand(r4, PixelArray::kExternalPointerOffset)); | 778 __ ldr(ip, FieldMemOperand(r4, PixelArray::kExternalPointerOffset)); |
| 780 __ ldrb(r2, MemOperand(ip, r2)); | 779 __ ldrb(r2, MemOperand(ip, r2)); |
| 781 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); // Tag result as smi. | 780 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); // Tag result as smi. |
| 782 __ Ret(); | 781 __ Ret(); |
| 783 | 782 |
| 784 __ bind(&check_number_dictionary); | 783 __ bind(&check_number_dictionary); |
| 785 // Check whether the elements is a number dictionary. | 784 // Check whether the elements is a number dictionary. |
| 786 // r0: key | 785 // r0: key |
| 787 // r2: untagged index | |
| 788 // r3: elements map | 786 // r3: elements map |
| 789 // r4: elements | 787 // r4: elements |
| 790 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 788 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
| 791 __ cmp(r3, ip); | 789 __ cmp(r3, ip); |
| 792 __ b(ne, &slow); | 790 __ b(ne, &slow); |
| 791 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); |
| 793 GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r2, r3, r5); | 792 GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r2, r3, r5); |
| 794 __ mov(r0, r2); | |
| 795 __ Ret(); | 793 __ Ret(); |
| 796 | 794 |
| 797 // Slow case, key and receiver still in r0 and r1. | 795 // Slow case, key and receiver still in r0 and r1. |
| 798 __ bind(&slow); | 796 __ bind(&slow); |
| 799 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r2, r3); | 797 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r2, r3); |
| 800 GenerateRuntimeGetProperty(masm); | 798 GenerateRuntimeGetProperty(masm); |
| 801 } | 799 } |
| 802 | 800 |
| 803 | 801 |
| 804 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 802 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 __ b(lt, &slow); | 1266 __ b(lt, &slow); |
| 1269 | 1267 |
| 1270 | 1268 |
| 1271 // Object case: Check key against length in the elements array. | 1269 // Object case: Check key against length in the elements array. |
| 1272 __ ldr(r3, FieldMemOperand(r3, JSObject::kElementsOffset)); | 1270 __ ldr(r3, FieldMemOperand(r3, JSObject::kElementsOffset)); |
| 1273 // Check that the object is in fast mode (not dictionary). | 1271 // Check that the object is in fast mode (not dictionary). |
| 1274 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); | 1272 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| 1275 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 1273 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 1276 __ cmp(r2, ip); | 1274 __ cmp(r2, ip); |
| 1277 __ b(ne, &check_pixel_array); | 1275 __ b(ne, &check_pixel_array); |
| 1278 // Untag the key (for checking against untagged length in the fixed array). | |
| 1279 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); | |
| 1280 // Compute address to store into and check array bounds. | 1276 // Compute address to store into and check array bounds. |
| 1281 __ add(r2, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1277 __ add(r2, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 1282 __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2)); | 1278 // The key is a smi. Assert we can shift left by 1 to use it as a |
| 1279 // byte offset. |
| 1280 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 1281 __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 1283 __ ldr(ip, FieldMemOperand(r3, FixedArray::kLengthOffset)); | 1282 __ ldr(ip, FieldMemOperand(r3, FixedArray::kLengthOffset)); |
| 1284 __ cmp(r1, Operand(ip)); | 1283 __ cmp(r1, Operand(ip)); |
| 1285 __ b(lo, &fast); | 1284 __ b(lo, &fast); |
| 1286 | 1285 |
| 1287 | 1286 |
| 1288 // Slow case: | 1287 // Slow case: |
| 1289 __ bind(&slow); | 1288 __ bind(&slow); |
| 1290 GenerateRuntimeSetProperty(masm); | 1289 GenerateRuntimeSetProperty(masm); |
| 1291 | 1290 |
| 1292 // Check whether the elements is a pixel array. | 1291 // Check whether the elements is a pixel array. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1319 __ mov(r0, Operand(r4)); // Return the original value. | 1318 __ mov(r0, Operand(r4)); // Return the original value. |
| 1320 __ Ret(); | 1319 __ Ret(); |
| 1321 | 1320 |
| 1322 | 1321 |
| 1323 // Extra capacity case: Check if there is extra capacity to | 1322 // Extra capacity case: Check if there is extra capacity to |
| 1324 // perform the store and update the length. Used for adding one | 1323 // perform the store and update the length. Used for adding one |
| 1325 // element to the array by writing to array[array.length]. | 1324 // element to the array by writing to array[array.length]. |
| 1326 // r0 == value, r1 == key, r2 == elements, r3 == object | 1325 // r0 == value, r1 == key, r2 == elements, r3 == object |
| 1327 __ bind(&extra); | 1326 __ bind(&extra); |
| 1328 __ b(ne, &slow); // do not leave holes in the array | 1327 __ b(ne, &slow); // do not leave holes in the array |
| 1329 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); // untag | 1328 __ ldr(ip, FieldMemOperand(r2, FixedArray::kLengthOffset)); |
| 1330 __ ldr(ip, FieldMemOperand(r2, Array::kLengthOffset)); | |
| 1331 __ cmp(r1, Operand(ip)); | 1329 __ cmp(r1, Operand(ip)); |
| 1332 __ b(hs, &slow); | 1330 __ b(hs, &slow); |
| 1333 __ mov(r1, Operand(r1, LSL, kSmiTagSize)); // restore tag | 1331 // Increment the key to get the new length. |
| 1334 __ add(r1, r1, Operand(1 << kSmiTagSize)); // and increment | 1332 __ add(r1, r1, Operand(Smi::FromInt(1))); |
| 1335 __ str(r1, FieldMemOperand(r3, JSArray::kLengthOffset)); | 1333 __ str(r1, FieldMemOperand(r3, JSArray::kLengthOffset)); |
| 1336 __ mov(r3, Operand(r2)); | 1334 __ mov(r3, Operand(r2)); |
| 1337 // NOTE: Computing the address to store into must take the fact | 1335 // NOTE: Computing the address to store into must take the fact |
| 1338 // that the key has been incremented into account. | 1336 // that the key has been incremented into account. |
| 1339 int displacement = FixedArray::kHeaderSize - kHeapObjectTag - | 1337 int displacement = FixedArray::kHeaderSize - kHeapObjectTag - |
| 1340 ((1 << kSmiTagSize) * 2); | 1338 ((1 << kSmiTagSize) * 2); |
| 1341 __ add(r2, r2, Operand(displacement)); | 1339 __ add(r2, r2, Operand(displacement)); |
| 1340 // The key is a smi. Assert we can shift left by 1 to use it as a |
| 1341 // byte offset. |
| 1342 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 1342 __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1343 __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 1343 __ b(&fast); | 1344 __ b(&fast); |
| 1344 | 1345 |
| 1345 | 1346 |
| 1346 // Array case: Get the length and the elements array from the JS | 1347 // Array case: Get the length and the elements array from the JS |
| 1347 // array. Check that the array is in fast mode; if it is the | 1348 // array. Check that the array is in fast mode; if it is the |
| 1348 // length is always a smi. | 1349 // length is always a smi. |
| 1349 // r0 == value, r3 == object | 1350 // r0 == value, r3 == object |
| 1350 __ bind(&array); | 1351 __ bind(&array); |
| 1351 __ ldr(r2, FieldMemOperand(r3, JSObject::kElementsOffset)); | 1352 __ ldr(r2, FieldMemOperand(r3, JSObject::kElementsOffset)); |
| 1352 __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); | 1353 __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); |
| 1353 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 1354 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 1354 __ cmp(r1, ip); | 1355 __ cmp(r1, ip); |
| 1355 __ b(ne, &slow); | 1356 __ b(ne, &slow); |
| 1356 | 1357 |
| 1357 // Check the key against the length in the array, compute the | 1358 // Check the key against the length in the array, compute the |
| 1358 // address to store into and fall through to fast case. | 1359 // address to store into and fall through to fast case. |
| 1359 __ ldr(r1, MemOperand(sp)); // restore key | 1360 __ ldr(r1, MemOperand(sp)); // restore key |
| 1360 // r0 == value, r1 == key, r2 == elements, r3 == object. | 1361 // r0 == value, r1 == key, r2 == elements, r3 == object. |
| 1361 __ ldr(ip, FieldMemOperand(r3, JSArray::kLengthOffset)); | 1362 __ ldr(ip, FieldMemOperand(r3, JSArray::kLengthOffset)); |
| 1362 __ cmp(r1, Operand(ip)); | 1363 __ cmp(r1, Operand(ip)); |
| 1363 __ b(hs, &extra); | 1364 __ b(hs, &extra); |
| 1364 __ mov(r3, Operand(r2)); | 1365 __ mov(r3, Operand(r2)); |
| 1365 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1366 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 1367 // The key is a smi. Assert we can shift left by 1 to use it as a |
| 1368 // byte offset. |
| 1369 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 1366 __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1370 __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 1367 | 1371 |
| 1368 | 1372 |
| 1369 // Fast case: Do the store. | 1373 // Fast case: Do the store. |
| 1370 // r0 == value, r2 == address to store into, r3 == elements | 1374 // r0 == value, r2 == address to store into, r3 == elements |
| 1371 __ bind(&fast); | 1375 __ bind(&fast); |
| 1372 __ str(r0, MemOperand(r2)); | 1376 __ str(r0, MemOperand(r2)); |
| 1373 // Skip write barrier if the written value is a smi. | 1377 // Skip write barrier if the written value is a smi. |
| 1374 __ tst(r0, Operand(kSmiTagMask)); | 1378 __ tst(r0, Operand(kSmiTagMask)); |
| 1375 __ b(eq, &exit); | 1379 __ b(eq, &exit); |
| (...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1834 __ bind(&miss); | 1838 __ bind(&miss); |
| 1835 | 1839 |
| 1836 GenerateMiss(masm); | 1840 GenerateMiss(masm); |
| 1837 } | 1841 } |
| 1838 | 1842 |
| 1839 | 1843 |
| 1840 #undef __ | 1844 #undef __ |
| 1841 | 1845 |
| 1842 | 1846 |
| 1843 } } // namespace v8::internal | 1847 } } // namespace v8::internal |
| OLD | NEW |