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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 "Traces all failed optimization attempts"); | 50 "Traces all failed optimization attempts"); |
51 DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling"); | 51 DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling"); |
52 DEFINE_FLAG(bool, trace_ic_miss_in_optimized, false, | 52 DEFINE_FLAG(bool, trace_ic_miss_in_optimized, false, |
53 "Trace IC miss in optimized code"); | 53 "Trace IC miss in optimized code"); |
54 DEFINE_FLAG(bool, trace_optimized_ic_calls, false, | 54 DEFINE_FLAG(bool, trace_optimized_ic_calls, false, |
55 "Trace IC calls in optimized code."); | 55 "Trace IC calls in optimized code."); |
56 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code."); | 56 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code."); |
57 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls"); | 57 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls"); |
58 DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks."); | 58 DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks."); |
59 | 59 |
60 DECLARE_FLAG(int, deoptimization_counter_threshold); | 60 DECLARE_FLAG(int, max_deoptimization_counter_threshold); |
61 DECLARE_FLAG(bool, enable_inlining_annotations); | 61 DECLARE_FLAG(bool, enable_inlining_annotations); |
62 DECLARE_FLAG(bool, trace_compiler); | 62 DECLARE_FLAG(bool, trace_compiler); |
63 DECLARE_FLAG(bool, trace_optimizing_compiler); | 63 DECLARE_FLAG(bool, trace_optimizing_compiler); |
64 DECLARE_FLAG(bool, warn_on_javascript_compatibility); | 64 DECLARE_FLAG(bool, warn_on_javascript_compatibility); |
65 DECLARE_FLAG(int, max_polymorphic_checks); | 65 DECLARE_FLAG(int, max_polymorphic_checks); |
66 | 66 |
67 DEFINE_FLAG(bool, use_osr, true, "Use on-stack replacement."); | 67 DEFINE_FLAG(bool, use_osr, true, "Use on-stack replacement."); |
68 DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement."); | 68 DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement."); |
69 | 69 |
70 DEFINE_FLAG(int, stacktrace_every, 0, | 70 DEFINE_FLAG(int, stacktrace_every, 0, |
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 const Code& target_code = Code::Handle(target_function.CurrentCode()); | 670 const Code& target_code = Code::Handle(target_function.CurrentCode()); |
671 // Before patching verify that we are not repeatedly patching to the same | 671 // Before patching verify that we are not repeatedly patching to the same |
672 // target. | 672 // target. |
673 ASSERT(target_code.raw() != | 673 ASSERT(target_code.raw() != |
674 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); | 674 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); |
675 CodePatcher::PatchStaticCallAt(caller_frame->pc(), | 675 CodePatcher::PatchStaticCallAt(caller_frame->pc(), |
676 caller_code, | 676 caller_code, |
677 target_code); | 677 target_code); |
678 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); | 678 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); |
679 if (FLAG_trace_patching) { | 679 if (FLAG_trace_patching) { |
680 OS::PrintErr("PatchStaticCall: patching caller pc %#" Px "" | 680 THR_Print("PatchStaticCall: patching caller pc %#" Px "" |
681 " to '%s' new entry point %#" Px " (%s)\n", | 681 " to '%s' new entry point %#" Px " (%s)\n", |
682 caller_frame->pc(), | 682 caller_frame->pc(), |
683 target_function.ToFullyQualifiedCString(), | 683 target_function.ToFullyQualifiedCString(), |
684 target_code.EntryPoint(), | 684 target_code.EntryPoint(), |
685 target_code.is_optimized() ? "optimized" : "unoptimized"); | 685 target_code.is_optimized() ? "optimized" : "unoptimized"); |
686 } | 686 } |
687 arguments.SetReturn(target_code); | 687 arguments.SetReturn(target_code); |
688 } | 688 } |
689 | 689 |
690 | 690 |
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 const intptr_t kLowInvocationCount = -100000000; | 1248 const intptr_t kLowInvocationCount = -100000000; |
1249 Isolate* isolate = thread->isolate(); | 1249 Isolate* isolate = thread->isolate(); |
1250 if (isolate->debugger()->IsStepping() || | 1250 if (isolate->debugger()->IsStepping() || |
1251 isolate->debugger()->HasBreakpoint(function, thread->zone())) { | 1251 isolate->debugger()->HasBreakpoint(function, thread->zone())) { |
1252 // We cannot set breakpoints and single step in optimized code, | 1252 // We cannot set breakpoints and single step in optimized code, |
1253 // so do not optimize the function. | 1253 // so do not optimize the function. |
1254 function.set_usage_counter(0); | 1254 function.set_usage_counter(0); |
1255 return false; | 1255 return false; |
1256 } | 1256 } |
1257 if (function.deoptimization_counter() >= | 1257 if (function.deoptimization_counter() >= |
1258 FLAG_deoptimization_counter_threshold) { | 1258 FLAG_max_deoptimization_counter_threshold) { |
1259 if (FLAG_trace_failed_optimization_attempts || | 1259 if (FLAG_trace_failed_optimization_attempts || |
1260 FLAG_stop_on_excessive_deoptimization) { | 1260 FLAG_stop_on_excessive_deoptimization) { |
1261 OS::PrintErr("Too Many Deoptimizations: %s\n", | 1261 OS::PrintErr("Too Many Deoptimizations: %s\n", |
1262 function.ToFullyQualifiedCString()); | 1262 function.ToFullyQualifiedCString()); |
1263 if (FLAG_stop_on_excessive_deoptimization) { | 1263 if (FLAG_stop_on_excessive_deoptimization) { |
1264 FATAL("Stop on excessive deoptimization"); | 1264 FATAL("Stop on excessive deoptimization"); |
1265 } | 1265 } |
1266 } | 1266 } |
1267 // TODO(srdjan): Investigate excessive deoptimization. | 1267 // TODO(srdjan): Investigate excessive deoptimization. |
1268 function.set_usage_counter(kLowInvocationCount); | 1268 function.set_usage_counter(kLowInvocationCount); |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1700 cpu_registers_copy[i] = | 1700 cpu_registers_copy[i] = |
1701 *reinterpret_cast<intptr_t*>(saved_registers_address); | 1701 *reinterpret_cast<intptr_t*>(saved_registers_address); |
1702 saved_registers_address += kWordSize; | 1702 saved_registers_address += kWordSize; |
1703 } | 1703 } |
1704 *cpu_registers = cpu_registers_copy; | 1704 *cpu_registers = cpu_registers_copy; |
1705 } | 1705 } |
1706 | 1706 |
1707 | 1707 |
1708 // Copies saved registers and caller's frame into temporary buffers. | 1708 // Copies saved registers and caller's frame into temporary buffers. |
1709 // Returns the stack size of unoptimized frame. | 1709 // Returns the stack size of unoptimized frame. |
| 1710 // The calling code must be optimized, but its function may not have |
| 1711 // have optimized code if the code is OSR code, or if the code was invalidated |
| 1712 // through class loading/finalization or field guard. |
1710 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 1713 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
1711 2, | 1714 2, |
1712 uword saved_registers_address, | 1715 uword saved_registers_address, |
1713 uword is_lazy_deopt) { | 1716 uword is_lazy_deopt) { |
1714 Thread* thread = Thread::Current(); | 1717 Thread* thread = Thread::Current(); |
1715 Isolate* isolate = thread->isolate(); | 1718 Isolate* isolate = thread->isolate(); |
1716 StackZone zone(thread); | 1719 StackZone zone(thread); |
1717 HANDLESCOPE(thread); | 1720 HANDLESCOPE(thread); |
1718 | 1721 |
1719 // All registers have been saved below last-fp as if they were locals. | 1722 // All registers have been saved below last-fp as if they were locals. |
1720 const uword last_fp = saved_registers_address | 1723 const uword last_fp = saved_registers_address |
1721 + (kNumberOfCpuRegisters * kWordSize) | 1724 + (kNumberOfCpuRegisters * kWordSize) |
1722 + (kNumberOfFpuRegisters * kFpuRegisterSize) | 1725 + (kNumberOfFpuRegisters * kFpuRegisterSize) |
1723 - ((kFirstLocalSlotFromFp + 1) * kWordSize); | 1726 - ((kFirstLocalSlotFromFp + 1) * kWordSize); |
1724 | 1727 |
1725 // Get optimized code and frame that need to be deoptimized. | 1728 // Get optimized code and frame that need to be deoptimized. |
1726 DartFrameIterator iterator(last_fp); | 1729 DartFrameIterator iterator(last_fp); |
1727 StackFrame* caller_frame = iterator.NextFrame(); | 1730 StackFrame* caller_frame = iterator.NextFrame(); |
1728 ASSERT(caller_frame != NULL); | 1731 ASSERT(caller_frame != NULL); |
1729 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1732 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
1730 ASSERT(optimized_code.is_optimized()); | 1733 ASSERT(optimized_code.is_optimized()); |
| 1734 const Function& top_function = |
| 1735 Function::Handle(thread->zone(), optimized_code.function()); |
| 1736 const bool deoptimizing_code = top_function.HasOptimizedCode(); |
| 1737 if (FLAG_trace_deoptimization) { |
| 1738 const Function& function = Function::Handle(optimized_code.function()); |
| 1739 THR_Print("== Deoptimizing code for '%s', %s, %s\n", |
| 1740 function.ToFullyQualifiedCString(), |
| 1741 deoptimizing_code ? "code & frame" : "frame", |
| 1742 is_lazy_deopt ? "lazy-deopt" : ""); |
| 1743 } |
1731 | 1744 |
1732 // Copy the saved registers from the stack. | 1745 // Copy the saved registers from the stack. |
1733 fpu_register_t* fpu_registers; | 1746 fpu_register_t* fpu_registers; |
1734 intptr_t* cpu_registers; | 1747 intptr_t* cpu_registers; |
1735 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); | 1748 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); |
1736 | 1749 |
1737 // Create the DeoptContext. | 1750 // Create the DeoptContext. |
1738 DeoptContext* deopt_context = | 1751 DeoptContext* deopt_context = |
1739 new DeoptContext(caller_frame, | 1752 new DeoptContext(caller_frame, |
1740 optimized_code, | 1753 optimized_code, |
1741 DeoptContext::kDestIsOriginalFrame, | 1754 DeoptContext::kDestIsOriginalFrame, |
1742 fpu_registers, | 1755 fpu_registers, |
1743 cpu_registers, | 1756 cpu_registers, |
1744 is_lazy_deopt != 0); | 1757 is_lazy_deopt != 0, |
| 1758 deoptimizing_code); |
1745 isolate->set_deopt_context(deopt_context); | 1759 isolate->set_deopt_context(deopt_context); |
1746 | 1760 |
1747 // Stack size (FP - SP) in bytes. | 1761 // Stack size (FP - SP) in bytes. |
1748 return deopt_context->DestStackAdjustment() * kWordSize; | 1762 return deopt_context->DestStackAdjustment() * kWordSize; |
1749 } | 1763 } |
1750 END_LEAF_RUNTIME_ENTRY | 1764 END_LEAF_RUNTIME_ENTRY |
1751 | 1765 |
1752 | 1766 |
1753 // The stack has been adjusted to fit all values for unoptimized frame. | 1767 // The stack has been adjusted to fit all values for unoptimized frame. |
1754 // Fill the unoptimized frame. | 1768 // Fill the unoptimized frame. |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1875 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1889 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1876 const TypedData& new_data = | 1890 const TypedData& new_data = |
1877 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1891 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1878 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1892 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1879 typed_data_cell.SetAt(0, new_data); | 1893 typed_data_cell.SetAt(0, new_data); |
1880 arguments.SetReturn(new_data); | 1894 arguments.SetReturn(new_data); |
1881 } | 1895 } |
1882 | 1896 |
1883 | 1897 |
1884 } // namespace dart | 1898 } // namespace dart |
OLD | NEW |