| 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 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 Smi::FromInt(PropertyDetails::TypeField::mask())); | 374 Smi::FromInt(PropertyDetails::TypeField::mask())); |
| 375 __ j(not_zero, miss); | 375 __ j(not_zero, miss); |
| 376 | 376 |
| 377 // Get the value at the masked, scaled index. | 377 // Get the value at the masked, scaled index. |
| 378 const int kValueOffset = | 378 const int kValueOffset = |
| 379 NumberDictionary::kElementsStartOffset + kPointerSize; | 379 NumberDictionary::kElementsStartOffset + kPointerSize; |
| 380 __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | 380 __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); |
| 381 } | 381 } |
| 382 | 382 |
| 383 | 383 |
| 384 // The offset from the inlined patch site to the start of the inlined | |
| 385 // load instruction. | |
| 386 const int LoadIC::kOffsetToLoadInstruction = 20; | |
| 387 | |
| 388 | |
| 389 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | 384 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
| 390 // ----------- S t a t e ------------- | 385 // ----------- S t a t e ------------- |
| 391 // -- rax : receiver | 386 // -- rax : receiver |
| 392 // -- rcx : name | 387 // -- rcx : name |
| 393 // -- rsp[0] : return address | 388 // -- rsp[0] : return address |
| 394 // ----------------------------------- | 389 // ----------------------------------- |
| 395 Label miss; | 390 Label miss; |
| 396 | 391 |
| 397 StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss); | 392 StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss); |
| 398 __ bind(&miss); | 393 __ bind(&miss); |
| (...skipping 891 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1290 __ push(rcx); // name | 1285 __ push(rcx); // name |
| 1291 __ push(rbx); // return address | 1286 __ push(rbx); // return address |
| 1292 | 1287 |
| 1293 // Perform tail call to the entry. | 1288 // Perform tail call to the entry. |
| 1294 ExternalReference ref = | 1289 ExternalReference ref = |
| 1295 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); | 1290 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); |
| 1296 __ TailCallExternalReference(ref, 2, 1); | 1291 __ TailCallExternalReference(ref, 2, 1); |
| 1297 } | 1292 } |
| 1298 | 1293 |
| 1299 | 1294 |
| 1300 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { | |
| 1301 if (V8::UseCrankshaft()) return false; | |
| 1302 | |
| 1303 // The address of the instruction following the call. | |
| 1304 Address test_instruction_address = | |
| 1305 address + Assembler::kCallTargetAddressOffset; | |
| 1306 // If the instruction following the call is not a test rax, nothing | |
| 1307 // was inlined. | |
| 1308 if (*test_instruction_address != Assembler::kTestEaxByte) return false; | |
| 1309 | |
| 1310 Address delta_address = test_instruction_address + 1; | |
| 1311 // The delta to the start of the map check instruction. | |
| 1312 int delta = *reinterpret_cast<int*>(delta_address); | |
| 1313 | |
| 1314 // The map address is the last 8 bytes of the 10-byte | |
| 1315 // immediate move instruction, so we add 2 to get the | |
| 1316 // offset to the last 8 bytes. | |
| 1317 Address map_address = test_instruction_address + delta + 2; | |
| 1318 *(reinterpret_cast<Object**>(map_address)) = map; | |
| 1319 | |
| 1320 // The offset is in the 32-bit displacement of a seven byte | |
| 1321 // memory-to-register move instruction (REX.W 0x88 ModR/M disp32), | |
| 1322 // so we add 3 to get the offset of the displacement. | |
| 1323 Address offset_address = | |
| 1324 test_instruction_address + delta + kOffsetToLoadInstruction + 3; | |
| 1325 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; | |
| 1326 return true; | |
| 1327 } | |
| 1328 | |
| 1329 | |
| 1330 bool LoadIC::PatchInlinedContextualLoad(Address address, | |
| 1331 Object* map, | |
| 1332 Object* cell, | |
| 1333 bool is_dont_delete) { | |
| 1334 // TODO(<bug#>): implement this. | |
| 1335 return false; | |
| 1336 } | |
| 1337 | |
| 1338 | |
| 1339 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { | |
| 1340 if (V8::UseCrankshaft()) return false; | |
| 1341 | |
| 1342 // The address of the instruction following the call. | |
| 1343 Address test_instruction_address = | |
| 1344 address + Assembler::kCallTargetAddressOffset; | |
| 1345 | |
| 1346 // If the instruction following the call is not a test rax, nothing | |
| 1347 // was inlined. | |
| 1348 if (*test_instruction_address != Assembler::kTestEaxByte) return false; | |
| 1349 | |
| 1350 // Extract the encoded deltas from the test rax instruction. | |
| 1351 Address encoded_offsets_address = test_instruction_address + 1; | |
| 1352 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); | |
| 1353 int delta_to_map_check = -(encoded_offsets & 0xFFFF); | |
| 1354 int delta_to_record_write = encoded_offsets >> 16; | |
| 1355 | |
| 1356 // Patch the map to check. The map address is the last 8 bytes of | |
| 1357 // the 10-byte immediate move instruction. | |
| 1358 Address map_check_address = test_instruction_address + delta_to_map_check; | |
| 1359 Address map_address = map_check_address + 2; | |
| 1360 *(reinterpret_cast<Object**>(map_address)) = map; | |
| 1361 | |
| 1362 // Patch the offset in the store instruction. The offset is in the | |
| 1363 // last 4 bytes of a 7 byte register-to-memory move instruction. | |
| 1364 Address offset_address = | |
| 1365 map_check_address + StoreIC::kOffsetToStoreInstruction + 3; | |
| 1366 // The offset should have initial value (kMaxInt - 1), cleared value | |
| 1367 // (-1) or we should be clearing the inlined version. | |
| 1368 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 || | |
| 1369 *reinterpret_cast<int*>(offset_address) == -1 || | |
| 1370 (offset == 0 && map == HEAP->null_value())); | |
| 1371 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; | |
| 1372 | |
| 1373 // Patch the offset in the write-barrier code. The offset is the | |
| 1374 // last 4 bytes of a 7 byte lea instruction. | |
| 1375 offset_address = map_check_address + delta_to_record_write + 3; | |
| 1376 // The offset should have initial value (kMaxInt), cleared value | |
| 1377 // (-1) or we should be clearing the inlined version. | |
| 1378 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || | |
| 1379 *reinterpret_cast<int*>(offset_address) == -1 || | |
| 1380 (offset == 0 && map == HEAP->null_value())); | |
| 1381 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; | |
| 1382 | |
| 1383 return true; | |
| 1384 } | |
| 1385 | |
| 1386 | |
| 1387 static bool PatchInlinedMapCheck(Address address, Object* map) { | |
| 1388 if (V8::UseCrankshaft()) return false; | |
| 1389 | |
| 1390 // Arguments are address of start of call sequence that called | |
| 1391 // the IC, | |
| 1392 Address test_instruction_address = | |
| 1393 address + Assembler::kCallTargetAddressOffset; | |
| 1394 // The keyed load has a fast inlined case if the IC call instruction | |
| 1395 // is immediately followed by a test instruction. | |
| 1396 if (*test_instruction_address != Assembler::kTestEaxByte) return false; | |
| 1397 | |
| 1398 // Fetch the offset from the test instruction to the map compare | |
| 1399 // instructions (starting with the 64-bit immediate mov of the map | |
| 1400 // address). This offset is stored in the last 4 bytes of the 5 | |
| 1401 // byte test instruction. | |
| 1402 Address delta_address = test_instruction_address + 1; | |
| 1403 int delta = *reinterpret_cast<int*>(delta_address); | |
| 1404 // Compute the map address. The map address is in the last 8 bytes | |
| 1405 // of the 10-byte immediate mov instruction (incl. REX prefix), so we add 2 | |
| 1406 // to the offset to get the map address. | |
| 1407 Address map_address = test_instruction_address + delta + 2; | |
| 1408 // Patch the map check. | |
| 1409 *(reinterpret_cast<Object**>(map_address)) = map; | |
| 1410 return true; | |
| 1411 } | |
| 1412 | |
| 1413 | |
| 1414 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { | |
| 1415 return PatchInlinedMapCheck(address, map); | |
| 1416 } | |
| 1417 | |
| 1418 | |
| 1419 bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { | |
| 1420 return PatchInlinedMapCheck(address, map); | |
| 1421 } | |
| 1422 | |
| 1423 | |
| 1424 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 1295 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1425 // ----------- S t a t e ------------- | 1296 // ----------- S t a t e ------------- |
| 1426 // -- rax : key | 1297 // -- rax : key |
| 1427 // -- rdx : receiver | 1298 // -- rdx : receiver |
| 1428 // -- rsp[0] : return address | 1299 // -- rsp[0] : return address |
| 1429 // ----------------------------------- | 1300 // ----------------------------------- |
| 1430 | 1301 |
| 1431 Counters* counters = masm->isolate()->counters(); | 1302 Counters* counters = masm->isolate()->counters(); |
| 1432 __ IncrementCounter(counters->keyed_load_miss(), 1); | 1303 __ IncrementCounter(counters->keyed_load_miss(), 1); |
| 1433 | 1304 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1496 __ push(rax); // value | 1367 __ push(rax); // value |
| 1497 __ push(rbx); // return address | 1368 __ push(rbx); // return address |
| 1498 | 1369 |
| 1499 // Perform tail call to the entry. | 1370 // Perform tail call to the entry. |
| 1500 ExternalReference ref = | 1371 ExternalReference ref = |
| 1501 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); | 1372 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); |
| 1502 __ TailCallExternalReference(ref, 3, 1); | 1373 __ TailCallExternalReference(ref, 3, 1); |
| 1503 } | 1374 } |
| 1504 | 1375 |
| 1505 | 1376 |
| 1506 // The offset from the inlined patch site to the start of the inlined | |
| 1507 // store instruction. | |
| 1508 const int StoreIC::kOffsetToStoreInstruction = 20; | |
| 1509 | |
| 1510 | |
| 1511 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { | 1377 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
| 1512 // ----------- S t a t e ------------- | 1378 // ----------- S t a t e ------------- |
| 1513 // -- rax : value | 1379 // -- rax : value |
| 1514 // -- rcx : name | 1380 // -- rcx : name |
| 1515 // -- rdx : receiver | 1381 // -- rdx : receiver |
| 1516 // -- rsp[0] : return address | 1382 // -- rsp[0] : return address |
| 1517 // ----------------------------------- | 1383 // ----------------------------------- |
| 1518 // | 1384 // |
| 1519 // This accepts as a receiver anything JSObject::SetElementsLength accepts | 1385 // This accepts as a receiver anything JSObject::SetElementsLength accepts |
| 1520 // (currently anything except for external and pixel arrays which means | 1386 // (currently anything except for external and pixel arrays which means |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1743 Condition cc = *jmp_address == Assembler::kJncShortOpcode | 1609 Condition cc = *jmp_address == Assembler::kJncShortOpcode |
| 1744 ? not_zero | 1610 ? not_zero |
| 1745 : zero; | 1611 : zero; |
| 1746 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1612 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1747 } | 1613 } |
| 1748 | 1614 |
| 1749 | 1615 |
| 1750 } } // namespace v8::internal | 1616 } } // namespace v8::internal |
| 1751 | 1617 |
| 1752 #endif // V8_TARGET_ARCH_X64 | 1618 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |