| 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 |