| 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 12 matching lines...) Expand all Loading... |
| 23 #include "vm/stack_frame.h" | 23 #include "vm/stack_frame.h" |
| 24 #include "vm/symbols.h" | 24 #include "vm/symbols.h" |
| 25 #include "vm/verifier.h" | 25 #include "vm/verifier.h" |
| 26 | 26 |
| 27 namespace dart { | 27 namespace dart { |
| 28 | 28 |
| 29 DEFINE_FLAG(bool, deoptimize_alot, false, | 29 DEFINE_FLAG(bool, deoptimize_alot, false, |
| 30 "Deoptimizes all live frames when we are about to return to Dart code from" | 30 "Deoptimizes all live frames when we are about to return to Dart code from" |
| 31 " native entries."); | 31 " native entries."); |
| 32 DEFINE_FLAG(bool, inline_cache, true, "Enable inline caches"); | 32 DEFINE_FLAG(bool, inline_cache, true, "Enable inline caches"); |
| 33 DEFINE_FLAG(bool, trace_deopt, false, "Trace deoptimization"); | 33 DEFINE_FLAG(bool, trace_deoptimization, false, "Trace deoptimization"); |
| 34 DEFINE_FLAG(bool, trace_deoptimization_verbose, false, |
| 35 "Trace deoptimization verbose"); |
| 34 DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling"); | 36 DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling"); |
| 35 DEFINE_FLAG(bool, trace_ic_miss_in_optimized, false, | 37 DEFINE_FLAG(bool, trace_ic_miss_in_optimized, false, |
| 36 "Trace IC miss in optimized code"); | 38 "Trace IC miss in optimized code"); |
| 37 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code."); | 39 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code."); |
| 38 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls"); | 40 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls"); |
| 39 DEFINE_FLAG(int, optimization_counter_threshold, 2000, | 41 DEFINE_FLAG(int, optimization_counter_threshold, 2000, |
| 40 "Function's usage-counter value before it is optimized, -1 means never"); | 42 "Function's usage-counter value before it is optimized, -1 means never"); |
| 41 DECLARE_FLAG(bool, enable_type_checks); | 43 DECLARE_FLAG(bool, enable_type_checks); |
| 42 DECLARE_FLAG(bool, trace_type_checks); | 44 DECLARE_FLAG(bool, trace_type_checks); |
| 43 DECLARE_FLAG(bool, report_usage_count); | 45 DECLARE_FLAG(bool, report_usage_count); |
| (...skipping 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1544 // Include the return address of optimized code. | 1546 // Include the return address of optimized code. |
| 1545 intptr_t* start = reinterpret_cast<intptr_t*>(frame.sp() - kWordSize); | 1547 intptr_t* start = reinterpret_cast<intptr_t*>(frame.sp() - kWordSize); |
| 1546 for (intptr_t i = 0; i < frame_copy_size; i++) { | 1548 for (intptr_t i = 0; i < frame_copy_size; i++) { |
| 1547 frame_copy[i] = *(start + i); | 1549 frame_copy[i] = *(start + i); |
| 1548 } | 1550 } |
| 1549 Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size); | 1551 Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size); |
| 1550 } | 1552 } |
| 1551 | 1553 |
| 1552 | 1554 |
| 1553 // Copies saved registers and caller's frame into temporary buffers. | 1555 // Copies saved registers and caller's frame into temporary buffers. |
| 1554 // Returns the stack size of unoptimzied frame. | 1556 // Returns the stack size of unoptimized frame. |
| 1555 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 1557 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| 1556 uword saved_registers_address) { | 1558 uword saved_registers_address) { |
| 1557 Isolate* isolate = Isolate::Current(); | 1559 Isolate* isolate = Isolate::Current(); |
| 1558 Zone zone(isolate); | 1560 Zone zone(isolate); |
| 1559 HANDLESCOPE(isolate); | 1561 HANDLESCOPE(isolate); |
| 1560 | 1562 |
| 1561 // All registers have been saved below last-fp. | 1563 // All registers have been saved below last-fp. |
| 1562 const uword last_fp = saved_registers_address + | 1564 const uword last_fp = saved_registers_address + |
| 1563 kNumberOfCpuRegisters * kWordSize + kNumberOfXmmRegisters * kDoubleSize; | 1565 kNumberOfCpuRegisters * kWordSize + kNumberOfXmmRegisters * kDoubleSize; |
| 1564 CopySavedRegisters(saved_registers_address); | 1566 CopySavedRegisters(saved_registers_address); |
| 1565 | 1567 |
| 1566 // Get optimized code and frame that need to be deoptimized. | 1568 // Get optimized code and frame that need to be deoptimized. |
| 1567 DartFrameIterator iterator(last_fp); | 1569 DartFrameIterator iterator(last_fp); |
| 1568 StackFrame* caller_frame = iterator.NextFrame(); | 1570 StackFrame* caller_frame = iterator.NextFrame(); |
| 1569 ASSERT(caller_frame != NULL); | 1571 ASSERT(caller_frame != NULL); |
| 1570 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1572 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
| 1571 ASSERT(optimized_code.is_optimized()); | 1573 ASSERT(optimized_code.is_optimized()); |
| 1572 | 1574 |
| 1573 | 1575 |
| 1574 DeoptInfo& deopt_info = DeoptInfo::Handle(); | 1576 DeoptInfo& deopt_info = DeoptInfo::Handle(); |
| 1575 DeoptReasonId deopt_reason = kDeoptUnknown; | 1577 DeoptReasonId deopt_reason = kDeoptUnknown; |
| 1576 GetDeoptInfoAtPc(optimized_code, caller_frame->pc(), &deopt_info, | 1578 GetDeoptInfoAtPc(optimized_code, caller_frame->pc(), &deopt_info, |
| 1577 &deopt_reason); | 1579 &deopt_reason); |
| 1578 ASSERT(!deopt_info.IsNull()); | 1580 ASSERT(!deopt_info.IsNull()); |
| 1579 | 1581 |
| 1580 CopyFrame(optimized_code, *caller_frame); | 1582 CopyFrame(optimized_code, *caller_frame); |
| 1581 if (FLAG_trace_deopt) { | 1583 if (FLAG_trace_deoptimization) { |
| 1582 OS::Print("Deoptimizing (reason %d '%s') at pc %#"Px" '%s'\n", | 1584 OS::Print("Deoptimizing (reason %d '%s') at pc %#"Px" '%s'\n", |
| 1583 deopt_reason, | 1585 deopt_reason, |
| 1584 DeoptReasonToText(deopt_reason), | 1586 DeoptReasonToText(deopt_reason), |
| 1585 caller_frame->pc(), | 1587 caller_frame->pc(), |
| 1586 Function::Handle(optimized_code.function()).ToFullyQualifiedCString()); | 1588 Function::Handle(optimized_code.function()).ToFullyQualifiedCString()); |
| 1587 } | 1589 } |
| 1588 | 1590 |
| 1589 // Compute the stack size of the unoptimized frame. For functions with | 1591 // Compute the stack size of the unoptimized frame. For functions with |
| 1590 // optional arguments the deoptimization info does not describe the | 1592 // optional arguments the deoptimization info does not describe the |
| 1591 // incoming arguments. | 1593 // incoming arguments. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1620 + (caller_frame.fp() - caller_frame.sp()) / kWordSize | 1622 + (caller_frame.fp() - caller_frame.sp()) / kWordSize |
| 1621 + 3 // caller-fp, pc, pc-marker. | 1623 + 3 // caller-fp, pc, pc-marker. |
| 1622 + num_args; | 1624 + num_args; |
| 1623 DeoptimizationContext deopt_context(start, | 1625 DeoptimizationContext deopt_context(start, |
| 1624 to_frame_size, | 1626 to_frame_size, |
| 1625 Array::Handle(code.object_table()), | 1627 Array::Handle(code.object_table()), |
| 1626 num_args); | 1628 num_args); |
| 1627 for (intptr_t to_index = len - 1; to_index >= 0; to_index--) { | 1629 for (intptr_t to_index = len - 1; to_index >= 0; to_index--) { |
| 1628 deopt_instructions[to_index]->Execute(&deopt_context, to_index); | 1630 deopt_instructions[to_index]->Execute(&deopt_context, to_index); |
| 1629 } | 1631 } |
| 1630 if (FLAG_trace_deopt) { | 1632 if (FLAG_trace_deoptimization_verbose) { |
| 1631 for (intptr_t i = 0; i < len; i++) { | 1633 for (intptr_t i = 0; i < len; i++) { |
| 1632 OS::Print("*%"Pd". [%p] %#014"Px" [%s]\n", | 1634 OS::Print("*%"Pd". [%p] %#014"Px" [%s]\n", |
| 1633 i, | 1635 i, |
| 1634 &start[i], | 1636 &start[i], |
| 1635 start[i], | 1637 start[i], |
| 1636 deopt_instructions[i]->ToCString()); | 1638 deopt_instructions[i]->ToCString()); |
| 1637 } | 1639 } |
| 1638 } | 1640 } |
| 1639 return deopt_context.GetCallerFp(); | 1641 return deopt_context.GetCallerFp(); |
| 1640 } | 1642 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1683 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 1685 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
| 1684 | 1686 |
| 1685 if (function.HasOptimizedCode()) { | 1687 if (function.HasOptimizedCode()) { |
| 1686 function.SwitchToUnoptimizedCode(); | 1688 function.SwitchToUnoptimizedCode(); |
| 1687 } | 1689 } |
| 1688 return caller_fp; | 1690 return caller_fp; |
| 1689 } | 1691 } |
| 1690 END_LEAF_RUNTIME_ENTRY | 1692 END_LEAF_RUNTIME_ENTRY |
| 1691 | 1693 |
| 1692 | 1694 |
| 1695 // This is the last step in the deoptimization, GC can occur. |
| 1693 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterializeDoubles, 0) { | 1696 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterializeDoubles, 0) { |
| 1694 DeferredDouble* deferred_double = Isolate::Current()->DetachDeferredDoubles(); | 1697 DeferredDouble* deferred_double = Isolate::Current()->DetachDeferredDoubles(); |
| 1695 | 1698 |
| 1696 while (deferred_double != NULL) { | 1699 while (deferred_double != NULL) { |
| 1697 DeferredDouble* current = deferred_double; | 1700 DeferredDouble* current = deferred_double; |
| 1698 deferred_double = deferred_double->next(); | 1701 deferred_double = deferred_double->next(); |
| 1699 | 1702 |
| 1700 RawDouble** slot = current->slot(); | 1703 RawDouble** slot = current->slot(); |
| 1701 *slot = Double::New(current->value()); | 1704 *slot = Double::New(current->value()); |
| 1702 | 1705 |
| 1703 if (FLAG_trace_deopt) { | 1706 if (FLAG_trace_deoptimization_verbose) { |
| 1704 OS::Print("materializing double at %"Px": %g\n", | 1707 OS::Print("materializing double at %"Px": %g\n", |
| 1705 reinterpret_cast<uword>(current->slot()), | 1708 reinterpret_cast<uword>(current->slot()), |
| 1706 current->value()); | 1709 current->value()); |
| 1707 } | 1710 } |
| 1708 | 1711 |
| 1709 delete current; | 1712 delete current; |
| 1710 } | 1713 } |
| 1711 | 1714 |
| 1712 DeferredMint* deferred_mint = Isolate::Current()->DetachDeferredMints(); | 1715 DeferredMint* deferred_mint = Isolate::Current()->DetachDeferredMints(); |
| 1713 | 1716 |
| 1714 while (deferred_mint != NULL) { | 1717 while (deferred_mint != NULL) { |
| 1715 DeferredMint* current = deferred_mint; | 1718 DeferredMint* current = deferred_mint; |
| 1716 deferred_mint = deferred_mint->next(); | 1719 deferred_mint = deferred_mint->next(); |
| 1717 | 1720 |
| 1718 RawMint** slot = current->slot(); | 1721 RawMint** slot = current->slot(); |
| 1719 ASSERT(!Smi::IsValid64(current->value())); | 1722 ASSERT(!Smi::IsValid64(current->value())); |
| 1720 *slot = Mint::New(current->value()); | 1723 *slot = Mint::New(current->value()); |
| 1721 | 1724 |
| 1722 if (FLAG_trace_deopt) { | 1725 if (FLAG_trace_deoptimization_verbose) { |
| 1723 OS::Print("materializing mint at %"Px": %"Pd64"\n", | 1726 OS::Print("materializing mint at %"Px": %"Pd64"\n", |
| 1724 reinterpret_cast<uword>(current->slot()), | 1727 reinterpret_cast<uword>(current->slot()), |
| 1725 current->value()); | 1728 current->value()); |
| 1726 } | 1729 } |
| 1727 | 1730 |
| 1728 delete current; | 1731 delete current; |
| 1729 } | 1732 } |
| 1733 // Since this is the only step where GC can occur during deoptimization, |
| 1734 // use it to report the source line where deoptimization occured. |
| 1735 if (FLAG_trace_deoptimization) { |
| 1736 DartFrameIterator iterator; |
| 1737 StackFrame* top_frame = iterator.NextFrame(); |
| 1738 ASSERT(top_frame != NULL); |
| 1739 const Code& code = Code::Handle(top_frame->LookupDartCode()); |
| 1740 const Function& top_function = Function::Handle(code.function()); |
| 1741 const Script& script = Script::Handle(top_function.script()); |
| 1742 const intptr_t token_pos = code.GetTokenIndexOfPC(top_frame->pc()); |
| 1743 intptr_t line, column; |
| 1744 script.GetTokenLocation(token_pos, &line, &column); |
| 1745 String& line_string = String::Handle(script.GetLine(line)); |
| 1746 OS::Print(" Function: %s\n", top_function.ToFullyQualifiedCString()); |
| 1747 OS::Print(" Line %"Pd": '%s'\n", line, line_string.ToCString()); |
| 1748 } |
| 1730 } | 1749 } |
| 1731 | 1750 |
| 1732 | 1751 |
| 1733 } // namespace dart | 1752 } // namespace dart |
| OLD | NEW |