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/code_generator.h" | 5 #include "vm/code_generator.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 1586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1597 const Code& unoptimized_code = | 1597 const Code& unoptimized_code = |
1598 Code::Handle(zone, function.unoptimized_code()); | 1598 Code::Handle(zone, function.unoptimized_code()); |
1599 ASSERT(!unoptimized_code.IsNull()); | 1599 ASSERT(!unoptimized_code.IsNull()); |
1600 // The switch to unoptimized code may have already occurred. | 1600 // The switch to unoptimized code may have already occurred. |
1601 if (function.HasOptimizedCode()) { | 1601 if (function.HasOptimizedCode()) { |
1602 function.SwitchToUnoptimizedCode(); | 1602 function.SwitchToUnoptimizedCode(); |
1603 } | 1603 } |
1604 // Patch call site (lazy deoptimization is quite rare, patching it twice | 1604 // Patch call site (lazy deoptimization is quite rare, patching it twice |
1605 // is not a performance issue). | 1605 // is not a performance issue). |
1606 uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc(); | 1606 uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc(); |
1607 #if !defined(TARGET_ARCH_DBC) | |
1607 ASSERT(lazy_deopt_jump != 0); | 1608 ASSERT(lazy_deopt_jump != 0); |
1609 #endif | |
1608 const Instructions& instrs = | 1610 const Instructions& instrs = |
1609 Instructions::Handle(zone, optimized_code.instructions()); | 1611 Instructions::Handle(zone, optimized_code.instructions()); |
1610 { | 1612 { |
1611 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); | 1613 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); |
1612 CodePatcher::InsertDeoptimizationCallAt(pc, lazy_deopt_jump); | 1614 CodePatcher::InsertDeoptimizationCallAt(pc, lazy_deopt_jump); |
1613 } | 1615 } |
1614 if (FLAG_trace_patching) { | 1616 if (FLAG_trace_patching) { |
1615 const String& name = String::Handle(function.name()); | 1617 const String& name = String::Handle(function.name()); |
1616 OS::PrintErr("InsertDeoptimizationCallAt: %" Px " to %" Px " for %s\n", pc, | 1618 OS::PrintErr("InsertDeoptimizationCallAt: %" Px " to %" Px " for %s\n", pc, |
1617 lazy_deopt_jump, name.ToCString()); | 1619 lazy_deopt_jump, name.ToCString()); |
(...skipping 12 matching lines...) Expand all Loading... | |
1630 while (frame != NULL) { | 1632 while (frame != NULL) { |
1631 optimized_code = frame->LookupDartCode(); | 1633 optimized_code = frame->LookupDartCode(); |
1632 if (optimized_code.is_optimized()) { | 1634 if (optimized_code.is_optimized()) { |
1633 DeoptimizeAt(optimized_code, frame->pc()); | 1635 DeoptimizeAt(optimized_code, frame->pc()); |
1634 } | 1636 } |
1635 frame = iterator.NextFrame(); | 1637 frame = iterator.NextFrame(); |
1636 } | 1638 } |
1637 } | 1639 } |
1638 | 1640 |
1639 #if !defined(DART_PRECOMPILED_RUNTIME) | 1641 #if !defined(DART_PRECOMPILED_RUNTIME) |
1642 #if !defined(TARGET_ARCH_DBC) | |
1643 static const intptr_t kNumberOfSavedCpuRegisters = kNumberOfFpuRegisters; | |
zra
2016/05/19 16:24:27
kNumberOfCpuRegisters?
Vyacheslav Egorov (Google)
2016/05/20 12:11:46
Done.
| |
1644 static const intptr_t kNumberOfSavedFpuRegisters = kNumberOfFpuRegisters; | |
1645 #else | |
1646 static const intptr_t kNumberOfSavedCpuRegisters = 0; | |
1647 static const intptr_t kNumberOfSavedFpuRegisters = 0; | |
1648 #endif | |
1649 | |
1640 static void CopySavedRegisters(uword saved_registers_address, | 1650 static void CopySavedRegisters(uword saved_registers_address, |
1641 fpu_register_t** fpu_registers, | 1651 fpu_register_t** fpu_registers, |
1642 intptr_t** cpu_registers) { | 1652 intptr_t** cpu_registers) { |
1643 ASSERT(sizeof(fpu_register_t) == kFpuRegisterSize); | 1653 ASSERT(sizeof(fpu_register_t) == kFpuRegisterSize); |
1644 fpu_register_t* fpu_registers_copy = | 1654 fpu_register_t* fpu_registers_copy = |
1645 new fpu_register_t[kNumberOfFpuRegisters]; | 1655 new fpu_register_t[kNumberOfSavedFpuRegisters]; |
1646 ASSERT(fpu_registers_copy != NULL); | 1656 ASSERT(fpu_registers_copy != NULL); |
1647 for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) { | 1657 for (intptr_t i = 0; i < kNumberOfSavedFpuRegisters; i++) { |
1648 fpu_registers_copy[i] = | 1658 fpu_registers_copy[i] = |
1649 *reinterpret_cast<fpu_register_t*>(saved_registers_address); | 1659 *reinterpret_cast<fpu_register_t*>(saved_registers_address); |
1650 saved_registers_address += kFpuRegisterSize; | 1660 saved_registers_address += kFpuRegisterSize; |
1651 } | 1661 } |
1652 *fpu_registers = fpu_registers_copy; | 1662 *fpu_registers = fpu_registers_copy; |
1653 | 1663 |
1654 ASSERT(sizeof(intptr_t) == kWordSize); | 1664 ASSERT(sizeof(intptr_t) == kWordSize); |
1655 intptr_t* cpu_registers_copy = new intptr_t[kNumberOfCpuRegisters]; | 1665 intptr_t* cpu_registers_copy = new intptr_t[kNumberOfSavedCpuRegisters]; |
1656 ASSERT(cpu_registers_copy != NULL); | 1666 ASSERT(cpu_registers_copy != NULL); |
1657 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { | 1667 for (intptr_t i = 0; i < kNumberOfSavedCpuRegisters; i++) { |
1658 cpu_registers_copy[i] = | 1668 cpu_registers_copy[i] = |
1659 *reinterpret_cast<intptr_t*>(saved_registers_address); | 1669 *reinterpret_cast<intptr_t*>(saved_registers_address); |
1660 saved_registers_address += kWordSize; | 1670 saved_registers_address += kWordSize; |
1661 } | 1671 } |
1662 *cpu_registers = cpu_registers_copy; | 1672 *cpu_registers = cpu_registers_copy; |
1663 } | 1673 } |
1664 #endif | 1674 #endif |
1665 | 1675 |
1666 | 1676 |
1667 // Copies saved registers and caller's frame into temporary buffers. | 1677 // Copies saved registers and caller's frame into temporary buffers. |
1668 // Returns the stack size of unoptimized frame. | 1678 // Returns the stack size of unoptimized frame. |
1669 // The calling code must be optimized, but its function may not have | 1679 // The calling code must be optimized, but its function may not have |
1670 // have optimized code if the code is OSR code, or if the code was invalidated | 1680 // have optimized code if the code is OSR code, or if the code was invalidated |
1671 // through class loading/finalization or field guard. | 1681 // through class loading/finalization or field guard. |
1672 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 1682 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
1673 2, | 1683 2, |
1674 uword saved_registers_address, | 1684 uword saved_registers_address, |
1675 uword is_lazy_deopt) { | 1685 uword is_lazy_deopt) { |
1676 #if !defined(DART_PRECOMPILED_RUNTIME) | 1686 #if !defined(DART_PRECOMPILED_RUNTIME) |
1677 Thread* thread = Thread::Current(); | 1687 Thread* thread = Thread::Current(); |
1678 Isolate* isolate = thread->isolate(); | 1688 Isolate* isolate = thread->isolate(); |
1679 StackZone zone(thread); | 1689 StackZone zone(thread); |
1680 HANDLESCOPE(thread); | 1690 HANDLESCOPE(thread); |
1681 | 1691 |
1692 #if !defined(TARGET_ARCH_DBC) | |
1682 // All registers have been saved below last-fp as if they were locals. | 1693 // All registers have been saved below last-fp as if they were locals. |
1683 const uword last_fp = saved_registers_address | 1694 const uword last_fp = saved_registers_address |
1684 + (kNumberOfCpuRegisters * kWordSize) | 1695 + (kNumberOfSavedCpuRegisters * kWordSize) |
1685 + (kNumberOfFpuRegisters * kFpuRegisterSize) | 1696 + (kNumberOfSavedFpuRegisters * kFpuRegisterSize) |
1686 - ((kFirstLocalSlotFromFp + 1) * kWordSize); | 1697 - ((kFirstLocalSlotFromFp + 1) * kWordSize); |
1687 | 1698 |
1688 // Get optimized code and frame that need to be deoptimized. | 1699 // Get optimized code and frame that need to be deoptimized. |
1689 DartFrameIterator iterator(last_fp); | 1700 DartFrameIterator iterator(last_fp); |
1701 #else | |
Florian Schneider
2016/05/19 13:21:39
Needed?
I think the code above works for DBC as w
Vyacheslav Egorov (Google)
2016/05/19 15:19:39
Done.
| |
1702 // Get optimized code and frame that need to be deoptimized. | |
1703 DartFrameIterator iterator(saved_registers_address); | |
1704 #endif | |
1705 | |
1690 StackFrame* caller_frame = iterator.NextFrame(); | 1706 StackFrame* caller_frame = iterator.NextFrame(); |
1691 ASSERT(caller_frame != NULL); | 1707 ASSERT(caller_frame != NULL); |
1692 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1708 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
1693 ASSERT(optimized_code.is_optimized()); | 1709 ASSERT(optimized_code.is_optimized()); |
1694 const Function& top_function = | 1710 const Function& top_function = |
1695 Function::Handle(thread->zone(), optimized_code.function()); | 1711 Function::Handle(thread->zone(), optimized_code.function()); |
1696 const bool deoptimizing_code = top_function.HasOptimizedCode(); | 1712 const bool deoptimizing_code = top_function.HasOptimizedCode(); |
1697 if (FLAG_trace_deoptimization) { | 1713 if (FLAG_trace_deoptimization) { |
1698 const Function& function = Function::Handle(optimized_code.function()); | 1714 const Function& function = Function::Handle(optimized_code.function()); |
1699 THR_Print("== Deoptimizing code for '%s', %s, %s\n", | 1715 THR_Print("== Deoptimizing code for '%s', %s, %s\n", |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1755 // The code will be the same as before. | 1771 // The code will be the same as before. |
1756 ASSERT(code.raw() == optimized_code.raw()); | 1772 ASSERT(code.raw() == optimized_code.raw()); |
1757 | 1773 |
1758 // Some sanity checking of the optimized code. | 1774 // Some sanity checking of the optimized code. |
1759 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); | 1775 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); |
1760 } | 1776 } |
1761 #endif | 1777 #endif |
1762 | 1778 |
1763 // TODO(turnidge): Compute the start of the dest frame in the | 1779 // TODO(turnidge): Compute the start of the dest frame in the |
1764 // DeoptContext instead of passing it in here. | 1780 // DeoptContext instead of passing it in here. |
1765 intptr_t* start = reinterpret_cast<intptr_t*>( | 1781 #if !defined(TARGET_ARCH_DBC) |
1766 caller_frame->sp() - (kDartFrameFixedSize * kWordSize)); | 1782 // On non-DBC architectures stack grows down: SP <= FP |
1783 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame->sp() - | |
1784 kDartFrameFixedSize * kWordSize); | |
1785 #else | |
1786 // On DBC stack grows up: FP <= SP | |
1787 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame->fp() - | |
Florian Schneider
2016/05/19 13:21:39
Maybe a helper FrameStart(frame)?
Vyacheslav Egorov (Google)
2016/05/19 15:19:40
Done.
| |
1788 (kDartFrameFixedSize + deopt_context->num_args()) * kWordSize); | |
1789 #endif // !defined(TARGET_ARCH_DBC) | |
1767 deopt_context->set_dest_frame(start); | 1790 deopt_context->set_dest_frame(start); |
1768 deopt_context->FillDestFrame(); | 1791 deopt_context->FillDestFrame(); |
1769 #else | 1792 #else |
1770 UNREACHABLE(); | 1793 UNREACHABLE(); |
1771 #endif // !DART_PRECOMPILED_RUNTIME | 1794 #endif // !DART_PRECOMPILED_RUNTIME |
1772 } | 1795 } |
1773 END_LEAF_RUNTIME_ENTRY | 1796 END_LEAF_RUNTIME_ENTRY |
1774 | 1797 |
1775 | 1798 |
1776 // This is the last step in the deoptimization, GC can occur. | 1799 // This is the last step in the deoptimization, GC can occur. |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1872 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1895 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1873 const TypedData& new_data = | 1896 const TypedData& new_data = |
1874 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1897 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1875 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1898 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1876 typed_data_cell.SetAt(0, new_data); | 1899 typed_data_cell.SetAt(0, new_data); |
1877 arguments.SetReturn(new_data); | 1900 arguments.SetReturn(new_data); |
1878 } | 1901 } |
1879 | 1902 |
1880 | 1903 |
1881 } // namespace dart | 1904 } // namespace dart |
OLD | NEW |