| 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 |