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_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
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/cpu.h" | 10 #include "vm/cpu.h" |
11 #include "vm/compiler.h" | 11 #include "vm/compiler.h" |
12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
13 #include "vm/flow_graph_compiler.h" | 13 #include "vm/flow_graph_compiler.h" |
14 #include "vm/heap.h" | 14 #include "vm/heap.h" |
15 #include "vm/instructions.h" | 15 #include "vm/instructions.h" |
16 #include "vm/object_store.h" | 16 #include "vm/object_store.h" |
17 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
18 #include "vm/stub_code.h" | 18 #include "vm/stub_code.h" |
19 #include "vm/tags.h" | 19 #include "vm/tags.h" |
20 | 20 |
21 #define __ assembler-> | 21 #define __ assembler-> |
22 | 22 |
23 namespace dart { | 23 namespace dart { |
24 | 24 |
25 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); | 25 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); |
26 DEFINE_FLAG(bool, use_slow_path, false, | 26 DEFINE_FLAG(bool, use_slow_path, false, |
27 "Set to true for debugging & verifying the slow paths."); | 27 "Set to true for debugging & verifying the slow paths."); |
28 DECLARE_FLAG(bool, trace_optimized_ic_calls); | 28 DECLARE_FLAG(bool, trace_optimized_ic_calls); |
29 | 29 |
| 30 DECLARE_FLAG(bool, enable_debugger); |
30 | 31 |
31 // Input parameters: | 32 // Input parameters: |
32 // LR : return address. | 33 // LR : return address. |
33 // SP : address of last argument in argument array. | 34 // SP : address of last argument in argument array. |
34 // SP + 4*R4 - 4 : address of first argument in argument array. | 35 // SP + 4*R4 - 4 : address of first argument in argument array. |
35 // SP + 4*R4 : address of return value. | 36 // SP + 4*R4 : address of return value. |
36 // R5 : address of the runtime function to call. | 37 // R5 : address of the runtime function to call. |
37 // R4 : number of arguments to the call. | 38 // R4 : number of arguments to the call. |
38 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 39 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
39 const intptr_t isolate_offset = NativeArguments::isolate_offset(); | 40 const intptr_t isolate_offset = NativeArguments::isolate_offset(); |
(...skipping 1221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1261 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); | 1262 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); |
1262 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1263 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1263 __ and_(R6, R6, ShifterOperand(ICData::NumArgsTestedMask())); | 1264 __ and_(R6, R6, ShifterOperand(ICData::NumArgsTestedMask())); |
1264 __ CompareImmediate(R6, num_args); | 1265 __ CompareImmediate(R6, num_args); |
1265 __ b(&ok, EQ); | 1266 __ b(&ok, EQ); |
1266 __ Stop("Incorrect stub for IC data"); | 1267 __ Stop("Incorrect stub for IC data"); |
1267 __ Bind(&ok); | 1268 __ Bind(&ok); |
1268 } | 1269 } |
1269 #endif // DEBUG | 1270 #endif // DEBUG |
1270 | 1271 |
1271 // Check single stepping. | 1272 if (FLAG_enable_debugger) { |
1272 Label not_stepping; | 1273 // Check single stepping. |
1273 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); | 1274 Label not_stepping; |
1274 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); | 1275 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); |
1275 __ CompareImmediate(R6, 0); | 1276 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); |
1276 __ b(¬_stepping, EQ); | 1277 __ CompareImmediate(R6, 0); |
1277 __ EnterStubFrame(); | 1278 __ b(¬_stepping, EQ); |
1278 __ Push(R5); // Preserve IC data. | 1279 __ EnterStubFrame(); |
1279 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1280 __ Push(R5); // Preserve IC data. |
1280 __ Pop(R5); | 1281 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1281 __ LeaveStubFrame(); | 1282 __ Pop(R5); |
1282 __ Bind(¬_stepping); | 1283 __ LeaveStubFrame(); |
| 1284 __ Bind(¬_stepping); |
| 1285 } |
1283 | 1286 |
1284 // Load arguments descriptor into R4. | 1287 // Load arguments descriptor into R4. |
1285 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1288 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
1286 // Preserve return address, since LR is needed for subroutine call. | 1289 // Preserve return address, since LR is needed for subroutine call. |
1287 __ mov(R8, ShifterOperand(LR)); | 1290 __ mov(R8, ShifterOperand(LR)); |
1288 // Loop that checks if there is an IC data match. | 1291 // Loop that checks if there is an IC data match. |
1289 Label loop, update, test, found, get_class_id_as_smi; | 1292 Label loop, update, test, found, get_class_id_as_smi; |
1290 // R5: IC data object (preserved). | 1293 // R5: IC data object (preserved). |
1291 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); | 1294 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); |
1292 // R6: ic_data_array with check entries: classes and target functions. | 1295 // R6: ic_data_array with check entries: classes and target functions. |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1476 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); | 1479 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); |
1477 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1480 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1478 __ and_(R6, R6, ShifterOperand(ICData::NumArgsTestedMask())); | 1481 __ and_(R6, R6, ShifterOperand(ICData::NumArgsTestedMask())); |
1479 __ CompareImmediate(R6, 0); | 1482 __ CompareImmediate(R6, 0); |
1480 __ b(&ok, EQ); | 1483 __ b(&ok, EQ); |
1481 __ Stop("Incorrect IC data for unoptimized static call"); | 1484 __ Stop("Incorrect IC data for unoptimized static call"); |
1482 __ Bind(&ok); | 1485 __ Bind(&ok); |
1483 } | 1486 } |
1484 #endif // DEBUG | 1487 #endif // DEBUG |
1485 | 1488 |
1486 // Check single stepping. | 1489 if (FLAG_enable_debugger) { |
1487 Label not_stepping; | 1490 // Check single stepping. |
1488 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); | 1491 Label not_stepping; |
1489 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); | 1492 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); |
1490 __ CompareImmediate(R6, 0); | 1493 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); |
1491 __ b(¬_stepping, EQ); | 1494 __ CompareImmediate(R6, 0); |
1492 __ EnterStubFrame(); | 1495 __ b(¬_stepping, EQ); |
1493 __ Push(R5); // Preserve IC data. | 1496 __ EnterStubFrame(); |
1494 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1497 __ Push(R5); // Preserve IC data. |
1495 __ Pop(R5); | 1498 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1496 __ LeaveStubFrame(); | 1499 __ Pop(R5); |
1497 __ Bind(¬_stepping); | 1500 __ LeaveStubFrame(); |
| 1501 __ Bind(¬_stepping); |
| 1502 } |
1498 | 1503 |
1499 // R5: IC data object (preserved). | 1504 // R5: IC data object (preserved). |
1500 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); | 1505 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); |
1501 // R6: ic_data_array with entries: target functions and count. | 1506 // R6: ic_data_array with entries: target functions and count. |
1502 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1507 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); |
1503 // R6: points directly to the first ic data array element. | 1508 // R6: points directly to the first ic data array element. |
1504 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1509 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1505 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1510 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1506 | 1511 |
1507 // Increment count for this call. | 1512 // Increment count for this call. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1565 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1570 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1566 __ PopList((1 << R0) | (1 << R4) | (1 << R5)); | 1571 __ PopList((1 << R0) | (1 << R4) | (1 << R5)); |
1567 __ LeaveStubFrame(); | 1572 __ LeaveStubFrame(); |
1568 __ bx(R0); | 1573 __ bx(R0); |
1569 } | 1574 } |
1570 | 1575 |
1571 | 1576 |
1572 // Called only from unoptimized code. All relevant registers have been saved. | 1577 // Called only from unoptimized code. All relevant registers have been saved. |
1573 void StubCode::GenerateDebugStepCheckStub( | 1578 void StubCode::GenerateDebugStepCheckStub( |
1574 Assembler* assembler) { | 1579 Assembler* assembler) { |
1575 // Check single stepping. | 1580 if (FLAG_enable_debugger) { |
1576 Label not_stepping; | 1581 // Check single stepping. |
1577 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); | 1582 Label not_stepping; |
1578 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); | 1583 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); |
1579 __ CompareImmediate(R1, 0); | 1584 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); |
1580 __ b(¬_stepping, EQ); | 1585 __ CompareImmediate(R1, 0); |
1581 __ EnterStubFrame(); | 1586 __ b(¬_stepping, EQ); |
1582 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1587 __ EnterStubFrame(); |
1583 __ LeaveStubFrame(); | 1588 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1584 __ Bind(¬_stepping); | 1589 __ LeaveStubFrame(); |
| 1590 __ Bind(¬_stepping); |
| 1591 } |
1585 __ Ret(); | 1592 __ Ret(); |
1586 } | 1593 } |
1587 | 1594 |
1588 | 1595 |
1589 // Used to check class and type arguments. Arguments passed in registers: | 1596 // Used to check class and type arguments. Arguments passed in registers: |
1590 // LR: return address. | 1597 // LR: return address. |
1591 // R0: instance (must be preserved). | 1598 // R0: instance (must be preserved). |
1592 // R1: instantiator type arguments or NULL. | 1599 // R1: instantiator type arguments or NULL. |
1593 // R2: cache array. | 1600 // R2: cache array. |
1594 // Result in R1: null -> not found, otherwise result (true or false). | 1601 // Result in R1: null -> not found, otherwise result (true or false). |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1814 } | 1821 } |
1815 | 1822 |
1816 | 1823 |
1817 // Called only from unoptimized code. All relevant registers have been saved. | 1824 // Called only from unoptimized code. All relevant registers have been saved. |
1818 // LR: return address. | 1825 // LR: return address. |
1819 // SP + 4: left operand. | 1826 // SP + 4: left operand. |
1820 // SP + 0: right operand. | 1827 // SP + 0: right operand. |
1821 // Return Zero condition flag set if equal. | 1828 // Return Zero condition flag set if equal. |
1822 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 1829 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
1823 Assembler* assembler) { | 1830 Assembler* assembler) { |
1824 // Check single stepping. | 1831 if (FLAG_enable_debugger) { |
1825 Label not_stepping; | 1832 // Check single stepping. |
1826 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); | 1833 Label not_stepping; |
1827 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); | 1834 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); |
1828 __ CompareImmediate(R1, 0); | 1835 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); |
1829 __ b(¬_stepping, EQ); | 1836 __ CompareImmediate(R1, 0); |
1830 __ EnterStubFrame(); | 1837 __ b(¬_stepping, EQ); |
1831 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1838 __ EnterStubFrame(); |
1832 __ LeaveStubFrame(); | 1839 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1833 __ Bind(¬_stepping); | 1840 __ LeaveStubFrame(); |
| 1841 __ Bind(¬_stepping); |
| 1842 } |
1834 | 1843 |
1835 const Register temp = R2; | 1844 const Register temp = R2; |
1836 const Register left = R1; | 1845 const Register left = R1; |
1837 const Register right = R0; | 1846 const Register right = R0; |
1838 __ ldr(left, Address(SP, 1 * kWordSize)); | 1847 __ ldr(left, Address(SP, 1 * kWordSize)); |
1839 __ ldr(right, Address(SP, 0 * kWordSize)); | 1848 __ ldr(right, Address(SP, 0 * kWordSize)); |
1840 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1849 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
1841 __ Ret(); | 1850 __ Ret(); |
1842 } | 1851 } |
1843 | 1852 |
(...skipping 10 matching lines...) Expand all Loading... |
1854 const Register right = R0; | 1863 const Register right = R0; |
1855 __ ldr(left, Address(SP, 1 * kWordSize)); | 1864 __ ldr(left, Address(SP, 1 * kWordSize)); |
1856 __ ldr(right, Address(SP, 0 * kWordSize)); | 1865 __ ldr(right, Address(SP, 0 * kWordSize)); |
1857 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1866 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
1858 __ Ret(); | 1867 __ Ret(); |
1859 } | 1868 } |
1860 | 1869 |
1861 } // namespace dart | 1870 } // namespace dart |
1862 | 1871 |
1863 #endif // defined TARGET_ARCH_ARM | 1872 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |