| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_macros.h" | 7 #include "vm/assembler_macros.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 1464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1475 while (frame != NULL) { | 1475 while (frame != NULL) { |
| 1476 optimized_code = frame->LookupDartCode(); | 1476 optimized_code = frame->LookupDartCode(); |
| 1477 if (optimized_code.is_optimized()) { | 1477 if (optimized_code.is_optimized()) { |
| 1478 intptr_t deopt_id, deopt_reason, deopt_index; | 1478 intptr_t deopt_id, deopt_reason, deopt_index; |
| 1479 GetDeoptIxDescrAtPc(optimized_code, frame->pc(), | 1479 GetDeoptIxDescrAtPc(optimized_code, frame->pc(), |
| 1480 &deopt_id, &deopt_reason, &deopt_index); | 1480 &deopt_id, &deopt_reason, &deopt_index); |
| 1481 ASSERT(deopt_id != Isolate::kNoDeoptId); | 1481 ASSERT(deopt_id != Isolate::kNoDeoptId); |
| 1482 function = optimized_code.function(); | 1482 function = optimized_code.function(); |
| 1483 unoptimized_code = function.unoptimized_code(); | 1483 unoptimized_code = function.unoptimized_code(); |
| 1484 ASSERT(!unoptimized_code.IsNull()); | 1484 ASSERT(!unoptimized_code.IsNull()); |
| 1485 uword continue_at_pc = | |
| 1486 unoptimized_code.GetDeoptAfterPcAtDeoptId(deopt_id); | |
| 1487 ASSERT(continue_at_pc != 0); | |
| 1488 // The switch to unoptimized code may have already occured. | 1485 // The switch to unoptimized code may have already occured. |
| 1489 if (function.HasOptimizedCode()) { | 1486 if (function.HasOptimizedCode()) { |
| 1490 function.SwitchToUnoptimizedCode(); | 1487 function.SwitchToUnoptimizedCode(); |
| 1491 } | 1488 } |
| 1492 // Patch call site (lazy deoptimization is quite rare, patching it twice | 1489 // Patch call site (lazy deoptimization is quite rare, patching it twice |
| 1493 // is not a performance issue). | 1490 // is not a performance issue). |
| 1494 uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc(); | 1491 uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc(); |
| 1495 ASSERT(lazy_deopt_jump != 0); | 1492 ASSERT(lazy_deopt_jump != 0); |
| 1496 CodePatcher::InsertCallAt(frame->pc(), lazy_deopt_jump); | 1493 CodePatcher::InsertCallAt(frame->pc(), lazy_deopt_jump); |
| 1497 // Mark code as dead (do not GC its embedded objects). | 1494 // Mark code as dead (do not GC its embedded objects). |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1602 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 1599 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 1603 intptr_t unoptimized_stack_size = | 1600 intptr_t unoptimized_stack_size = |
| 1604 + deopt_info.Length() - num_args | 1601 + deopt_info.Length() - num_args |
| 1605 - 2; // Subtract caller FP and PC. | 1602 - 2; // Subtract caller FP and PC. |
| 1606 return unoptimized_stack_size * kWordSize; | 1603 return unoptimized_stack_size * kWordSize; |
| 1607 } | 1604 } |
| 1608 END_LEAF_RUNTIME_ENTRY | 1605 END_LEAF_RUNTIME_ENTRY |
| 1609 | 1606 |
| 1610 | 1607 |
| 1611 | 1608 |
| 1612 static void DeoptimizeWithDeoptInfo(const Code& code, | 1609 static intptr_t DeoptimizeWithDeoptInfo(const Code& code, |
| 1613 const DeoptInfo& deopt_info, | 1610 const DeoptInfo& deopt_info, |
| 1614 const StackFrame& caller_frame) { | 1611 const StackFrame& caller_frame) { |
| 1615 const intptr_t len = deopt_info.Length(); | 1612 const intptr_t len = deopt_info.Length(); |
| 1616 GrowableArray<DeoptInstr*> deopt_instructions(len); | 1613 GrowableArray<DeoptInstr*> deopt_instructions(len); |
| 1617 for (intptr_t i = 0; i < len; i++) { | 1614 for (intptr_t i = 0; i < len; i++) { |
| 1618 deopt_instructions.Add(DeoptInstr::Create(deopt_info.Instruction(i), | 1615 deopt_instructions.Add(DeoptInstr::Create(deopt_info.Instruction(i), |
| 1619 deopt_info.FromIndex(i))); | 1616 deopt_info.FromIndex(i))); |
| 1620 } | 1617 } |
| 1621 | 1618 |
| 1622 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame.sp() - kWordSize); | 1619 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame.sp() - kWordSize); |
| 1623 const Function& function = Function::Handle(code.function()); | 1620 const Function& function = Function::Handle(code.function()); |
| 1624 const intptr_t num_args = | 1621 const intptr_t num_args = |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1637 } | 1634 } |
| 1638 if (FLAG_trace_deopt) { | 1635 if (FLAG_trace_deopt) { |
| 1639 for (intptr_t i = 0; i < len; i++) { | 1636 for (intptr_t i = 0; i < len; i++) { |
| 1640 OS::Print("*%"Pd". [%p] %#014"Px" [%s]\n", | 1637 OS::Print("*%"Pd". [%p] %#014"Px" [%s]\n", |
| 1641 i, | 1638 i, |
| 1642 &start[i], | 1639 &start[i], |
| 1643 start[i], | 1640 start[i], |
| 1644 deopt_instructions[i]->ToCString()); | 1641 deopt_instructions[i]->ToCString()); |
| 1645 } | 1642 } |
| 1646 } | 1643 } |
| 1644 return deopt_context.GetCallerFp(); |
| 1647 } | 1645 } |
| 1648 | 1646 |
| 1649 | 1647 |
| 1650 // The stack has been adjusted to fit all values for unoptimized frame. | 1648 // The stack has been adjusted to fit all values for unoptimized frame. |
| 1651 // Fill the unoptimized frame. | 1649 // Fill the unoptimized frame. |
| 1652 DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp) { | 1650 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeFillFrame, uword last_fp) { |
| 1653 Isolate* isolate = Isolate::Current(); | 1651 Isolate* isolate = Isolate::Current(); |
| 1654 Zone zone(isolate); | 1652 Zone zone(isolate); |
| 1655 HANDLESCOPE(isolate); | 1653 HANDLESCOPE(isolate); |
| 1656 | 1654 |
| 1657 DartFrameIterator iterator(last_fp); | 1655 DartFrameIterator iterator(last_fp); |
| 1658 StackFrame* caller_frame = iterator.NextFrame(); | 1656 StackFrame* caller_frame = iterator.NextFrame(); |
| 1659 ASSERT(caller_frame != NULL); | 1657 ASSERT(caller_frame != NULL); |
| 1660 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1658 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
| 1661 const Function& function = Function::Handle(optimized_code.function()); | 1659 const Function& function = Function::Handle(optimized_code.function()); |
| 1662 ASSERT(!function.IsNull()); | 1660 ASSERT(!function.IsNull()); |
| 1663 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); | 1661 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); |
| 1664 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); | 1662 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); |
| 1665 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); | 1663 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); |
| 1666 | 1664 |
| 1667 intptr_t* frame_copy = isolate->deopt_frame_copy(); | 1665 intptr_t* frame_copy = isolate->deopt_frame_copy(); |
| 1668 intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy(); | 1666 intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy(); |
| 1669 double* xmm_registers_copy = isolate->deopt_xmm_registers_copy(); | 1667 double* xmm_registers_copy = isolate->deopt_xmm_registers_copy(); |
| 1670 | 1668 |
| 1671 intptr_t deopt_id, deopt_reason, deopt_index; | 1669 intptr_t deopt_id, deopt_reason, deopt_index; |
| 1672 GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(), | 1670 GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(), |
| 1673 &deopt_id, &deopt_reason, &deopt_index); | 1671 &deopt_id, &deopt_reason, &deopt_index); |
| 1674 ASSERT(deopt_id != Isolate::kNoDeoptId); | 1672 ASSERT(deopt_id != Isolate::kNoDeoptId); |
| 1675 uword continue_at_pc = 0; | |
| 1676 if (deopt_reason == kDeoptAtCall) { | |
| 1677 continue_at_pc = unoptimized_code.GetDeoptAfterPcAtDeoptId(deopt_id); | |
| 1678 } else { | |
| 1679 continue_at_pc = unoptimized_code.GetDeoptBeforePcAtDeoptId(deopt_id); | |
| 1680 } | |
| 1681 ASSERT(continue_at_pc != 0); | |
| 1682 if (FLAG_trace_deopt) { | |
| 1683 OS::Print(" -> continue at %#"Px"\n", continue_at_pc); | |
| 1684 // TODO(srdjan): If we could allow GC, we could print the line where | |
| 1685 // deoptimization occured. | |
| 1686 } | |
| 1687 const Array& deopt_info_array = | 1673 const Array& deopt_info_array = |
| 1688 Array::Handle(optimized_code.deopt_info_array()); | 1674 Array::Handle(optimized_code.deopt_info_array()); |
| 1689 ASSERT(!deopt_info_array.IsNull()); | 1675 ASSERT(!deopt_info_array.IsNull()); |
| 1690 DeoptInfo& deopt_info = DeoptInfo::Handle(); | 1676 DeoptInfo& deopt_info = DeoptInfo::Handle(); |
| 1691 deopt_info ^= deopt_info_array.At(deopt_index); | 1677 deopt_info ^= deopt_info_array.At(deopt_index); |
| 1692 ASSERT(!deopt_info.IsNull()); | 1678 ASSERT(!deopt_info.IsNull()); |
| 1693 DeoptimizeWithDeoptInfo(optimized_code, deopt_info, *caller_frame); | 1679 const intptr_t caller_fp = |
| 1680 DeoptimizeWithDeoptInfo(optimized_code, deopt_info, *caller_frame); |
| 1694 | 1681 |
| 1695 isolate->SetDeoptFrameCopy(NULL, 0); | 1682 isolate->SetDeoptFrameCopy(NULL, 0); |
| 1696 isolate->set_deopt_cpu_registers_copy(NULL); | 1683 isolate->set_deopt_cpu_registers_copy(NULL); |
| 1697 isolate->set_deopt_xmm_registers_copy(NULL); | 1684 isolate->set_deopt_xmm_registers_copy(NULL); |
| 1698 delete[] frame_copy; | 1685 delete[] frame_copy; |
| 1699 delete[] cpu_registers_copy; | 1686 delete[] cpu_registers_copy; |
| 1700 delete[] xmm_registers_copy; | 1687 delete[] xmm_registers_copy; |
| 1701 | 1688 |
| 1702 // Clear invocation counter so that the function gets optimized after | 1689 // Clear invocation counter so that the function gets optimized after |
| 1703 // classes have been collected. | 1690 // classes have been collected. |
| 1704 function.set_usage_counter(0); | 1691 function.set_usage_counter(0); |
| 1705 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 1692 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
| 1706 | 1693 |
| 1707 if (function.HasOptimizedCode()) { | 1694 if (function.HasOptimizedCode()) { |
| 1708 function.SwitchToUnoptimizedCode(); | 1695 function.SwitchToUnoptimizedCode(); |
| 1709 } | 1696 } |
| 1697 return caller_fp; |
| 1710 } | 1698 } |
| 1711 END_LEAF_RUNTIME_ENTRY | 1699 END_LEAF_RUNTIME_ENTRY |
| 1712 | 1700 |
| 1713 | 1701 |
| 1714 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterializeDoubles, 0) { | 1702 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterializeDoubles, 0) { |
| 1715 DeferredDouble* deferred_double = Isolate::Current()->DetachDeferredDoubles(); | 1703 DeferredDouble* deferred_double = Isolate::Current()->DetachDeferredDoubles(); |
| 1716 | 1704 |
| 1717 while (deferred_double != NULL) { | 1705 while (deferred_double != NULL) { |
| 1718 DeferredDouble* current = deferred_double; | 1706 DeferredDouble* current = deferred_double; |
| 1719 deferred_double = deferred_double->next(); | 1707 deferred_double = deferred_double->next(); |
| 1720 | 1708 |
| 1721 RawDouble** slot = current->slot(); | 1709 RawDouble** slot = current->slot(); |
| 1722 *slot = Double::New(current->value()); | 1710 *slot = Double::New(current->value()); |
| 1723 | 1711 |
| 1724 if (FLAG_trace_deopt) { | 1712 if (FLAG_trace_deopt) { |
| 1725 OS::Print("materialing double at %p: %g\n", | 1713 OS::Print("materialing double at %p: %g\n", |
| 1726 current->slot(), | 1714 current->slot(), |
| 1727 current->value()); | 1715 current->value()); |
| 1728 } | 1716 } |
| 1729 | 1717 |
| 1730 delete current; | 1718 delete current; |
| 1731 } | 1719 } |
| 1732 } | 1720 } |
| 1733 | 1721 |
| 1734 | 1722 |
| 1735 } // namespace dart | 1723 } // namespace dart |
| OLD | NEW |