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); | |
31 | |
32 // Input parameters: | 30 // Input parameters: |
33 // LR : return address. | 31 // LR : return address. |
34 // SP : address of last argument in argument array. | 32 // SP : address of last argument in argument array. |
35 // SP + 4*R4 - 4 : address of first argument in argument array. | 33 // SP + 4*R4 - 4 : address of first argument in argument array. |
36 // SP + 4*R4 : address of return value. | 34 // SP + 4*R4 : address of return value. |
37 // R5 : address of the runtime function to call. | 35 // R5 : address of the runtime function to call. |
38 // R4 : number of arguments to the call. | 36 // R4 : number of arguments to the call. |
39 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 37 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
40 const intptr_t isolate_offset = NativeArguments::isolate_offset(); | 38 const intptr_t isolate_offset = NativeArguments::isolate_offset(); |
41 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); | 39 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); |
(...skipping 1203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1243 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1246 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); | 1244 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); |
1247 __ CompareImmediate(R6, num_args); | 1245 __ CompareImmediate(R6, num_args); |
1248 __ b(&ok, EQ); | 1246 __ b(&ok, EQ); |
1249 __ Stop("Incorrect stub for IC data"); | 1247 __ Stop("Incorrect stub for IC data"); |
1250 __ Bind(&ok); | 1248 __ Bind(&ok); |
1251 } | 1249 } |
1252 #endif // DEBUG | 1250 #endif // DEBUG |
1253 | 1251 |
1254 Label stepping, done_stepping; | 1252 Label stepping, done_stepping; |
1255 if (FLAG_enable_debugger) { | 1253 |
1256 // Check single stepping. | 1254 // Check single stepping. |
1257 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); | 1255 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); |
1258 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); | 1256 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); |
1259 __ CompareImmediate(R6, 0); | 1257 __ CompareImmediate(R6, 0); |
1260 __ b(&stepping, NE); | 1258 __ b(&stepping, NE); |
1261 __ Bind(&done_stepping); | 1259 __ Bind(&done_stepping); |
1262 } | |
1263 | 1260 |
1264 // Load arguments descriptor into R4. | 1261 // Load arguments descriptor into R4. |
1265 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1262 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
1266 // Loop that checks if there is an IC data match. | 1263 // Loop that checks if there is an IC data match. |
1267 Label loop, update, test, found; | 1264 Label loop, update, test, found; |
1268 // R5: IC data object (preserved). | 1265 // R5: IC data object (preserved). |
1269 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); | 1266 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); |
1270 // R6: ic_data_array with check entries: classes and target functions. | 1267 // R6: ic_data_array with check entries: classes and target functions. |
1271 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1268 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); |
1272 // R6: points directly to the first ic data array element. | 1269 // R6: points directly to the first ic data array element. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1356 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1353 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
1357 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. | 1354 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. |
1358 __ StoreToOffset(kWord, R1, R6, count_offset); | 1355 __ StoreToOffset(kWord, R1, R6, count_offset); |
1359 | 1356 |
1360 __ Bind(&call_target_function); | 1357 __ Bind(&call_target_function); |
1361 // R0: target function. | 1358 // R0: target function. |
1362 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 1359 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); |
1363 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | 1360 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
1364 __ bx(R2); | 1361 __ bx(R2); |
1365 | 1362 |
1366 if (FLAG_enable_debugger) { | 1363 __ Bind(&stepping); |
1367 __ Bind(&stepping); | 1364 __ EnterStubFrame(); |
1368 __ EnterStubFrame(); | 1365 __ Push(R5); // Preserve IC data. |
1369 __ Push(R5); // Preserve IC data. | 1366 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1370 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1367 __ Pop(R5); |
1371 __ Pop(R5); | 1368 __ LeaveStubFrame(); |
1372 __ LeaveStubFrame(); | 1369 __ b(&done_stepping); |
1373 __ b(&done_stepping); | |
1374 } | |
1375 } | 1370 } |
1376 | 1371 |
1377 | 1372 |
1378 // Use inline cache data array to invoke the target or continue in inline | 1373 // Use inline cache data array to invoke the target or continue in inline |
1379 // cache miss handler. Stub for 1-argument check (receiver class). | 1374 // cache miss handler. Stub for 1-argument check (receiver class). |
1380 // LR: return address. | 1375 // LR: return address. |
1381 // R5: inline cache data object. | 1376 // R5: inline cache data object. |
1382 // Inline cache data object structure: | 1377 // Inline cache data object structure: |
1383 // 0: function-name | 1378 // 0: function-name |
1384 // 1: N, number of arguments checked. | 1379 // 1: N, number of arguments checked. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1448 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); | 1443 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); |
1449 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1444 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1450 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); | 1445 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); |
1451 __ CompareImmediate(R6, 0); | 1446 __ CompareImmediate(R6, 0); |
1452 __ b(&ok, EQ); | 1447 __ b(&ok, EQ); |
1453 __ Stop("Incorrect IC data for unoptimized static call"); | 1448 __ Stop("Incorrect IC data for unoptimized static call"); |
1454 __ Bind(&ok); | 1449 __ Bind(&ok); |
1455 } | 1450 } |
1456 #endif // DEBUG | 1451 #endif // DEBUG |
1457 | 1452 |
1458 if (FLAG_enable_debugger) { | 1453 // Check single stepping. |
1459 // Check single stepping. | 1454 Label not_stepping; |
1460 Label not_stepping; | 1455 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); |
1461 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); | 1456 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); |
1462 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); | 1457 __ CompareImmediate(R6, 0); |
1463 __ CompareImmediate(R6, 0); | 1458 __ b(¬_stepping, EQ); |
1464 __ b(¬_stepping, EQ); | 1459 __ EnterStubFrame(); |
1465 __ EnterStubFrame(); | 1460 __ Push(R5); // Preserve IC data. |
1466 __ Push(R5); // Preserve IC data. | 1461 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1467 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1462 __ Pop(R5); |
1468 __ Pop(R5); | 1463 __ LeaveStubFrame(); |
1469 __ LeaveStubFrame(); | 1464 __ Bind(¬_stepping); |
1470 __ Bind(¬_stepping); | |
1471 } | |
1472 | 1465 |
1473 // R5: IC data object (preserved). | 1466 // R5: IC data object (preserved). |
1474 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); | 1467 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); |
1475 // R6: ic_data_array with entries: target functions and count. | 1468 // R6: ic_data_array with entries: target functions and count. |
1476 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1469 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); |
1477 // R6: points directly to the first ic data array element. | 1470 // R6: points directly to the first ic data array element. |
1478 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1471 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1479 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1472 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1480 | 1473 |
1481 // Increment count for this call. | 1474 // Increment count for this call. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1565 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1558 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1566 __ PopList((1 << R0)); | 1559 __ PopList((1 << R0)); |
1567 __ LeaveStubFrame(); | 1560 __ LeaveStubFrame(); |
1568 __ bx(R0); | 1561 __ bx(R0); |
1569 } | 1562 } |
1570 | 1563 |
1571 | 1564 |
1572 // Called only from unoptimized code. All relevant registers have been saved. | 1565 // Called only from unoptimized code. All relevant registers have been saved. |
1573 void StubCode::GenerateDebugStepCheckStub( | 1566 void StubCode::GenerateDebugStepCheckStub( |
1574 Assembler* assembler) { | 1567 Assembler* assembler) { |
1575 if (FLAG_enable_debugger) { | 1568 // Check single stepping. |
1576 // Check single stepping. | 1569 Label not_stepping; |
1577 Label not_stepping; | 1570 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); |
1578 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); | 1571 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); |
1579 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); | 1572 __ CompareImmediate(R1, 0); |
1580 __ CompareImmediate(R1, 0); | 1573 __ b(¬_stepping, EQ); |
1581 __ b(¬_stepping, EQ); | 1574 __ EnterStubFrame(); |
1582 __ EnterStubFrame(); | 1575 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1583 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1576 __ LeaveStubFrame(); |
1584 __ LeaveStubFrame(); | 1577 __ Bind(¬_stepping); |
1585 __ Bind(¬_stepping); | 1578 |
1586 } | |
1587 __ Ret(); | 1579 __ Ret(); |
1588 } | 1580 } |
1589 | 1581 |
1590 | 1582 |
1591 // Used to check class and type arguments. Arguments passed in registers: | 1583 // Used to check class and type arguments. Arguments passed in registers: |
1592 // LR: return address. | 1584 // LR: return address. |
1593 // R0: instance (must be preserved). | 1585 // R0: instance (must be preserved). |
1594 // R1: instantiator type arguments or NULL. | 1586 // R1: instantiator type arguments or NULL. |
1595 // R2: cache array. | 1587 // R2: cache array. |
1596 // Result in R1: null -> not found, otherwise result (true or false). | 1588 // Result in R1: null -> not found, otherwise result (true or false). |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1824 } | 1816 } |
1825 | 1817 |
1826 | 1818 |
1827 // Called only from unoptimized code. All relevant registers have been saved. | 1819 // Called only from unoptimized code. All relevant registers have been saved. |
1828 // LR: return address. | 1820 // LR: return address. |
1829 // SP + 4: left operand. | 1821 // SP + 4: left operand. |
1830 // SP + 0: right operand. | 1822 // SP + 0: right operand. |
1831 // Return Zero condition flag set if equal. | 1823 // Return Zero condition flag set if equal. |
1832 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 1824 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
1833 Assembler* assembler) { | 1825 Assembler* assembler) { |
1834 if (FLAG_enable_debugger) { | 1826 // Check single stepping. |
1835 // Check single stepping. | 1827 Label not_stepping; |
1836 Label not_stepping; | 1828 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); |
1837 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); | 1829 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); |
1838 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); | 1830 __ CompareImmediate(R1, 0); |
1839 __ CompareImmediate(R1, 0); | 1831 __ b(¬_stepping, EQ); |
1840 __ b(¬_stepping, EQ); | 1832 __ EnterStubFrame(); |
1841 __ EnterStubFrame(); | 1833 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1842 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1834 __ LeaveStubFrame(); |
1843 __ LeaveStubFrame(); | 1835 __ Bind(¬_stepping); |
1844 __ Bind(¬_stepping); | |
1845 } | |
1846 | 1836 |
1847 const Register temp = R2; | 1837 const Register temp = R2; |
1848 const Register left = R1; | 1838 const Register left = R1; |
1849 const Register right = R0; | 1839 const Register right = R0; |
1850 __ ldr(left, Address(SP, 1 * kWordSize)); | 1840 __ ldr(left, Address(SP, 1 * kWordSize)); |
1851 __ ldr(right, Address(SP, 0 * kWordSize)); | 1841 __ ldr(right, Address(SP, 0 * kWordSize)); |
1852 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1842 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
1853 __ Ret(); | 1843 __ Ret(); |
1854 } | 1844 } |
1855 | 1845 |
(...skipping 10 matching lines...) Expand all Loading... |
1866 const Register right = R0; | 1856 const Register right = R0; |
1867 __ ldr(left, Address(SP, 1 * kWordSize)); | 1857 __ ldr(left, Address(SP, 1 * kWordSize)); |
1868 __ ldr(right, Address(SP, 0 * kWordSize)); | 1858 __ ldr(right, Address(SP, 0 * kWordSize)); |
1869 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1859 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
1870 __ Ret(); | 1860 __ Ret(); |
1871 } | 1861 } |
1872 | 1862 |
1873 } // namespace dart | 1863 } // namespace dart |
1874 | 1864 |
1875 #endif // defined TARGET_ARCH_ARM | 1865 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |