| 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; | 804 __ cmp(R2, ShifterOperand(R8)); // R8 is raw null. |
| 805 __ b(&function_compiled, NE); | 805 __ Branch(&StubCode::LazyCompileClosureLabel(), EQ); |
| 806 | 806 |
| 807 // Create a stub frame as we are pushing some objects on the stack before | 807 // R2: code. |
| 808 // calling into the runtime. | 808 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); |
| 809 __ EnterStubFrame(); | 809 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 810 | 810 __ 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 | 811 |
| 829 __ Bind(¬_closure); | 812 __ Bind(¬_closure); |
| 830 // Call runtime to attempt to resolve and invoke a call method on a | 813 // 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, | 814 // non-closure object, passing the non-closure object and its arguments array, |
| 832 // returning here. | 815 // returning here. |
| 833 // If no call method exists, throw a NoSuchMethodError. | 816 // If no call method exists, throw a NoSuchMethodError. |
| 834 // R1: non-closure object. | 817 // R1: non-closure object. |
| 835 // R4: arguments descriptor array. | 818 // R4: arguments descriptor array. |
| 836 | 819 |
| 837 // Create a stub frame as we are pushing some objects on the stack before | 820 // 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); | 1488 __ LoadFromOffset(kWord, R0, R6, target_offset); |
| 1506 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1489 __ LoadFromOffset(kWord, R1, R6, count_offset); |
| 1507 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); | 1490 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); |
| 1508 __ StoreToOffset(kWord, R1, R6, count_offset); | 1491 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1509 __ b(&call_target_function, VC); // No overflow. | 1492 __ b(&call_target_function, VC); // No overflow. |
| 1510 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); | 1493 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); |
| 1511 __ StoreToOffset(kWord, R1, R6, count_offset); | 1494 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1512 | 1495 |
| 1513 __ Bind(&call_target_function); | 1496 __ Bind(&call_target_function); |
| 1514 // R0: target function. | 1497 // R0: target function. |
| 1515 __ ldr(R1, FieldAddress(R0, Function::code_offset())); | 1498 __ ldr(R2, FieldAddress(R0, Function::code_offset())); |
| 1516 if (FLAG_collect_code) { | 1499 if (FLAG_collect_code) { |
| 1517 // If we are collecting code, the code object may be null. | 1500 // If we are collecting code, the code object may be null. |
| 1518 Label is_compiled; | 1501 Label is_compiled; |
| 1519 __ CompareImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); | 1502 __ CompareImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); |
| 1520 __ b(&is_compiled, NE); | 1503 __ Branch(&StubCode::LazyCompileLabel(), EQ); |
| 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 } | 1504 } |
| 1533 __ ldr(R0, FieldAddress(R1, Code::instructions_offset())); | 1505 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); |
| 1534 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); | 1506 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1535 __ bx(R0); | 1507 __ bx(R2); |
| 1536 | 1508 |
| 1537 // Instance in R0, return its class-id in R0 as Smi. | 1509 // Instance in R0, return its class-id in R0 as Smi. |
| 1538 __ Bind(&get_class_id_as_smi); | 1510 __ Bind(&get_class_id_as_smi); |
| 1539 | 1511 |
| 1540 // Test if Smi -> load Smi class for comparison. | 1512 // Test if Smi -> load Smi class for comparison. |
| 1541 __ tst(R0, ShifterOperand(kSmiTagMask)); | 1513 __ tst(R0, ShifterOperand(kSmiTagMask)); |
| 1542 __ mov(R0, ShifterOperand(Smi::RawValue(kSmiCid)), EQ); | 1514 __ mov(R0, ShifterOperand(Smi::RawValue(kSmiCid)), EQ); |
| 1543 __ bx(LR, EQ); | 1515 __ bx(LR, EQ); |
| 1544 __ LoadClassId(R0, R0); | 1516 __ LoadClassId(R0, R0); |
| 1545 __ SmiTag(R0); | 1517 __ SmiTag(R0); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 // Increment count for this call. | 1627 // Increment count for this call. |
| 1656 Label increment_done; | 1628 Label increment_done; |
| 1657 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1629 __ LoadFromOffset(kWord, R1, R6, count_offset); |
| 1658 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); | 1630 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); |
| 1659 __ StoreToOffset(kWord, R1, R6, count_offset); | 1631 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1660 __ b(&increment_done, VC); // No overflow. | 1632 __ b(&increment_done, VC); // No overflow. |
| 1661 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); | 1633 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); |
| 1662 __ StoreToOffset(kWord, R1, R6, count_offset); | 1634 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1663 __ Bind(&increment_done); | 1635 __ Bind(&increment_done); |
| 1664 | 1636 |
| 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. | 1637 // Load arguments descriptor into R4. |
| 1689 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1638 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
| 1690 __ bx(R0); | 1639 |
| 1640 // Get function and call it, if possible. |
| 1641 __ LoadFromOffset(kWord, R0, R6, target_offset); |
| 1642 __ ldr(R2, FieldAddress(R0, Function::code_offset())); |
| 1643 |
| 1644 // R0: function. |
| 1645 // R2: target code. |
| 1646 __ CompareImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); |
| 1647 __ Branch(&StubCode::LazyCompileLabel(), EQ); |
| 1648 |
| 1649 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); |
| 1650 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1651 __ bx(R2); |
| 1691 } | 1652 } |
| 1692 | 1653 |
| 1693 | 1654 |
| 1694 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1655 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1695 GenerateUsageCounterIncrement(assembler, R6); | 1656 GenerateUsageCounterIncrement(assembler, R6); |
| 1696 GenerateNArgsCheckInlineCacheStub( | 1657 GenerateNArgsCheckInlineCacheStub( |
| 1697 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); | 1658 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); |
| 1698 } | 1659 } |
| 1699 | 1660 |
| 1700 | 1661 |
| 1701 // Stub for calling the CompileFunction runtime call. | 1662 // Stub for compiling a function and jumping to the compiled code. |
| 1702 // R5: IC-Data. | 1663 // R5: IC-Data. |
| 1703 // R4: Arguments descriptor. | 1664 // R4: Arguments descriptor. |
| 1704 // R0: Function. | 1665 // R0: Function. |
| 1705 void StubCode::GenerateCompileFunctionRuntimeCallStub(Assembler* assembler) { | 1666 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
| 1706 // Preserve arg desc. and IC data object. | 1667 // Preserve arg desc. and IC data object. |
| 1707 __ EnterStubFrame(); | 1668 __ EnterStubFrame(); |
| 1708 __ PushList((1 << R4) | (1 << R5)); | 1669 __ PushList((1 << R4) | (1 << R5)); |
| 1709 __ Push(R0); // Pass function. | 1670 __ Push(R0); // Pass function. |
| 1710 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1671 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1711 __ Pop(R0); // Restore argument. | 1672 __ Pop(R0); // Restore argument. |
| 1712 __ PopList((1 << R4) | (1 << R5)); // Restore arg desc. and IC data. | 1673 __ PopList((1 << R4) | (1 << R5)); // Restore arg desc. and IC data. |
| 1713 __ LeaveStubFrame(); | 1674 __ LeaveStubFrame(); |
| 1675 |
| 1676 __ ldr(R2, FieldAddress(R0, Function::code_offset())); |
| 1677 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); |
| 1678 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1679 __ bx(R2); |
| 1680 } |
| 1681 |
| 1682 |
| 1683 // Stub for calling the CompileFunction runtime call. |
| 1684 // R4: Arguments descriptor. |
| 1685 // R0: Function. |
| 1686 void StubCode::GenerateLazyCompileClosureStub(Assembler* assembler) { |
| 1687 // Preserve arg desc. and IC data object. |
| 1688 __ EnterStubFrame(); |
| 1689 __ Push(R4); |
| 1690 __ Push(R0); // Pass function. |
| 1691 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1692 __ Pop(R0); // Restore argument. |
| 1693 __ Pop(R4); // Restore arg desc. |
| 1694 __ LeaveStubFrame(); |
| 1695 |
| 1696 __ ldr(R2, FieldAddress(R0, Function::code_offset())); |
| 1697 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); |
| 1698 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1699 __ bx(R2); |
| 1700 } |
| 1701 |
| 1702 |
| 1703 // Stub for calling the CompileFunction runtime call. |
| 1704 // R0: Function. |
| 1705 void StubCode::GenerateCompileFunctionRuntimeCallStub(Assembler* assembler) { |
| 1706 __ EnterStubFrame(); |
| 1707 __ Push(R0); // Pass function. |
| 1708 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1709 __ Pop(R0); // Restore argument. |
| 1710 __ LeaveStubFrame(); |
| 1714 __ Ret(); | 1711 __ Ret(); |
| 1715 } | 1712 } |
| 1716 | 1713 |
| 1717 | 1714 |
| 1718 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { | 1715 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { |
| 1719 __ Comment("BreakpointRuntime stub"); | 1716 __ Comment("BreakpointRuntime stub"); |
| 1720 __ EnterStubFrame(); | 1717 __ EnterStubFrame(); |
| 1721 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1718 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 1722 // Preserve arguments descriptor and make room for result. | 1719 // Preserve arguments descriptor and make room for result. |
| 1723 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); | 1720 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2013 const Register right = R0; | 2010 const Register right = R0; |
| 2014 __ ldr(left, Address(SP, 1 * kWordSize)); | 2011 __ ldr(left, Address(SP, 1 * kWordSize)); |
| 2015 __ ldr(right, Address(SP, 0 * kWordSize)); | 2012 __ ldr(right, Address(SP, 0 * kWordSize)); |
| 2016 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2013 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2017 __ Ret(); | 2014 __ Ret(); |
| 2018 } | 2015 } |
| 2019 | 2016 |
| 2020 } // namespace dart | 2017 } // namespace dart |
| 2021 | 2018 |
| 2022 #endif // defined TARGET_ARCH_ARM | 2019 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |