OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1265 | 1265 |
1266 | 1266 |
1267 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 1267 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
1268 StrictModeFlag strict_mode) { | 1268 StrictModeFlag strict_mode) { |
1269 // ---------- S t a t e -------------- | 1269 // ---------- S t a t e -------------- |
1270 // -- r0 : value | 1270 // -- r0 : value |
1271 // -- r1 : key | 1271 // -- r1 : key |
1272 // -- r2 : receiver | 1272 // -- r2 : receiver |
1273 // -- lr : return address | 1273 // -- lr : return address |
1274 // ----------------------------------- | 1274 // ----------------------------------- |
1275 Label slow, fast, array, extra; | 1275 Label slow, array, extra, check_if_double_array; |
1276 Label fast_object_with_map_check, fast_object_without_map_check; | |
1277 Label fast_double_with_map_check, fast_double_without_map_check; | |
1276 | 1278 |
1277 // Register usage. | 1279 // Register usage. |
1278 Register value = r0; | 1280 Register value = r0; |
1279 Register key = r1; | 1281 Register key = r1; |
1280 Register receiver = r2; | 1282 Register receiver = r2; |
1281 Register elements = r3; // Elements array of the receiver. | 1283 Register elements = r3; // Elements array of the receiver. |
1284 Register elements_map = r6; | |
1285 Register receiver_map = r7; | |
1282 // r4 and r5 are used as general scratch registers. | 1286 // r4 and r5 are used as general scratch registers. |
1283 | 1287 |
1284 // Check that the key is a smi. | 1288 // Check that the key is a smi. |
1285 __ JumpIfNotSmi(key, &slow); | 1289 __ JumpIfNotSmi(key, &slow); |
1286 // Check that the object isn't a smi. | 1290 // Check that the object isn't a smi. |
1287 __ JumpIfSmi(receiver, &slow); | 1291 __ JumpIfSmi(receiver, &slow); |
1288 // Get the map of the object. | 1292 // Get the map of the object. |
1289 __ ldr(r4, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1293 __ ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
1290 // Check that the receiver does not require access checks. We need | 1294 // Check that the receiver does not require access checks. We need |
1291 // to do this because this generic stub does not perform map checks. | 1295 // to do this because this generic stub does not perform map checks. |
1292 __ ldrb(ip, FieldMemOperand(r4, Map::kBitFieldOffset)); | 1296 __ ldrb(ip, FieldMemOperand(receiver_map, Map::kBitFieldOffset)); |
1293 __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded)); | 1297 __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded)); |
1294 __ b(ne, &slow); | 1298 __ b(ne, &slow); |
1295 // Check if the object is a JS array or not. | 1299 // Check if the object is a JS array or not. |
1296 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 1300 __ ldrb(r4, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset)); |
1297 __ cmp(r4, Operand(JS_ARRAY_TYPE)); | 1301 __ cmp(r4, Operand(JS_ARRAY_TYPE)); |
1298 __ b(eq, &array); | 1302 __ b(eq, &array); |
1299 // Check that the object is some kind of JSObject. | 1303 // Check that the object is some kind of JSObject. |
1300 __ cmp(r4, Operand(FIRST_JS_RECEIVER_TYPE)); | 1304 __ cmp(r4, Operand(FIRST_JS_RECEIVER_TYPE)); |
1301 __ b(lt, &slow); | 1305 __ b(lt, &slow); |
1302 __ cmp(r4, Operand(JS_PROXY_TYPE)); | 1306 __ cmp(r4, Operand(JS_PROXY_TYPE)); |
1303 __ b(eq, &slow); | 1307 __ b(eq, &slow); |
1304 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE)); | 1308 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE)); |
1305 __ b(eq, &slow); | 1309 __ b(eq, &slow); |
1306 | 1310 |
1307 // Object case: Check key against length in the elements array. | 1311 // Object case: Check key against length in the elements array. |
1308 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 1312 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
1309 // Check that the object is in fast mode and writable. | |
1310 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); | |
1311 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | |
1312 __ cmp(r4, ip); | |
1313 __ b(ne, &slow); | |
1314 // Check array bounds. Both the key and the length of FixedArray are smis. | 1313 // Check array bounds. Both the key and the length of FixedArray are smis. |
1315 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1314 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1316 __ cmp(key, Operand(ip)); | 1315 __ cmp(key, Operand(ip)); |
1317 __ b(lo, &fast); | 1316 __ b(lo, &fast_object_with_map_check); |
1318 | 1317 |
1319 // Slow case, handle jump to runtime. | 1318 // Slow case, handle jump to runtime. |
1320 __ bind(&slow); | 1319 __ bind(&slow); |
1321 // Entry registers are intact. | 1320 // Entry registers are intact. |
1322 // r0: value. | 1321 // r0: value. |
1323 // r1: key. | 1322 // r1: key. |
1324 // r2: receiver. | 1323 // r2: receiver. |
Rico
2011/10/05 08:39:19
r5: receiver map
| |
1325 GenerateRuntimeSetProperty(masm, strict_mode); | 1324 GenerateRuntimeSetProperty(masm, strict_mode); |
1326 | 1325 |
1327 // Extra capacity case: Check if there is extra capacity to | 1326 // Extra capacity case: Check if there is extra capacity to |
1328 // perform the store and update the length. Used for adding one | 1327 // perform the store and update the length. Used for adding one |
1329 // element to the array by writing to array[array.length]. | 1328 // element to the array by writing to array[array.length]. |
1330 __ bind(&extra); | 1329 __ bind(&extra); |
1331 // Condition code from comparing key and array length is still available. | 1330 // Condition code from comparing key and array length is still available. |
1332 __ b(ne, &slow); // Only support writing to writing to array[array.length]. | 1331 __ b(ne, &slow); // Only support writing to writing to array[array.length]. |
1333 // Check for room in the elements backing store. | 1332 // Check for room in the elements backing store. |
1334 // Both the key and the length of FixedArray are smis. | 1333 // Both the key and the length of FixedArray are smis. |
1335 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1334 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1336 __ cmp(key, Operand(ip)); | 1335 __ cmp(key, Operand(ip)); |
1337 __ b(hs, &slow); | 1336 __ b(hs, &slow); |
1337 __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); | |
1338 __ cmp(elements_map, | |
1339 Operand(masm->isolate()->factory()->fixed_array_map())); | |
1340 __ b(ne, &check_if_double_array); | |
1338 // Calculate key + 1 as smi. | 1341 // Calculate key + 1 as smi. |
1339 STATIC_ASSERT(kSmiTag == 0); | 1342 STATIC_ASSERT(kSmiTag == 0); |
1340 __ add(r4, key, Operand(Smi::FromInt(1))); | 1343 __ add(r4, key, Operand(Smi::FromInt(1))); |
1341 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1344 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1342 __ b(&fast); | 1345 __ b(&fast_object_without_map_check); |
1346 | |
1347 __ bind(&check_if_double_array); | |
1348 __ cmp(elements_map, | |
1349 Operand(masm->isolate()->factory()->fixed_double_array_map())); | |
1350 __ b(ne, &slow); | |
1351 // Add 1 to key, and go to common element store code for doubles. | |
1352 STATIC_ASSERT(kSmiTag == 0); | |
1353 __ add(r4, key, Operand(Smi::FromInt(1))); | |
1354 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
1355 __ bind(&fast_double_without_map_check); | |
1343 | 1356 |
1344 // Array case: Get the length and the elements array from the JS | 1357 // Array case: Get the length and the elements array from the JS |
1345 // array. Check that the array is in fast mode (and writable); if it | 1358 // array. Check that the array is in fast mode (and writable); if it |
1346 // is the length is always a smi. | 1359 // is the length is always a smi. |
1347 __ bind(&array); | 1360 __ bind(&array); |
1348 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 1361 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
1349 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); | |
1350 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | |
1351 __ cmp(r4, ip); | |
1352 __ b(ne, &slow); | |
1353 | 1362 |
1354 // Check the key against the length in the array. | 1363 // Check the key against the length in the array. |
1355 __ ldr(ip, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1364 __ ldr(ip, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1356 __ cmp(key, Operand(ip)); | 1365 __ cmp(key, Operand(ip)); |
1357 __ b(hs, &extra); | 1366 __ b(hs, &extra); |
1358 // Fall through to fast case. | 1367 // Fall through to fast case. |
1359 | 1368 |
1360 __ bind(&fast); | 1369 __ bind(&fast_object_with_map_check); |
1361 Register scratch_value = r4; | 1370 Register scratch_value = r4; |
1362 Register address = r5; | 1371 Register address = r5; |
1363 | 1372 __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
1373 __ cmp(elements_map, | |
1374 Operand(masm->isolate()->factory()->fixed_array_map())); | |
1375 __ b(ne, &fast_double_with_map_check); | |
1376 __ bind(&fast_object_without_map_check); | |
1377 // Smi stores don't require further checks. | |
1364 Label non_smi_value; | 1378 Label non_smi_value; |
1365 __ JumpIfNotSmi(value, &non_smi_value); | 1379 __ JumpIfNotSmi(value, &non_smi_value); |
1366 // It's irrelevant whether array is smi-only or not when writing a smi. | 1380 // It's irrelevant whether array is smi-only or not when writing a smi. |
1367 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1381 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
1368 __ add(address, address, Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1382 __ add(address, address, Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
1369 __ str(value, MemOperand(address)); | 1383 __ str(value, MemOperand(address)); |
1370 __ Ret(); | 1384 __ Ret(); |
1371 | 1385 |
1372 __ bind(&non_smi_value); | 1386 __ bind(&non_smi_value); |
1373 if (FLAG_smi_only_arrays) { | 1387 if (FLAG_smi_only_arrays) { |
1374 // Escape to slow case when writing non-smi into smi-only array. | 1388 // Escape to slow case when writing non-smi into smi-only array. |
1375 __ ldr(scratch_value, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1389 __ CheckFastObjectElements(receiver_map, scratch_value, &slow); |
1376 __ CheckFastObjectElements(scratch_value, scratch_value, &slow); | |
1377 } | 1390 } |
1378 // Fast elements array, store the value to the elements backing store. | 1391 // Fast elements array, store the value to the elements backing store. |
1379 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1392 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
1380 __ add(address, address, Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1393 __ add(address, address, Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
1381 __ str(value, MemOperand(address)); | 1394 __ str(value, MemOperand(address)); |
1382 // Update write barrier for the elements array address. | 1395 // Update write barrier for the elements array address. |
1383 __ mov(scratch_value, value); // Preserve the value which is returned. | 1396 __ mov(scratch_value, value); // Preserve the value which is returned. |
1384 __ RecordWrite(elements, | 1397 __ RecordWrite(elements, |
1385 address, | 1398 address, |
1386 scratch_value, | 1399 scratch_value, |
1387 kLRHasNotBeenSaved, | 1400 kLRHasNotBeenSaved, |
1388 kDontSaveFPRegs, | 1401 kDontSaveFPRegs, |
1389 EMIT_REMEMBERED_SET, | 1402 EMIT_REMEMBERED_SET, |
1390 OMIT_SMI_CHECK); | 1403 OMIT_SMI_CHECK); |
1391 __ Ret(); | 1404 __ Ret(); |
1405 | |
1406 __ bind(&fast_double_with_map_check); | |
1407 // Check for fast double array case. If this fails, call through to the | |
1408 // runtime. | |
1409 __ cmp(elements_map, | |
1410 Operand(masm->isolate()->factory()->fixed_double_array_map())); | |
1411 __ b(ne, &slow); | |
1412 __ bind(&fast_double_without_map_check); | |
1413 __ StoreNumberToDoubleElements(value, key, receiver, elements, | |
Rico
2011/10/05 08:39:19
all arguments on one line or each on seperate line
| |
1414 r4, r5, r6, r7, &slow); | |
1415 __ Ret(); | |
1392 } | 1416 } |
1393 | 1417 |
1394 | 1418 |
1395 void StoreIC::GenerateMegamorphic(MacroAssembler* masm, | 1419 void StoreIC::GenerateMegamorphic(MacroAssembler* masm, |
1396 StrictModeFlag strict_mode) { | 1420 StrictModeFlag strict_mode) { |
1397 // ----------- S t a t e ------------- | 1421 // ----------- S t a t e ------------- |
1398 // -- r0 : value | 1422 // -- r0 : value |
1399 // -- r1 : receiver | 1423 // -- r1 : receiver |
1400 // -- r2 : name | 1424 // -- r2 : name |
1401 // -- lr : return address | 1425 // -- lr : return address |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1641 Register reg = Assembler::GetRn(instr_at_patch); | 1665 Register reg = Assembler::GetRn(instr_at_patch); |
1642 patcher.masm()->tst(reg, Operand(kSmiTagMask)); | 1666 patcher.masm()->tst(reg, Operand(kSmiTagMask)); |
1643 patcher.EmitCondition(eq); | 1667 patcher.EmitCondition(eq); |
1644 } | 1668 } |
1645 } | 1669 } |
1646 | 1670 |
1647 | 1671 |
1648 } } // namespace v8::internal | 1672 } } // namespace v8::internal |
1649 | 1673 |
1650 #endif // V8_TARGET_ARCH_ARM | 1674 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |