OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 1381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 __ popq(RAX); | 1392 __ popq(RAX); |
1393 __ popq(RAX); | 1393 __ popq(RAX); |
1394 __ popq(RAX); // Get result into RAX. | 1394 __ popq(RAX); // Get result into RAX. |
1395 | 1395 |
1396 // Remove the stub frame as we are about to return. | 1396 // Remove the stub frame as we are about to return. |
1397 __ LeaveFrame(); | 1397 __ LeaveFrame(); |
1398 __ ret(); | 1398 __ ret(); |
1399 } | 1399 } |
1400 | 1400 |
1401 | 1401 |
| 1402 // Cannot use function object from ICData as it may be the inlined |
| 1403 // function and not the top-scope function. |
1402 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { | 1404 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { |
1403 Register argdesc_reg = R10; | |
1404 Register ic_reg = RBX; | 1405 Register ic_reg = RBX; |
1405 Register func_reg = RDI; | 1406 Register func_reg = RDI; |
1406 if (FLAG_trace_optimized_ic_calls) { | 1407 if (FLAG_trace_optimized_ic_calls) { |
1407 __ EnterStubFrame(); | 1408 __ EnterStubFrame(); |
1408 __ pushq(func_reg); // Preserve | 1409 __ pushq(func_reg); // Preserve |
1409 __ pushq(argdesc_reg); // Preserve. | |
1410 __ pushq(ic_reg); // Preserve. | 1410 __ pushq(ic_reg); // Preserve. |
1411 __ pushq(ic_reg); // Argument. | 1411 __ pushq(ic_reg); // Argument. |
1412 __ pushq(func_reg); // Argument. | 1412 __ pushq(func_reg); // Argument. |
1413 __ CallRuntime(kTraceICCallRuntimeEntry); | 1413 __ CallRuntime(kTraceICCallRuntimeEntry); |
1414 __ popq(RAX); // Discard argument; | 1414 __ popq(RAX); // Discard argument; |
1415 __ popq(RAX); // Discard argument; | 1415 __ popq(RAX); // Discard argument; |
1416 __ popq(ic_reg); // Restore. | 1416 __ popq(ic_reg); // Restore. |
1417 __ popq(argdesc_reg); // Restore. | |
1418 __ popq(func_reg); // Restore. | 1417 __ popq(func_reg); // Restore. |
1419 __ LeaveFrame(); | 1418 __ LeaveFrame(); |
1420 } | 1419 } |
1421 __ incq(FieldAddress(func_reg, Function::usage_counter_offset())); | 1420 __ incq(FieldAddress(func_reg, Function::usage_counter_offset())); |
1422 } | 1421 } |
1423 | 1422 |
1424 | 1423 |
1425 // Loads function into 'temp_reg', preserves 'ic_reg'. | 1424 // Loads function into 'temp_reg', preserves 'ic_reg'. |
1426 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, | 1425 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, |
1427 Register temp_reg) { | 1426 Register temp_reg) { |
1428 Register ic_reg = RBX; | 1427 Register ic_reg = RBX; |
1429 Register func_reg = temp_reg; | 1428 Register func_reg = temp_reg; |
1430 ASSERT(ic_reg != func_reg); | 1429 ASSERT(ic_reg != func_reg); |
1431 __ movq(func_reg, FieldAddress(ic_reg, ICData::function_offset())); | 1430 __ movq(func_reg, FieldAddress(ic_reg, ICData::function_offset())); |
1432 __ incq(FieldAddress(func_reg, Function::usage_counter_offset())); | 1431 __ incq(FieldAddress(func_reg, Function::usage_counter_offset())); |
1433 } | 1432 } |
1434 | 1433 |
1435 | 1434 |
1436 // Generate inline cache check for 'num_args'. | 1435 // Generate inline cache check for 'num_args'. |
1437 // RBX: Inline cache data object. | 1436 // RBX: Inline cache data object. |
1438 // R10: Arguments descriptor array. | |
1439 // TOS(0): return address | 1437 // TOS(0): return address |
1440 // Control flow: | 1438 // Control flow: |
1441 // - If receiver is null -> jump to IC miss. | 1439 // - If receiver is null -> jump to IC miss. |
1442 // - If receiver is Smi -> load Smi class. | 1440 // - If receiver is Smi -> load Smi class. |
1443 // - If receiver is not-Smi -> load receiver's class. | 1441 // - If receiver is not-Smi -> load receiver's class. |
1444 // - Check if 'num_args' (including receiver) match any IC data group. | 1442 // - Check if 'num_args' (including receiver) match any IC data group. |
1445 // - Match found -> jump to target. | 1443 // - Match found -> jump to target. |
1446 // - Match not found -> jump to IC miss. | 1444 // - Match not found -> jump to IC miss. |
1447 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1445 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
1448 intptr_t num_args) { | 1446 intptr_t num_args) { |
1449 ASSERT(num_args > 0); | 1447 ASSERT(num_args > 0); |
1450 #if defined(DEBUG) | 1448 #if defined(DEBUG) |
1451 { Label ok; | 1449 { Label ok; |
1452 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1450 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
1453 // 'num_args_tested' is stored as an untagged int. | 1451 // 'num_args_tested' is stored as an untagged int. |
1454 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); | 1452 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); |
1455 __ cmpq(RCX, Immediate(num_args)); | 1453 __ cmpq(RCX, Immediate(num_args)); |
1456 __ j(EQUAL, &ok, Assembler::kNearJump); | 1454 __ j(EQUAL, &ok, Assembler::kNearJump); |
1457 __ Stop("Incorrect stub for IC data"); | 1455 __ Stop("Incorrect stub for IC data"); |
1458 __ Bind(&ok); | 1456 __ Bind(&ok); |
1459 } | 1457 } |
1460 #endif // DEBUG | 1458 #endif // DEBUG |
1461 | 1459 |
| 1460 // Load arguments descriptor into R10. |
| 1461 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
1462 // Loop that checks if there is an IC data match. | 1462 // Loop that checks if there is an IC data match. |
1463 Label loop, update, test, found, get_class_id_as_smi; | 1463 Label loop, update, test, found, get_class_id_as_smi; |
1464 // RBX: IC data object (preserved). | 1464 // RBX: IC data object (preserved). |
1465 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); | 1465 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
1466 // R12: ic_data_array with check entries: classes and target functions. | 1466 // R12: ic_data_array with check entries: classes and target functions. |
1467 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1467 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
1468 // R12: points directly to the first ic data array element. | 1468 // R12: points directly to the first ic data array element. |
1469 | 1469 |
1470 // Get the receiver's class ID (first read number of arguments from | 1470 // Get the receiver's class ID (first read number of arguments from |
1471 // arguments descriptor array and then access the receiver from the stack). | 1471 // arguments descriptor array and then access the receiver from the stack). |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1584 __ Bind(¬_smi); | 1584 __ Bind(¬_smi); |
1585 __ LoadClassId(RAX, RAX); | 1585 __ LoadClassId(RAX, RAX); |
1586 __ SmiTag(RAX); | 1586 __ SmiTag(RAX); |
1587 __ ret(); | 1587 __ ret(); |
1588 } | 1588 } |
1589 | 1589 |
1590 | 1590 |
1591 // Use inline cache data array to invoke the target or continue in inline | 1591 // Use inline cache data array to invoke the target or continue in inline |
1592 // cache miss handler. Stub for 1-argument check (receiver class). | 1592 // cache miss handler. Stub for 1-argument check (receiver class). |
1593 // RBX: Inline cache data object. | 1593 // RBX: Inline cache data object. |
1594 // R10: Arguments descriptor array. | |
1595 // TOS(0): Return address. | 1594 // TOS(0): Return address. |
1596 // Inline cache data object structure: | 1595 // Inline cache data object structure: |
1597 // 0: function-name | 1596 // 0: function-name |
1598 // 1: N, number of arguments checked. | 1597 // 1: N, number of arguments checked. |
1599 // 2 .. (length - 1): group of checks, each check containing: | 1598 // 2 .. (length - 1): group of checks, each check containing: |
1600 // - N classes. | 1599 // - N classes. |
1601 // - 1 target function. | 1600 // - 1 target function. |
1602 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1601 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
1603 GenerateUsageCounterIncrement(assembler, RCX); | 1602 GenerateUsageCounterIncrement(assembler, RCX); |
1604 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1603 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
1605 } | 1604 } |
1606 | 1605 |
1607 | 1606 |
1608 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1607 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
1609 GenerateUsageCounterIncrement(assembler, RCX); | 1608 GenerateUsageCounterIncrement(assembler, RCX); |
1610 GenerateNArgsCheckInlineCacheStub(assembler, 2); | 1609 GenerateNArgsCheckInlineCacheStub(assembler, 2); |
1611 } | 1610 } |
1612 | 1611 |
1613 | 1612 |
1614 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { | 1613 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { |
1615 GenerateUsageCounterIncrement(assembler, RCX); | 1614 GenerateUsageCounterIncrement(assembler, RCX); |
1616 GenerateNArgsCheckInlineCacheStub(assembler, 3); | 1615 GenerateNArgsCheckInlineCacheStub(assembler, 3); |
1617 } | 1616 } |
1618 | 1617 |
1619 // Use inline cache data array to invoke the target or continue in inline | 1618 // Use inline cache data array to invoke the target or continue in inline |
1620 // cache miss handler. Stub for 1-argument check (receiver class). | 1619 // cache miss handler. Stub for 1-argument check (receiver class). |
1621 // RDI: function which counter needs to be incremented. | 1620 // RDI: function which counter needs to be incremented. |
1622 // RBX: Inline cache data object. | 1621 // RBX: Inline cache data object. |
1623 // R10: Arguments descriptor array. | |
1624 // TOS(0): Return address. | 1622 // TOS(0): Return address. |
1625 // Inline cache data object structure: | 1623 // Inline cache data object structure: |
1626 // 0: function-name | 1624 // 0: function-name |
1627 // 1: N, number of arguments checked. | 1625 // 1: N, number of arguments checked. |
1628 // 2 .. (length - 1): group of checks, each check containing: | 1626 // 2 .. (length - 1): group of checks, each check containing: |
1629 // - N classes. | 1627 // - N classes. |
1630 // - 1 target function. | 1628 // - 1 target function. |
1631 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1629 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
1632 Assembler* assembler) { | 1630 Assembler* assembler) { |
1633 GenerateOptimizedUsageCounterIncrement(assembler); | 1631 GenerateOptimizedUsageCounterIncrement(assembler); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1676 __ pushq(raw_null); // Room for result. | 1674 __ pushq(raw_null); // Room for result. |
1677 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry); | 1675 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry); |
1678 __ popq(RAX); // Address of original. | 1676 __ popq(RAX); // Address of original. |
1679 __ popq(R10); // Restore arguments. | 1677 __ popq(R10); // Restore arguments. |
1680 __ popq(RBX); | 1678 __ popq(RBX); |
1681 __ LeaveFrame(); | 1679 __ LeaveFrame(); |
1682 __ jmp(RAX); // Jump to original stub. | 1680 __ jmp(RAX); // Jump to original stub. |
1683 } | 1681 } |
1684 | 1682 |
1685 | 1683 |
1686 // R10: Arguments descriptor array. | |
1687 // TOS(0): return address (Dart code). | 1684 // TOS(0): return address (Dart code). |
1688 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1685 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
1689 const Immediate& raw_null = | 1686 const Immediate& raw_null = |
1690 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1687 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1691 __ EnterStubFrame(); | 1688 __ EnterStubFrame(); |
1692 __ pushq(R10); // Preserve arguments descriptor. | 1689 __ pushq(R10); // Preserve arguments descriptor. |
1693 __ pushq(raw_null); // Room for result. | 1690 __ pushq(raw_null); // Room for result. |
1694 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); | 1691 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); |
1695 __ popq(RAX); // Code object. | 1692 __ popq(RAX); // Code object. |
1696 __ popq(R10); // Restore arguments descriptor. | 1693 __ popq(R10); // Restore arguments descriptor. |
(...skipping 15 matching lines...) Expand all Loading... |
1712 __ popq(RAX); | 1709 __ popq(RAX); |
1713 __ LeaveFrame(); | 1710 __ LeaveFrame(); |
1714 | 1711 |
1715 __ popq(R11); // discard return address of call to this stub. | 1712 __ popq(R11); // discard return address of call to this stub. |
1716 __ LeaveFrame(); | 1713 __ LeaveFrame(); |
1717 __ ret(); | 1714 __ ret(); |
1718 } | 1715 } |
1719 | 1716 |
1720 | 1717 |
1721 // RBX: Inline cache data array. | 1718 // RBX: Inline cache data array. |
1722 // R10: Arguments descriptor array. | |
1723 // TOS(0): return address (Dart code). | 1719 // TOS(0): return address (Dart code). |
1724 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1720 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
1725 __ EnterStubFrame(); | 1721 __ EnterStubFrame(); |
1726 __ pushq(RBX); | 1722 __ pushq(RBX); |
1727 __ pushq(R10); | |
1728 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); | 1723 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); |
1729 __ popq(R10); | |
1730 __ popq(RBX); | 1724 __ popq(RBX); |
1731 __ LeaveFrame(); | 1725 __ LeaveFrame(); |
1732 | 1726 |
1733 // Find out which dispatch stub to call. | 1727 // Find out which dispatch stub to call. |
1734 Label test_two, test_three, test_four; | 1728 Label test_two, test_three, test_four; |
1735 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); | 1729 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); |
1736 __ cmpq(RCX, Immediate(1)); | 1730 __ cmpq(RCX, Immediate(1)); |
1737 __ j(NOT_EQUAL, &test_two, Assembler::kNearJump); | 1731 __ j(NOT_EQUAL, &test_two, Assembler::kNearJump); |
1738 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); | 1732 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); |
1739 __ Bind(&test_two); | 1733 __ Bind(&test_two); |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2078 __ cmpq(left, right); | 2072 __ cmpq(left, right); |
2079 __ Bind(&done); | 2073 __ Bind(&done); |
2080 __ popq(right); | 2074 __ popq(right); |
2081 __ popq(left); | 2075 __ popq(left); |
2082 __ ret(); | 2076 __ ret(); |
2083 } | 2077 } |
2084 | 2078 |
2085 } // namespace dart | 2079 } // namespace dart |
2086 | 2080 |
2087 #endif // defined TARGET_ARCH_X64 | 2081 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |