| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 1505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1516 __ popq(RAX); | 1516 __ popq(RAX); |
| 1517 __ popq(RAX); | 1517 __ popq(RAX); |
| 1518 __ popq(RAX); // Get result into RAX. | 1518 __ popq(RAX); // Get result into RAX. |
| 1519 | 1519 |
| 1520 // Remove the stub frame as we are about to return. | 1520 // Remove the stub frame as we are about to return. |
| 1521 __ LeaveFrame(); | 1521 __ LeaveFrame(); |
| 1522 __ ret(); | 1522 __ ret(); |
| 1523 } | 1523 } |
| 1524 | 1524 |
| 1525 | 1525 |
| 1526 // Loads function into 'temp_reg', preserves 'ic_reg'. |
| 1527 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, |
| 1528 Register ic_reg, |
| 1529 Register temp_reg) { |
| 1530 __ movq(temp_reg, FieldAddress(ic_reg, ICData::function_offset())); |
| 1531 Label is_hot; |
| 1532 if (FlowGraphCompiler::CanOptimize()) { |
| 1533 ASSERT(FLAG_optimization_counter_threshold > 1); |
| 1534 // The usage_counter is always less than FLAG_optimization_counter_threshold |
| 1535 // except when the function gets optimized. |
| 1536 __ cmpq(FieldAddress(temp_reg, Function::usage_counter_offset()), |
| 1537 Immediate(FLAG_optimization_counter_threshold - 1)); |
| 1538 // Do not increment to equality with threshold, since a counter greater |
| 1539 // than threshold denotes a function that was already optimized. |
| 1540 // The equality should be reached only at exit of the method |
| 1541 // (return instruction). |
| 1542 __ j(EQUAL, &is_hot, Assembler::kNearJump); |
| 1543 // As long as VM has no OSR do not optimize in the middle of the function |
| 1544 // but only at exit so that we have collected all type feedback before |
| 1545 // optimizing. |
| 1546 } |
| 1547 __ incq(FieldAddress(temp_reg, Function::usage_counter_offset())); |
| 1548 __ Bind(&is_hot); |
| 1549 } |
| 1526 | 1550 |
| 1527 // Generate inline cache check for 'num_args'. | 1551 // Generate inline cache check for 'num_args'. |
| 1528 // RBX: Inline cache data object. | 1552 // RBX: Inline cache data object. |
| 1529 // R10: Arguments descriptor array. | 1553 // R10: Arguments descriptor array. |
| 1530 // TOS(0): return address | 1554 // TOS(0): return address |
| 1531 // Control flow: | 1555 // Control flow: |
| 1532 // - If receiver is null -> jump to IC miss. | 1556 // - If receiver is null -> jump to IC miss. |
| 1533 // - If receiver is Smi -> load Smi class. | 1557 // - If receiver is Smi -> load Smi class. |
| 1534 // - If receiver is not-Smi -> load receiver's class. | 1558 // - If receiver is not-Smi -> load receiver's class. |
| 1535 // - Check if 'num_args' (including receiver) match any IC data group. | 1559 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1536 // - Match found -> jump to target. | 1560 // - Match found -> jump to target. |
| 1537 // - Match not found -> jump to IC miss. | 1561 // - Match not found -> jump to IC miss. |
| 1538 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1562 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| 1539 intptr_t num_args) { | 1563 intptr_t num_args) { |
| 1540 ASSERT(num_args > 0); | 1564 ASSERT(num_args > 0); |
| 1541 #if defined(DEBUG) | 1565 #if defined(DEBUG) |
| 1542 { Label ok; | 1566 { Label ok; |
| 1543 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1567 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1544 // 'num_args_tested' is stored as an untagged int. | 1568 // 'num_args_tested' is stored as an untagged int. |
| 1545 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); | 1569 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); |
| 1546 __ cmpq(RCX, Immediate(num_args)); | 1570 __ cmpq(RCX, Immediate(num_args)); |
| 1547 __ j(EQUAL, &ok, Assembler::kNearJump); | 1571 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1548 __ Stop("Incorrect stub for IC data"); | 1572 __ Stop("Incorrect stub for IC data"); |
| 1549 __ Bind(&ok); | 1573 __ Bind(&ok); |
| 1550 } | 1574 } |
| 1551 #endif // DEBUG | 1575 #endif // DEBUG |
| 1552 | 1576 |
| 1553 __ movq(RCX, FieldAddress(RBX, ICData::function_offset())); | |
| 1554 Label is_hot; | |
| 1555 if (FlowGraphCompiler::CanOptimize()) { | |
| 1556 ASSERT(FLAG_optimization_counter_threshold > 1); | |
| 1557 // The usage_counter is always less than FLAG_optimization_counter_threshold | |
| 1558 // except when the function gets optimized. | |
| 1559 __ cmpq(FieldAddress(RCX, Function::usage_counter_offset()), | |
| 1560 Immediate(FLAG_optimization_counter_threshold - 1)); | |
| 1561 // Do not increment to equality with threshold, since a counter greater | |
| 1562 // than threshold denotes a function that was already optimized. | |
| 1563 // The equality should be reached only at exit of the method | |
| 1564 // (return instruction). | |
| 1565 __ j(EQUAL, &is_hot, Assembler::kNearJump); | |
| 1566 // As long as VM has no OSR do not optimize in the middle of the function | |
| 1567 // but only at exit so that we have collected all type feedback before | |
| 1568 // optimizing. | |
| 1569 } | |
| 1570 __ incq(FieldAddress(RCX, Function::usage_counter_offset())); | |
| 1571 __ Bind(&is_hot); | |
| 1572 | |
| 1573 // Loop that checks if there is an IC data match. | 1577 // Loop that checks if there is an IC data match. |
| 1574 Label loop, update, test, found, get_class_id_as_smi; | 1578 Label loop, update, test, found, get_class_id_as_smi; |
| 1575 // RBX: IC data object (preserved). | 1579 // RBX: IC data object (preserved). |
| 1576 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); | 1580 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
| 1577 // R12: ic_data_array with check entries: classes and target functions. | 1581 // R12: ic_data_array with check entries: classes and target functions. |
| 1578 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1582 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
| 1579 // R12: points directly to the first ic data array element. | 1583 // R12: points directly to the first ic data array element. |
| 1580 | 1584 |
| 1581 // Get the receiver's class ID (first read number of arguments from | 1585 // Get the receiver's class ID (first read number of arguments from |
| 1582 // argument descriptor array and then access the receiver from the stack). | 1586 // argument descriptor array and then access the receiver from the stack). |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1682 | 1686 |
| 1683 __ Bind(¬_smi); | 1687 __ Bind(¬_smi); |
| 1684 __ LoadClassId(RAX, RAX); | 1688 __ LoadClassId(RAX, RAX); |
| 1685 __ SmiTag(RAX); | 1689 __ SmiTag(RAX); |
| 1686 __ ret(); | 1690 __ ret(); |
| 1687 } | 1691 } |
| 1688 | 1692 |
| 1689 | 1693 |
| 1690 // Use inline cache data array to invoke the target or continue in inline | 1694 // Use inline cache data array to invoke the target or continue in inline |
| 1691 // cache miss handler. Stub for 1-argument check (receiver class). | 1695 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1692 // RCX: Inline cache data array | 1696 // RBX: Inline cache data object. |
| 1693 // RDX: Arguments array | 1697 // RDX: Arguments array. |
| 1694 // TOS(0): return address | 1698 // TOS(0): Return address. |
| 1695 // Inline cache data array structure: | 1699 // Inline cache data object structure: |
| 1696 // 0: function-name | 1700 // 0: function-name |
| 1697 // 1: N, number of arguments checked. | 1701 // 1: N, number of arguments checked. |
| 1698 // 2 .. (length - 1): group of checks, each check containing: | 1702 // 2 .. (length - 1): group of checks, each check containing: |
| 1699 // - N classes. | 1703 // - N classes. |
| 1700 // - 1 target function. | 1704 // - 1 target function. |
| 1701 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1705 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
| 1706 GenerateUsageCounterIncrement(assembler, RBX, RCX); |
| 1702 return GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1707 return GenerateNArgsCheckInlineCacheStub(assembler, 1); |
| 1703 } | 1708 } |
| 1704 | 1709 |
| 1705 | 1710 |
| 1706 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1711 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
| 1712 GenerateUsageCounterIncrement(assembler, RBX, RCX); |
| 1707 return GenerateNArgsCheckInlineCacheStub(assembler, 2); | 1713 return GenerateNArgsCheckInlineCacheStub(assembler, 2); |
| 1708 } | 1714 } |
| 1709 | 1715 |
| 1710 | 1716 |
| 1711 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { | 1717 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { |
| 1718 GenerateUsageCounterIncrement(assembler, RBX, RCX); |
| 1712 return GenerateNArgsCheckInlineCacheStub(assembler, 3); | 1719 return GenerateNArgsCheckInlineCacheStub(assembler, 3); |
| 1713 } | 1720 } |
| 1714 | 1721 |
| 1722 // Megamorphic call is currently implemented as IC call but through a stub |
| 1723 // that does not check/count function invocations. |
| 1724 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { |
| 1725 return GenerateNArgsCheckInlineCacheStub(assembler, 1); |
| 1726 } |
| 1715 | 1727 |
| 1716 // RBX: Function object. | 1728 // RBX: Function object. |
| 1717 // R10: Arguments array. | 1729 // R10: Arguments array. |
| 1718 // TOS(0): return address (Dart code). | 1730 // TOS(0): return address (Dart code). |
| 1719 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1731 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 1720 AssemblerMacros::EnterStubFrame(assembler); | 1732 AssemblerMacros::EnterStubFrame(assembler); |
| 1721 __ pushq(R10); | 1733 __ pushq(R10); |
| 1722 __ pushq(RBX); | 1734 __ pushq(RBX); |
| 1723 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); | 1735 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); |
| 1724 __ popq(RBX); | 1736 __ popq(RBX); |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2017 __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry); | 2029 __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry); |
| 2018 __ Drop(4); | 2030 __ Drop(4); |
| 2019 __ LeaveFrame(); | 2031 __ LeaveFrame(); |
| 2020 | 2032 |
| 2021 __ jmp(&compute_result, Assembler::kNearJump); | 2033 __ jmp(&compute_result, Assembler::kNearJump); |
| 2022 } | 2034 } |
| 2023 | 2035 |
| 2024 } // namespace dart | 2036 } // namespace dart |
| 2025 | 2037 |
| 2026 #endif // defined TARGET_ARCH_X64 | 2038 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |