| 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/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 __ b(¬_closure, EQ); // Not a closure, but a smi. | 786 __ b(¬_closure, EQ); // Not a closure, but a smi. |
| 787 // Verify that the class of the object is a closure class by checking that | 787 // Verify that the class of the object is a closure class by checking that |
| 788 // class.signature_function() is not null. | 788 // class.signature_function() is not null. |
| 789 __ LoadClass(R0, R1, R2); | 789 __ LoadClass(R0, R1, R2); |
| 790 __ ldr(R0, FieldAddress(R0, Class::signature_function_offset())); | 790 __ ldr(R0, FieldAddress(R0, Class::signature_function_offset())); |
| 791 __ cmp(R0, ShifterOperand(R8)); // R8 is raw null. | 791 __ cmp(R0, ShifterOperand(R8)); // R8 is raw null. |
| 792 // Actual class is not a closure class. | 792 // Actual class is not a closure class. |
| 793 __ b(¬_closure, EQ); | 793 __ b(¬_closure, EQ); |
| 794 | 794 |
| 795 // R0 is just the signature function. Load the actual closure function. | 795 // R0 is just the signature function. Load the actual closure function. |
| 796 __ ldr(R2, FieldAddress(R1, Closure::function_offset())); | 796 __ ldr(R0, FieldAddress(R1, Closure::function_offset())); |
| 797 | 797 |
| 798 // Load closure context in CTX; note that CTX has already been preserved. | 798 // Load closure context in CTX; note that CTX has already been preserved. |
| 799 __ ldr(CTX, FieldAddress(R1, Closure::context_offset())); | 799 __ ldr(CTX, FieldAddress(R1, Closure::context_offset())); |
| 800 | 800 |
| 801 // Load closure function code in R0. | 801 // R4: Arguments descriptor. |
| 802 __ ldr(R0, FieldAddress(R2, Function::code_offset())); | 802 // R0: Function. |
| 803 __ cmp(R0, ShifterOperand(R8)); // R8 is raw null. | 803 __ ldr(R2, FieldAddress(R0, Function::code_offset())); |
| 804 Label function_compiled; | |
| 805 __ b(&function_compiled, NE); | |
| 806 | 804 |
| 807 // Create a stub frame as we are pushing some objects on the stack before | 805 // R2: code. |
| 808 // calling into the runtime. | 806 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); |
| 809 __ EnterStubFrame(); | 807 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 810 | 808 __ bx(R2); |
| 811 // Preserve arguments descriptor array and read-only function object argument. | |
| 812 __ PushList((1 << R2) | (1 << R4)); | |
| 813 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | |
| 814 // Restore arguments descriptor array and read-only function object argument. | |
| 815 __ PopList((1 << R2) | (1 << R4)); | |
| 816 // Restore R0. | |
| 817 __ ldr(R0, FieldAddress(R2, Function::code_offset())); | |
| 818 | |
| 819 // Remove the stub frame as we are about to jump to the closure function. | |
| 820 __ LeaveStubFrame(); | |
| 821 | |
| 822 __ Bind(&function_compiled); | |
| 823 // R0: code. | |
| 824 // R4: arguments descriptor array. | |
| 825 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); | |
| 826 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); | |
| 827 __ bx(R0); | |
| 828 | 809 |
| 829 __ Bind(¬_closure); | 810 __ Bind(¬_closure); |
| 830 // Call runtime to attempt to resolve and invoke a call method on a | 811 // Call runtime to attempt to resolve and invoke a call method on a |
| 831 // non-closure object, passing the non-closure object and its arguments array, | 812 // non-closure object, passing the non-closure object and its arguments array, |
| 832 // returning here. | 813 // returning here. |
| 833 // If no call method exists, throw a NoSuchMethodError. | 814 // If no call method exists, throw a NoSuchMethodError. |
| 834 // R1: non-closure object. | 815 // R1: non-closure object. |
| 835 // R4: arguments descriptor array. | 816 // R4: arguments descriptor array. |
| 836 | 817 |
| 837 // Create a stub frame as we are pushing some objects on the stack before | 818 // Create a stub frame as we are pushing some objects on the stack before |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1505 __ LoadFromOffset(kWord, R0, R6, target_offset); | 1486 __ LoadFromOffset(kWord, R0, R6, target_offset); |
| 1506 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1487 __ LoadFromOffset(kWord, R1, R6, count_offset); |
| 1507 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); | 1488 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); |
| 1508 __ StoreToOffset(kWord, R1, R6, count_offset); | 1489 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1509 __ b(&call_target_function, VC); // No overflow. | 1490 __ b(&call_target_function, VC); // No overflow. |
| 1510 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); | 1491 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); |
| 1511 __ StoreToOffset(kWord, R1, R6, count_offset); | 1492 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1512 | 1493 |
| 1513 __ Bind(&call_target_function); | 1494 __ Bind(&call_target_function); |
| 1514 // R0: target function. | 1495 // R0: target function. |
| 1515 __ ldr(R1, FieldAddress(R0, Function::code_offset())); | 1496 __ ldr(R2, FieldAddress(R0, Function::code_offset())); |
| 1516 if (FLAG_collect_code) { | 1497 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); |
| 1517 // If we are collecting code, the code object may be null. | 1498 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1518 Label is_compiled; | 1499 __ bx(R2); |
| 1519 __ CompareImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); | |
| 1520 __ b(&is_compiled, NE); | |
| 1521 __ EnterStubFrame(); | |
| 1522 // Preserve arg desc. and IC data object. | |
| 1523 __ PushList((1 << R4) | (1 << R5)); | |
| 1524 __ Push(R0); // Pass function. | |
| 1525 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | |
| 1526 __ Pop(R0); // Discard argument. | |
| 1527 __ PopList((1 << R4) | (1 << R5)); // Restore arg desc. and IC data. | |
| 1528 __ LeaveStubFrame(); | |
| 1529 // R0: target function. | |
| 1530 __ ldr(R1, FieldAddress(R0, Function::code_offset())); | |
| 1531 __ Bind(&is_compiled); | |
| 1532 } | |
| 1533 __ ldr(R0, FieldAddress(R1, Code::instructions_offset())); | |
| 1534 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); | |
| 1535 __ bx(R0); | |
| 1536 | 1500 |
| 1537 // Instance in R0, return its class-id in R0 as Smi. | 1501 // Instance in R0, return its class-id in R0 as Smi. |
| 1538 __ Bind(&get_class_id_as_smi); | 1502 __ Bind(&get_class_id_as_smi); |
| 1539 | 1503 |
| 1540 // Test if Smi -> load Smi class for comparison. | 1504 // Test if Smi -> load Smi class for comparison. |
| 1541 __ tst(R0, ShifterOperand(kSmiTagMask)); | 1505 __ tst(R0, ShifterOperand(kSmiTagMask)); |
| 1542 __ mov(R0, ShifterOperand(Smi::RawValue(kSmiCid)), EQ); | 1506 __ mov(R0, ShifterOperand(Smi::RawValue(kSmiCid)), EQ); |
| 1543 __ bx(LR, EQ); | 1507 __ bx(LR, EQ); |
| 1544 __ LoadClassId(R0, R0); | 1508 __ LoadClassId(R0, R0); |
| 1545 __ SmiTag(R0); | 1509 __ SmiTag(R0); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 // Increment count for this call. | 1619 // Increment count for this call. |
| 1656 Label increment_done; | 1620 Label increment_done; |
| 1657 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1621 __ LoadFromOffset(kWord, R1, R6, count_offset); |
| 1658 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); | 1622 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); |
| 1659 __ StoreToOffset(kWord, R1, R6, count_offset); | 1623 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1660 __ b(&increment_done, VC); // No overflow. | 1624 __ b(&increment_done, VC); // No overflow. |
| 1661 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); | 1625 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); |
| 1662 __ StoreToOffset(kWord, R1, R6, count_offset); | 1626 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1663 __ Bind(&increment_done); | 1627 __ Bind(&increment_done); |
| 1664 | 1628 |
| 1665 Label target_is_compiled; | |
| 1666 // Get function and call it, if possible. | |
| 1667 __ LoadFromOffset(kWord, R1, R6, target_offset); | |
| 1668 __ ldr(R0, FieldAddress(R1, Function::code_offset())); | |
| 1669 __ CompareImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | |
| 1670 __ b(&target_is_compiled, NE); | |
| 1671 // R1: function. | |
| 1672 | |
| 1673 __ EnterStubFrame(); | |
| 1674 // Preserve target function and IC data object. | |
| 1675 __ PushList((1 << R1) | (1 << R5)); | |
| 1676 __ Push(R1); // Pass function. | |
| 1677 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | |
| 1678 __ Drop(1); // Discard argument. | |
| 1679 __ PopList((1 << R1) | (1 << R5)); // Restore function and IC data. | |
| 1680 __ LeaveStubFrame(); | |
| 1681 // R0: target function. | |
| 1682 __ ldr(R0, FieldAddress(R1, Function::code_offset())); | |
| 1683 | |
| 1684 __ Bind(&target_is_compiled); | |
| 1685 // R0: target code. | |
| 1686 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); | |
| 1687 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); | |
| 1688 // Load arguments descriptor into R4. | 1629 // Load arguments descriptor into R4. |
| 1689 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1630 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
| 1690 __ bx(R0); | 1631 |
| 1632 // Get function and call it, if possible. |
| 1633 __ LoadFromOffset(kWord, R0, R6, target_offset); |
| 1634 __ ldr(R2, FieldAddress(R0, Function::code_offset())); |
| 1635 |
| 1636 // R0: function. |
| 1637 // R2: target code. |
| 1638 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); |
| 1639 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1640 __ bx(R2); |
| 1691 } | 1641 } |
| 1692 | 1642 |
| 1693 | 1643 |
| 1694 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1644 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1695 GenerateUsageCounterIncrement(assembler, R6); | 1645 GenerateUsageCounterIncrement(assembler, R6); |
| 1696 GenerateNArgsCheckInlineCacheStub( | 1646 GenerateNArgsCheckInlineCacheStub( |
| 1697 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); | 1647 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); |
| 1698 } | 1648 } |
| 1699 | 1649 |
| 1700 | 1650 |
| 1701 // Stub for calling the CompileFunction runtime call. | 1651 // Stub for compiling a function and jumping to the compiled code. |
| 1702 // R5: IC-Data. | 1652 // R5: IC-Data (for methods). |
| 1703 // R4: Arguments descriptor. | 1653 // R4: Arguments descriptor. |
| 1704 // R0: Function. | 1654 // R0: Function. |
| 1705 void StubCode::GenerateCompileFunctionRuntimeCallStub(Assembler* assembler) { | 1655 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
| 1706 // Preserve arg desc. and IC data object. | 1656 // Preserve arg desc. and IC data object. |
| 1707 __ EnterStubFrame(); | 1657 __ EnterStubFrame(); |
| 1708 __ PushList((1 << R4) | (1 << R5)); | 1658 __ PushList((1 << R4) | (1 << R5)); |
| 1709 __ Push(R0); // Pass function. | 1659 __ Push(R0); // Pass function. |
| 1710 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1660 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1711 __ Pop(R0); // Restore argument. | 1661 __ Pop(R0); // Restore argument. |
| 1712 __ PopList((1 << R4) | (1 << R5)); // Restore arg desc. and IC data. | 1662 __ PopList((1 << R4) | (1 << R5)); // Restore arg desc. and IC data. |
| 1713 __ LeaveStubFrame(); | 1663 __ LeaveStubFrame(); |
| 1714 __ Ret(); | 1664 |
| 1665 __ ldr(R2, FieldAddress(R0, Function::code_offset())); |
| 1666 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); |
| 1667 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1668 __ bx(R2); |
| 1715 } | 1669 } |
| 1716 | 1670 |
| 1717 | 1671 |
| 1718 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { | 1672 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { |
| 1719 __ Comment("BreakpointRuntime stub"); | 1673 __ Comment("BreakpointRuntime stub"); |
| 1720 __ EnterStubFrame(); | 1674 __ EnterStubFrame(); |
| 1721 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1675 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 1722 // Preserve arguments descriptor and make room for result. | 1676 // Preserve arguments descriptor and make room for result. |
| 1723 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); | 1677 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); |
| 1724 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1678 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2013 const Register right = R0; | 1967 const Register right = R0; |
| 2014 __ ldr(left, Address(SP, 1 * kWordSize)); | 1968 __ ldr(left, Address(SP, 1 * kWordSize)); |
| 2015 __ ldr(right, Address(SP, 0 * kWordSize)); | 1969 __ ldr(right, Address(SP, 0 * kWordSize)); |
| 2016 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1970 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2017 __ Ret(); | 1971 __ Ret(); |
| 2018 } | 1972 } |
| 2019 | 1973 |
| 2020 } // namespace dart | 1974 } // namespace dart |
| 2021 | 1975 |
| 2022 #endif // defined TARGET_ARCH_ARM | 1976 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |