OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
13 #include "vm/heap.h" | 13 #include "vm/heap.h" |
14 #include "vm/instructions.h" | 14 #include "vm/instructions.h" |
15 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
16 #include "vm/stack_frame.h" | 16 #include "vm/stack_frame.h" |
17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
18 #include "vm/tags.h" | 18 #include "vm/tags.h" |
19 | 19 |
20 #define __ assembler-> | 20 #define __ assembler-> |
21 | 21 |
22 namespace dart { | 22 namespace dart { |
23 | 23 |
24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); | 24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); |
25 DEFINE_FLAG(bool, use_slow_path, false, | 25 DEFINE_FLAG(bool, use_slow_path, false, |
26 "Set to true for debugging & verifying the slow paths."); | 26 "Set to true for debugging & verifying the slow paths."); |
27 DECLARE_FLAG(bool, trace_optimized_ic_calls); | 27 DECLARE_FLAG(bool, trace_optimized_ic_calls); |
28 DECLARE_FLAG(int, optimization_counter_threshold); | 28 DECLARE_FLAG(int, optimization_counter_threshold); |
| 29 DECLARE_FLAG(bool, support_debugger); |
29 | 30 |
30 // Input parameters: | 31 // Input parameters: |
31 // LR : return address. | 32 // LR : return address. |
32 // SP : address of last argument in argument array. | 33 // SP : address of last argument in argument array. |
33 // SP + 8*R4 - 8 : address of first argument in argument array. | 34 // SP + 8*R4 - 8 : address of first argument in argument array. |
34 // SP + 8*R4 : address of return value. | 35 // SP + 8*R4 : address of return value. |
35 // R5 : address of the runtime function to call. | 36 // R5 : address of the runtime function to call. |
36 // R4 : number of arguments to the call. | 37 // R4 : number of arguments to the call. |
37 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 38 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
38 const intptr_t isolate_offset = NativeArguments::isolate_offset(); | 39 const intptr_t isolate_offset = NativeArguments::isolate_offset(); |
(...skipping 1346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1385 kNoPP, kUnsignedWord); | 1386 kNoPP, kUnsignedWord); |
1386 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1387 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1387 __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask())); | 1388 __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask())); |
1388 __ CompareImmediate(R6, num_args, kNoPP); | 1389 __ CompareImmediate(R6, num_args, kNoPP); |
1389 __ b(&ok, EQ); | 1390 __ b(&ok, EQ); |
1390 __ Stop("Incorrect stub for IC data"); | 1391 __ Stop("Incorrect stub for IC data"); |
1391 __ Bind(&ok); | 1392 __ Bind(&ok); |
1392 } | 1393 } |
1393 #endif // DEBUG | 1394 #endif // DEBUG |
1394 | 1395 |
1395 __ Comment("Check single stepping"); | |
1396 Label stepping, done_stepping; | 1396 Label stepping, done_stepping; |
1397 __ LoadIsolate(R6, kNoPP); | 1397 if (FLAG_support_debugger) { |
1398 __ LoadFromOffset( | 1398 __ Comment("Check single stepping"); |
1399 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); | 1399 __ LoadIsolate(R6, kNoPP); |
1400 __ CompareRegisters(R6, ZR); | 1400 __ LoadFromOffset( |
1401 __ b(&stepping, NE); | 1401 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); |
1402 __ Bind(&done_stepping); | 1402 __ CompareRegisters(R6, ZR); |
| 1403 __ b(&stepping, NE); |
| 1404 __ Bind(&done_stepping); |
| 1405 } |
1403 | 1406 |
1404 __ Comment("Range feedback collection"); | 1407 __ Comment("Range feedback collection"); |
1405 Label not_smi_or_overflow; | 1408 Label not_smi_or_overflow; |
1406 if (range_collection_mode == kCollectRanges) { | 1409 if (range_collection_mode == kCollectRanges) { |
1407 ASSERT((num_args == 1) || (num_args == 2)); | 1410 ASSERT((num_args == 1) || (num_args == 2)); |
1408 if (num_args == 2) { | 1411 if (num_args == 2) { |
1409 __ ldr(R0, Address(SP, 1 * kWordSize)); | 1412 __ ldr(R0, Address(SP, 1 * kWordSize)); |
1410 __ UpdateRangeFeedback(R0, 0, R5, R1, R4, ¬_smi_or_overflow); | 1413 __ UpdateRangeFeedback(R0, 0, R5, R1, R4, ¬_smi_or_overflow); |
1411 } | 1414 } |
1412 | 1415 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1556 Label done; | 1559 Label done; |
1557 __ ldr(R5, Address(FP, kFirstLocalSlotFromFp * kWordSize)); | 1560 __ ldr(R5, Address(FP, kFirstLocalSlotFromFp * kWordSize)); |
1558 __ UpdateRangeFeedback(R0, 2, R5, R1, R4, &done); | 1561 __ UpdateRangeFeedback(R0, 2, R5, R1, R4, &done); |
1559 __ Bind(&done); | 1562 __ Bind(&done); |
1560 __ LeaveStubFrame(); | 1563 __ LeaveStubFrame(); |
1561 __ ret(); | 1564 __ ret(); |
1562 } else { | 1565 } else { |
1563 __ br(R2); | 1566 __ br(R2); |
1564 } | 1567 } |
1565 | 1568 |
1566 __ Bind(&stepping); | 1569 if (FLAG_support_debugger) { |
1567 __ EnterStubFrame(); | 1570 __ Bind(&stepping); |
1568 __ Push(R5); // Preserve IC data. | 1571 __ EnterStubFrame(); |
1569 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1572 __ Push(R5); // Preserve IC data. |
1570 __ Pop(R5); | 1573 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1571 __ LeaveStubFrame(); | 1574 __ Pop(R5); |
1572 __ b(&done_stepping); | 1575 __ LeaveStubFrame(); |
| 1576 __ b(&done_stepping); |
| 1577 } |
1573 } | 1578 } |
1574 | 1579 |
1575 | 1580 |
1576 // Use inline cache data array to invoke the target or continue in inline | 1581 // Use inline cache data array to invoke the target or continue in inline |
1577 // cache miss handler. Stub for 1-argument check (receiver class). | 1582 // cache miss handler. Stub for 1-argument check (receiver class). |
1578 // LR: return address. | 1583 // LR: return address. |
1579 // R5: inline cache data object. | 1584 // R5: inline cache data object. |
1580 // Inline cache data object structure: | 1585 // Inline cache data object structure: |
1581 // 0: function-name | 1586 // 0: function-name |
1582 // 1: N, number of arguments checked. | 1587 // 1: N, number of arguments checked. |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1690 __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask())); | 1695 __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask())); |
1691 __ CompareImmediate(R6, 0, kNoPP); | 1696 __ CompareImmediate(R6, 0, kNoPP); |
1692 __ b(&ok, EQ); | 1697 __ b(&ok, EQ); |
1693 __ Stop("Incorrect IC data for unoptimized static call"); | 1698 __ Stop("Incorrect IC data for unoptimized static call"); |
1694 __ Bind(&ok); | 1699 __ Bind(&ok); |
1695 } | 1700 } |
1696 #endif // DEBUG | 1701 #endif // DEBUG |
1697 | 1702 |
1698 // Check single stepping. | 1703 // Check single stepping. |
1699 Label stepping, done_stepping; | 1704 Label stepping, done_stepping; |
1700 __ LoadIsolate(R6, kNoPP); | 1705 if (FLAG_support_debugger) { |
1701 __ LoadFromOffset( | 1706 __ LoadIsolate(R6, kNoPP); |
1702 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); | 1707 __ LoadFromOffset( |
1703 __ CompareImmediate(R6, 0, kNoPP); | 1708 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); |
1704 __ b(&stepping, NE); | 1709 __ CompareImmediate(R6, 0, kNoPP); |
1705 __ Bind(&done_stepping); | 1710 __ b(&stepping, NE); |
| 1711 __ Bind(&done_stepping); |
| 1712 } |
1706 | 1713 |
1707 // R5: IC data object (preserved). | 1714 // R5: IC data object (preserved). |
1708 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP); | 1715 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP); |
1709 // R6: ic_data_array with entries: target functions and count. | 1716 // R6: ic_data_array with entries: target functions and count. |
1710 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); | 1717 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); |
1711 // R6: points directly to the first ic data array element. | 1718 // R6: points directly to the first ic data array element. |
1712 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1719 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1713 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1720 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1714 | 1721 |
1715 if (FLAG_optimization_counter_threshold >= 0) { | 1722 if (FLAG_optimization_counter_threshold >= 0) { |
(...skipping 11 matching lines...) Expand all Loading... |
1727 // Get function and call it, if possible. | 1734 // Get function and call it, if possible. |
1728 __ LoadFromOffset(R0, R6, target_offset, kNoPP); | 1735 __ LoadFromOffset(R0, R6, target_offset, kNoPP); |
1729 __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP); | 1736 __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP); |
1730 | 1737 |
1731 // R0: function. | 1738 // R0: function. |
1732 // R2: target instructons. | 1739 // R2: target instructons. |
1733 __ AddImmediate( | 1740 __ AddImmediate( |
1734 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); | 1741 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); |
1735 __ br(R2); | 1742 __ br(R2); |
1736 | 1743 |
1737 __ Bind(&stepping); | 1744 if (FLAG_support_debugger) { |
1738 __ EnterStubFrame(); | 1745 __ Bind(&stepping); |
1739 __ Push(R5); // Preserve IC data. | 1746 __ EnterStubFrame(); |
1740 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1747 __ Push(R5); // Preserve IC data. |
1741 __ Pop(R5); | 1748 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1742 __ LeaveStubFrame(); | 1749 __ Pop(R5); |
1743 __ b(&done_stepping); | 1750 __ LeaveStubFrame(); |
| 1751 __ b(&done_stepping); |
| 1752 } |
1744 } | 1753 } |
1745 | 1754 |
1746 | 1755 |
1747 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1756 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
1748 GenerateUsageCounterIncrement(assembler, R6); | 1757 GenerateUsageCounterIncrement(assembler, R6); |
1749 GenerateNArgsCheckInlineCacheStub( | 1758 GenerateNArgsCheckInlineCacheStub( |
1750 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, | 1759 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, |
1751 kIgnoreRanges); | 1760 kIgnoreRanges); |
1752 } | 1761 } |
1753 | 1762 |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2072 | 2081 |
2073 // Called only from unoptimized code. All relevant registers have been saved. | 2082 // Called only from unoptimized code. All relevant registers have been saved. |
2074 // LR: return address. | 2083 // LR: return address. |
2075 // SP + 4: left operand. | 2084 // SP + 4: left operand. |
2076 // SP + 0: right operand. | 2085 // SP + 0: right operand. |
2077 // Return Zero condition flag set if equal. | 2086 // Return Zero condition flag set if equal. |
2078 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 2087 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
2079 Assembler* assembler) { | 2088 Assembler* assembler) { |
2080 // Check single stepping. | 2089 // Check single stepping. |
2081 Label stepping, done_stepping; | 2090 Label stepping, done_stepping; |
2082 __ LoadIsolate(R1, kNoPP); | 2091 if (FLAG_support_debugger) { |
2083 __ LoadFromOffset( | 2092 __ LoadIsolate(R1, kNoPP); |
2084 R1, R1, Isolate::single_step_offset(), kNoPP, kUnsignedByte); | 2093 __ LoadFromOffset( |
2085 __ CompareImmediate(R1, 0, kNoPP); | 2094 R1, R1, Isolate::single_step_offset(), kNoPP, kUnsignedByte); |
2086 __ b(&stepping, NE); | 2095 __ CompareImmediate(R1, 0, kNoPP); |
2087 __ Bind(&done_stepping); | 2096 __ b(&stepping, NE); |
| 2097 __ Bind(&done_stepping); |
| 2098 } |
2088 | 2099 |
2089 const Register left = R1; | 2100 const Register left = R1; |
2090 const Register right = R0; | 2101 const Register right = R0; |
2091 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); | 2102 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); |
2092 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); | 2103 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); |
2093 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 2104 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
2094 __ ret(); | 2105 __ ret(); |
2095 | 2106 |
2096 __ Bind(&stepping); | 2107 if (FLAG_support_debugger) { |
2097 __ EnterStubFrame(); | 2108 __ Bind(&stepping); |
2098 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 2109 __ EnterStubFrame(); |
2099 __ LeaveStubFrame(); | 2110 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
2100 __ b(&done_stepping); | 2111 __ LeaveStubFrame(); |
| 2112 __ b(&done_stepping); |
| 2113 } |
2101 } | 2114 } |
2102 | 2115 |
2103 | 2116 |
2104 // Called from optimized code only. | 2117 // Called from optimized code only. |
2105 // LR: return address. | 2118 // LR: return address. |
2106 // SP + 4: left operand. | 2119 // SP + 4: left operand. |
2107 // SP + 0: right operand. | 2120 // SP + 0: right operand. |
2108 // Return Zero condition flag set if equal. | 2121 // Return Zero condition flag set if equal. |
2109 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 2122 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
2110 Assembler* assembler) { | 2123 Assembler* assembler) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2167 // Result: | 2180 // Result: |
2168 // R1: entry point. | 2181 // R1: entry point. |
2169 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2182 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2170 EmitMegamorphicLookup(assembler, R0, R1, R1); | 2183 EmitMegamorphicLookup(assembler, R0, R1, R1); |
2171 __ ret(); | 2184 __ ret(); |
2172 } | 2185 } |
2173 | 2186 |
2174 } // namespace dart | 2187 } // namespace dart |
2175 | 2188 |
2176 #endif // defined TARGET_ARCH_ARM64 | 2189 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |