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 |