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 = kNumberOfCpuRegisters; |
| 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 |
1682 // All registers have been saved below last-fp as if they were locals. | 1692 // All registers have been saved below last-fp as if they were locals. |
1683 const uword last_fp = saved_registers_address | 1693 const uword last_fp = saved_registers_address |
1684 + (kNumberOfCpuRegisters * kWordSize) | 1694 + (kNumberOfSavedCpuRegisters * kWordSize) |
1685 + (kNumberOfFpuRegisters * kFpuRegisterSize) | 1695 + (kNumberOfSavedFpuRegisters * kFpuRegisterSize) |
1686 - ((kFirstLocalSlotFromFp + 1) * kWordSize); | 1696 - ((kFirstLocalSlotFromFp + 1) * kWordSize); |
1687 | 1697 |
1688 // Get optimized code and frame that need to be deoptimized. | 1698 // Get optimized code and frame that need to be deoptimized. |
1689 DartFrameIterator iterator(last_fp); | 1699 DartFrameIterator iterator(last_fp); |
| 1700 |
1690 StackFrame* caller_frame = iterator.NextFrame(); | 1701 StackFrame* caller_frame = iterator.NextFrame(); |
1691 ASSERT(caller_frame != NULL); | 1702 ASSERT(caller_frame != NULL); |
1692 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1703 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
1693 ASSERT(optimized_code.is_optimized()); | 1704 ASSERT(optimized_code.is_optimized()); |
1694 const Function& top_function = | 1705 const Function& top_function = |
1695 Function::Handle(thread->zone(), optimized_code.function()); | 1706 Function::Handle(thread->zone(), optimized_code.function()); |
1696 const bool deoptimizing_code = top_function.HasOptimizedCode(); | 1707 const bool deoptimizing_code = top_function.HasOptimizedCode(); |
1697 if (FLAG_trace_deoptimization) { | 1708 if (FLAG_trace_deoptimization) { |
1698 const Function& function = Function::Handle(optimized_code.function()); | 1709 const Function& function = Function::Handle(optimized_code.function()); |
1699 THR_Print("== Deoptimizing code for '%s', %s, %s\n", | 1710 THR_Print("== Deoptimizing code for '%s', %s, %s\n", |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1753 ASSERT(!function.IsNull()); | 1764 ASSERT(!function.IsNull()); |
1754 | 1765 |
1755 // The code will be the same as before. | 1766 // The code will be the same as before. |
1756 ASSERT(code.raw() == optimized_code.raw()); | 1767 ASSERT(code.raw() == optimized_code.raw()); |
1757 | 1768 |
1758 // Some sanity checking of the optimized code. | 1769 // Some sanity checking of the optimized code. |
1759 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); | 1770 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); |
1760 } | 1771 } |
1761 #endif | 1772 #endif |
1762 | 1773 |
1763 // TODO(turnidge): Compute the start of the dest frame in the | 1774 deopt_context->set_dest_frame(caller_frame); |
1764 // DeoptContext instead of passing it in here. | |
1765 intptr_t* start = reinterpret_cast<intptr_t*>( | |
1766 caller_frame->sp() - (kDartFrameFixedSize * kWordSize)); | |
1767 deopt_context->set_dest_frame(start); | |
1768 deopt_context->FillDestFrame(); | 1775 deopt_context->FillDestFrame(); |
1769 #else | 1776 #else |
1770 UNREACHABLE(); | 1777 UNREACHABLE(); |
1771 #endif // !DART_PRECOMPILED_RUNTIME | 1778 #endif // !DART_PRECOMPILED_RUNTIME |
1772 } | 1779 } |
1773 END_LEAF_RUNTIME_ENTRY | 1780 END_LEAF_RUNTIME_ENTRY |
1774 | 1781 |
1775 | 1782 |
1776 // This is the last step in the deoptimization, GC can occur. | 1783 // This is the last step in the deoptimization, GC can occur. |
1777 // Returns number of bytes to remove from the expression stack of the | 1784 // Returns number of bytes to remove from the expression stack of the |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1872 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1879 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1873 const TypedData& new_data = | 1880 const TypedData& new_data = |
1874 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1881 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1875 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1882 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1876 typed_data_cell.SetAt(0, new_data); | 1883 typed_data_cell.SetAt(0, new_data); |
1877 arguments.SetReturn(new_data); | 1884 arguments.SetReturn(new_data); |
1878 } | 1885 } |
1879 | 1886 |
1880 | 1887 |
1881 } // namespace dart | 1888 } // namespace dart |
OLD | NEW |