| 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" |
| (...skipping 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1444 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1444 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1445 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); | 1445 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); |
| 1446 __ CompareImmediate(R6, 0); | 1446 __ CompareImmediate(R6, 0); |
| 1447 __ b(&ok, EQ); | 1447 __ b(&ok, EQ); |
| 1448 __ Stop("Incorrect IC data for unoptimized static call"); | 1448 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1449 __ Bind(&ok); | 1449 __ Bind(&ok); |
| 1450 } | 1450 } |
| 1451 #endif // DEBUG | 1451 #endif // DEBUG |
| 1452 | 1452 |
| 1453 // Check single stepping. | 1453 // Check single stepping. |
| 1454 Label not_stepping; | 1454 Label stepping, done_stepping; |
| 1455 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); | 1455 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); |
| 1456 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); | 1456 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); |
| 1457 __ CompareImmediate(R6, 0); | 1457 __ CompareImmediate(R6, 0); |
| 1458 __ b(¬_stepping, EQ); | 1458 __ b(&stepping, NE); |
| 1459 __ EnterStubFrame(); | 1459 __ Bind(&done_stepping); |
| 1460 __ Push(R5); // Preserve IC data. | |
| 1461 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | |
| 1462 __ Pop(R5); | |
| 1463 __ LeaveStubFrame(); | |
| 1464 __ Bind(¬_stepping); | |
| 1465 | 1460 |
| 1466 // R5: IC data object (preserved). | 1461 // R5: IC data object (preserved). |
| 1467 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); | 1462 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); |
| 1468 // R6: ic_data_array with entries: target functions and count. | 1463 // R6: ic_data_array with entries: target functions and count. |
| 1469 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1464 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); |
| 1470 // R6: points directly to the first ic data array element. | 1465 // R6: points directly to the first ic data array element. |
| 1471 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1466 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1472 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1467 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1473 | 1468 |
| 1474 // Increment count for this call. | 1469 // Increment count for this call. |
| 1475 Label increment_done; | |
| 1476 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1470 __ LoadFromOffset(kWord, R1, R6, count_offset); |
| 1477 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1471 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
| 1472 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. |
| 1478 __ StoreToOffset(kWord, R1, R6, count_offset); | 1473 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1479 __ b(&increment_done, VC); // No overflow. | |
| 1480 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); | |
| 1481 __ StoreToOffset(kWord, R1, R6, count_offset); | |
| 1482 __ Bind(&increment_done); | |
| 1483 | 1474 |
| 1484 // Load arguments descriptor into R4. | 1475 // Load arguments descriptor into R4. |
| 1485 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1476 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
| 1486 | 1477 |
| 1487 // Get function and call it, if possible. | 1478 // Get function and call it, if possible. |
| 1488 __ LoadFromOffset(kWord, R0, R6, target_offset); | 1479 __ LoadFromOffset(kWord, R0, R6, target_offset); |
| 1489 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 1480 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); |
| 1490 | 1481 |
| 1491 // R0: function. | 1482 // R0: function. |
| 1492 // R2: target instructions. | 1483 // R2: target instructions. |
| 1493 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | 1484 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1494 __ bx(R2); | 1485 __ bx(R2); |
| 1486 |
| 1487 __ Bind(&stepping); |
| 1488 __ EnterStubFrame(); |
| 1489 __ Push(R5); // Preserve IC data. |
| 1490 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1491 __ Pop(R5); |
| 1492 __ LeaveStubFrame(); |
| 1493 __ b(&done_stepping); |
| 1495 } | 1494 } |
| 1496 | 1495 |
| 1497 | 1496 |
| 1498 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1497 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1499 GenerateUsageCounterIncrement(assembler, R6); | 1498 GenerateUsageCounterIncrement(assembler, R6); |
| 1500 GenerateNArgsCheckInlineCacheStub( | 1499 GenerateNArgsCheckInlineCacheStub( |
| 1501 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); | 1500 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); |
| 1502 } | 1501 } |
| 1503 | 1502 |
| 1504 | 1503 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1559 __ PopList((1 << R0)); | 1558 __ PopList((1 << R0)); |
| 1560 __ LeaveStubFrame(); | 1559 __ LeaveStubFrame(); |
| 1561 __ bx(R0); | 1560 __ bx(R0); |
| 1562 } | 1561 } |
| 1563 | 1562 |
| 1564 | 1563 |
| 1565 // Called only from unoptimized code. All relevant registers have been saved. | 1564 // Called only from unoptimized code. All relevant registers have been saved. |
| 1566 void StubCode::GenerateDebugStepCheckStub( | 1565 void StubCode::GenerateDebugStepCheckStub( |
| 1567 Assembler* assembler) { | 1566 Assembler* assembler) { |
| 1568 // Check single stepping. | 1567 // Check single stepping. |
| 1569 Label not_stepping; | 1568 Label stepping, done_stepping; |
| 1570 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); | 1569 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); |
| 1571 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); | 1570 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); |
| 1572 __ CompareImmediate(R1, 0); | 1571 __ CompareImmediate(R1, 0); |
| 1573 __ b(¬_stepping, EQ); | 1572 __ b(&stepping, NE); |
| 1573 __ Bind(&done_stepping); |
| 1574 __ Ret(); |
| 1575 |
| 1576 __ Bind(&stepping); |
| 1574 __ EnterStubFrame(); | 1577 __ EnterStubFrame(); |
| 1575 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1578 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1576 __ LeaveStubFrame(); | 1579 __ LeaveStubFrame(); |
| 1577 __ Bind(¬_stepping); | 1580 __ b(&done_stepping); |
| 1578 | |
| 1579 __ Ret(); | |
| 1580 } | 1581 } |
| 1581 | 1582 |
| 1582 | 1583 |
| 1583 // Used to check class and type arguments. Arguments passed in registers: | 1584 // Used to check class and type arguments. Arguments passed in registers: |
| 1584 // LR: return address. | 1585 // LR: return address. |
| 1585 // R0: instance (must be preserved). | 1586 // R0: instance (must be preserved). |
| 1586 // R1: instantiator type arguments or NULL. | 1587 // R1: instantiator type arguments or NULL. |
| 1587 // R2: cache array. | 1588 // R2: cache array. |
| 1588 // Result in R1: null -> not found, otherwise result (true or false). | 1589 // Result in R1: null -> not found, otherwise result (true or false). |
| 1589 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1590 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1817 | 1818 |
| 1818 | 1819 |
| 1819 // Called only from unoptimized code. All relevant registers have been saved. | 1820 // Called only from unoptimized code. All relevant registers have been saved. |
| 1820 // LR: return address. | 1821 // LR: return address. |
| 1821 // SP + 4: left operand. | 1822 // SP + 4: left operand. |
| 1822 // SP + 0: right operand. | 1823 // SP + 0: right operand. |
| 1823 // Return Zero condition flag set if equal. | 1824 // Return Zero condition flag set if equal. |
| 1824 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 1825 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 1825 Assembler* assembler) { | 1826 Assembler* assembler) { |
| 1826 // Check single stepping. | 1827 // Check single stepping. |
| 1827 Label not_stepping; | 1828 Label stepping, done_stepping; |
| 1828 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); | 1829 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); |
| 1829 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); | 1830 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); |
| 1830 __ CompareImmediate(R1, 0); | 1831 __ CompareImmediate(R1, 0); |
| 1831 __ b(¬_stepping, EQ); | 1832 __ b(&stepping, NE); |
| 1832 __ EnterStubFrame(); | 1833 __ Bind(&done_stepping); |
| 1833 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | |
| 1834 __ LeaveStubFrame(); | |
| 1835 __ Bind(¬_stepping); | |
| 1836 | 1834 |
| 1837 const Register temp = R2; | 1835 const Register temp = R2; |
| 1838 const Register left = R1; | 1836 const Register left = R1; |
| 1839 const Register right = R0; | 1837 const Register right = R0; |
| 1840 __ ldr(left, Address(SP, 1 * kWordSize)); | 1838 __ ldr(left, Address(SP, 1 * kWordSize)); |
| 1841 __ ldr(right, Address(SP, 0 * kWordSize)); | 1839 __ ldr(right, Address(SP, 0 * kWordSize)); |
| 1842 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1840 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 1843 __ Ret(); | 1841 __ Ret(); |
| 1842 |
| 1843 __ Bind(&stepping); |
| 1844 __ EnterStubFrame(); |
| 1845 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1846 __ LeaveStubFrame(); |
| 1847 __ b(&done_stepping); |
| 1844 } | 1848 } |
| 1845 | 1849 |
| 1846 | 1850 |
| 1847 // Called from optimized code only. | 1851 // Called from optimized code only. |
| 1848 // LR: return address. | 1852 // LR: return address. |
| 1849 // SP + 4: left operand. | 1853 // SP + 4: left operand. |
| 1850 // SP + 0: right operand. | 1854 // SP + 0: right operand. |
| 1851 // Return Zero condition flag set if equal. | 1855 // Return Zero condition flag set if equal. |
| 1852 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 1856 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
| 1853 Assembler* assembler) { | 1857 Assembler* assembler) { |
| 1854 const Register temp = R2; | 1858 const Register temp = R2; |
| 1855 const Register left = R1; | 1859 const Register left = R1; |
| 1856 const Register right = R0; | 1860 const Register right = R0; |
| 1857 __ ldr(left, Address(SP, 1 * kWordSize)); | 1861 __ ldr(left, Address(SP, 1 * kWordSize)); |
| 1858 __ ldr(right, Address(SP, 0 * kWordSize)); | 1862 __ ldr(right, Address(SP, 0 * kWordSize)); |
| 1859 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1863 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 1860 __ Ret(); | 1864 __ Ret(); |
| 1861 } | 1865 } |
| 1862 | 1866 |
| 1863 } // namespace dart | 1867 } // namespace dart |
| 1864 | 1868 |
| 1865 #endif // defined TARGET_ARCH_ARM | 1869 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |