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 |