Chromium Code Reviews| 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/deopt_instructions.h" | 5 #include "vm/deopt_instructions.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 #include "vm/locations.h" | 10 #include "vm/locations.h" |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 } | 559 } |
| 560 | 560 |
| 561 virtual DeoptInstr::Kind kind() const { return kRetAddress; } | 561 virtual DeoptInstr::Kind kind() const { return kRetAddress; } |
| 562 | 562 |
| 563 virtual const char* ToCString() const { | 563 virtual const char* ToCString() const { |
| 564 return Isolate::Current()->current_zone()->PrintToString( | 564 return Isolate::Current()->current_zone()->PrintToString( |
| 565 "ret oti:%" Pd "(%" Pd ")", object_table_index_, deopt_id_); | 565 "ret oti:%" Pd "(%" Pd ")", object_table_index_, deopt_id_); |
| 566 } | 566 } |
| 567 | 567 |
| 568 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 568 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 569 Function& function = Function::Handle(deopt_context->isolate()); | 569 Code& code = Code::Handle(deopt_context->isolate()); |
| 570 function ^= deopt_context->ObjectAt(object_table_index_); | 570 code ^= deopt_context->ObjectAt(object_table_index_); |
| 571 const Code& code = | |
| 572 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | |
| 573 ASSERT(!code.IsNull()); | 571 ASSERT(!code.IsNull()); |
| 574 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, | 572 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, |
| 575 PcDescriptors::kDeopt); | 573 PcDescriptors::kDeopt); |
| 576 ASSERT(continue_at_pc != 0); | 574 ASSERT(continue_at_pc != 0); |
| 577 *dest_addr = continue_at_pc; | 575 *dest_addr = continue_at_pc; |
| 578 | 576 |
| 579 uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall); | 577 uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall); |
| 580 if (pc != 0) { | 578 if (pc != 0) { |
| 581 // If the deoptimization happened at an IC call, update the IC data | 579 // If the deoptimization happened at an IC call, update the IC data |
| 582 // to avoid repeated deoptimization at the same site next time around. | 580 // to avoid repeated deoptimization at the same site next time around. |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 782 | 780 |
| 783 virtual intptr_t source_index() const { return object_table_index_; } | 781 virtual intptr_t source_index() const { return object_table_index_; } |
| 784 virtual DeoptInstr::Kind kind() const { return kPcMarker; } | 782 virtual DeoptInstr::Kind kind() const { return kPcMarker; } |
| 785 | 783 |
| 786 virtual const char* ToCString() const { | 784 virtual const char* ToCString() const { |
| 787 return Isolate::Current()->current_zone()->PrintToString( | 785 return Isolate::Current()->current_zone()->PrintToString( |
| 788 "pcmark oti:%" Pd "", object_table_index_); | 786 "pcmark oti:%" Pd "", object_table_index_); |
| 789 } | 787 } |
| 790 | 788 |
| 791 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 789 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 792 Function& function = Function::Handle(deopt_context->isolate()); | 790 Code& code = Code::Handle(deopt_context->isolate()); |
| 793 function ^= deopt_context->ObjectAt(object_table_index_); | 791 code ^= deopt_context->ObjectAt(object_table_index_); |
| 794 if (function.IsNull()) { | 792 if (code.IsNull()) { |
| 795 // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0. | 793 // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0. |
| 796 *dest_addr = 0; | 794 *dest_addr = 0; |
| 797 return; | 795 return; |
| 798 } | 796 } |
| 799 const Code& code = | 797 const Function& function = |
| 800 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | 798 Function::Handle(deopt_context->isolate(), code.function()); |
| 801 ASSERT(!code.IsNull()); | 799 if (!function.HasCode()) { |
|
Ivan Posva
2013/11/16 00:06:21
Should be an assert. The unoptimized code cannot b
zra
2013/11/18 18:54:33
Changed to ASSERT.
| |
| 800 ASSERT(!code.is_optimized()); | |
| 801 function.ReattachCode(code); | |
| 802 } | |
| 802 const intptr_t pc_marker = | 803 const intptr_t pc_marker = |
| 803 code.EntryPoint() + Assembler::kEntryPointToPcMarkerOffset; | 804 code.EntryPoint() + Assembler::kEntryPointToPcMarkerOffset; |
| 804 *dest_addr = pc_marker; | 805 *dest_addr = pc_marker; |
| 805 // Increment the deoptimization counter. This effectively increments each | 806 // Increment the deoptimization counter. This effectively increments each |
| 806 // function occurring in the optimized frame. | 807 // function occurring in the optimized frame. |
| 807 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 808 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
| 808 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | 809 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| 809 OS::PrintErr("Deoptimizing %s (count %d)\n", | 810 OS::PrintErr("Deoptimizing %s (count %d)\n", |
| 810 function.ToFullyQualifiedCString(), | 811 function.ToFullyQualifiedCString(), |
| 811 function.deoptimization_counter()); | 812 function.deoptimization_counter()); |
| 812 } | 813 } |
| 813 // Clear invocation counter so that hopefully the function gets reoptimized | 814 // Clear invocation counter so that hopefully the function gets reoptimized |
| 814 // only after more feedback has been collected. | 815 // only after more feedback has been collected. |
| 815 function.set_usage_counter(0); | 816 function.set_usage_counter(0); |
| 816 if (function.HasOptimizedCode()) function.SwitchToUnoptimizedCode(); | 817 if (function.HasOptimizedCode()) { |
| 818 function.SwitchToUnoptimizedCode(); | |
| 819 } | |
| 817 } | 820 } |
| 818 | 821 |
| 819 private: | 822 private: |
| 820 intptr_t object_table_index_; | 823 intptr_t object_table_index_; |
| 821 | 824 |
| 822 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); | 825 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); |
| 823 }; | 826 }; |
| 824 | 827 |
| 825 | 828 |
| 826 // Deoptimization instruction creating a pool pointer for the code of | 829 // Deoptimization instruction creating a pool pointer for the code of |
| 827 // function at 'object_table_index'. | 830 // function at 'object_table_index'. |
| 828 class DeoptPpInstr : public DeoptInstr { | 831 class DeoptPpInstr : public DeoptInstr { |
| 829 public: | 832 public: |
| 830 explicit DeoptPpInstr(intptr_t object_table_index) | 833 explicit DeoptPpInstr(intptr_t object_table_index) |
| 831 : object_table_index_(object_table_index) { | 834 : object_table_index_(object_table_index) { |
| 832 ASSERT(object_table_index >= 0); | 835 ASSERT(object_table_index >= 0); |
| 833 } | 836 } |
| 834 | 837 |
| 835 virtual intptr_t source_index() const { return object_table_index_; } | 838 virtual intptr_t source_index() const { return object_table_index_; } |
| 836 virtual DeoptInstr::Kind kind() const { return kPp; } | 839 virtual DeoptInstr::Kind kind() const { return kPp; } |
| 837 | 840 |
| 838 virtual const char* ToCString() const { | 841 virtual const char* ToCString() const { |
| 839 return Isolate::Current()->current_zone()->PrintToString( | 842 return Isolate::Current()->current_zone()->PrintToString( |
| 840 "pp oti:%" Pd "", object_table_index_); | 843 "pp oti:%" Pd "", object_table_index_); |
| 841 } | 844 } |
| 842 | 845 |
| 843 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 846 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 844 Function& function = Function::Handle(deopt_context->isolate()); | 847 Code& code = Code::Handle(deopt_context->isolate()); |
| 845 function ^= deopt_context->ObjectAt(object_table_index_); | 848 code ^= deopt_context->ObjectAt(object_table_index_); |
| 846 const Code& code = | |
| 847 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | |
| 848 ASSERT(!code.IsNull()); | 849 ASSERT(!code.IsNull()); |
| 849 const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool()); | 850 const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool()); |
| 850 *dest_addr = pp; | 851 *dest_addr = pp; |
| 851 } | 852 } |
| 852 | 853 |
| 853 private: | 854 private: |
| 854 intptr_t object_table_index_; | 855 intptr_t object_table_index_; |
| 855 | 856 |
| 856 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); | 857 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); |
| 857 }; | 858 }; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1044 const Array& object_table, | 1045 const Array& object_table, |
| 1045 Function* func) { | 1046 Function* func) { |
| 1046 ASSERT(instr->kind() == kRetAddress); | 1047 ASSERT(instr->kind() == kRetAddress); |
| 1047 DeoptRetAddressInstr* ret_address_instr = | 1048 DeoptRetAddressInstr* ret_address_instr = |
| 1048 static_cast<DeoptRetAddressInstr*>(instr); | 1049 static_cast<DeoptRetAddressInstr*>(instr); |
| 1049 // The following assert may trigger when displaying a backtrace | 1050 // The following assert may trigger when displaying a backtrace |
| 1050 // from the simulator. | 1051 // from the simulator. |
| 1051 ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id())); | 1052 ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id())); |
| 1052 ASSERT(!object_table.IsNull()); | 1053 ASSERT(!object_table.IsNull()); |
| 1053 ASSERT(func != NULL); | 1054 ASSERT(func != NULL); |
| 1054 *func ^= object_table.At(ret_address_instr->object_table_index()); | 1055 Code& code = Code::Handle(); |
| 1055 const Code& code = Code::Handle(func->unoptimized_code()); | 1056 code ^= object_table.At(ret_address_instr->object_table_index()); |
| 1056 ASSERT(!code.IsNull()); | 1057 ASSERT(!code.IsNull()); |
| 1058 *func ^= code.function(); | |
| 1057 uword res = code.GetPcForDeoptId(ret_address_instr->deopt_id(), | 1059 uword res = code.GetPcForDeoptId(ret_address_instr->deopt_id(), |
| 1058 PcDescriptors::kDeopt); | 1060 PcDescriptors::kDeopt); |
| 1059 ASSERT(res != 0); | 1061 ASSERT(res != 0); |
| 1060 return res; | 1062 return res; |
| 1061 } | 1063 } |
| 1062 | 1064 |
| 1063 | 1065 |
| 1064 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { | 1066 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { |
| 1065 Kind kind = static_cast<Kind>(kind_as_int); | 1067 Kind kind = static_cast<Kind>(kind_as_int); |
| 1066 switch (kind) { | 1068 switch (kind) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1154 | 1156 |
| 1155 | 1157 |
| 1156 intptr_t DeoptInfoBuilder::CalculateStackIndex( | 1158 intptr_t DeoptInfoBuilder::CalculateStackIndex( |
| 1157 const Location& source_loc) const { | 1159 const Location& source_loc) const { |
| 1158 return source_loc.stack_index() < 0 ? | 1160 return source_loc.stack_index() < 0 ? |
| 1159 source_loc.stack_index() + num_args_ : | 1161 source_loc.stack_index() + num_args_ : |
| 1160 source_loc.stack_index() + num_args_ + kDartFrameFixedSize; | 1162 source_loc.stack_index() + num_args_ + kDartFrameFixedSize; |
| 1161 } | 1163 } |
| 1162 | 1164 |
| 1163 | 1165 |
| 1164 void DeoptInfoBuilder::AddReturnAddress(const Function& function, | 1166 void DeoptInfoBuilder::AddReturnAddress(const Code& code, |
| 1165 intptr_t deopt_id, | 1167 intptr_t deopt_id, |
| 1166 intptr_t dest_index) { | 1168 intptr_t dest_index) { |
| 1167 // Check that deopt_id exists. | 1169 // Check that deopt_id exists. |
| 1168 // TODO(vegorov): verify after deoptimization targets as well. | 1170 // TODO(vegorov): verify after deoptimization targets as well. |
| 1169 #ifdef DEBUG | 1171 #ifdef DEBUG |
| 1170 const Code& code = Code::Handle(function.unoptimized_code()); | 1172 ASSERT(Isolate::IsDeoptAfter(deopt_id) || |
| 1171 // The inlined function's code pointer may be null if there is a GC during | 1173 (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0)); |
| 1172 // compilation. | |
| 1173 // TODO(zra): See if we can avoid this check by ensuring that code is not | |
| 1174 // removed during inlining. | |
| 1175 ASSERT(code.IsNull() || Isolate::IsDeoptAfter(deopt_id) || | |
| 1176 (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0)); | |
| 1177 #endif | 1174 #endif |
| 1178 const intptr_t object_table_index = FindOrAddObjectInTable(function); | 1175 const intptr_t object_table_index = FindOrAddObjectInTable(code); |
| 1179 ASSERT(dest_index == FrameSize()); | 1176 ASSERT(dest_index == FrameSize()); |
| 1180 instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id)); | 1177 instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id)); |
| 1181 } | 1178 } |
| 1182 | 1179 |
| 1183 | 1180 |
| 1184 void DeoptInfoBuilder::AddPcMarker(const Function& function, | 1181 void DeoptInfoBuilder::AddPcMarker(const Code& code, |
| 1185 intptr_t dest_index) { | 1182 intptr_t dest_index) { |
| 1186 intptr_t object_table_index = FindOrAddObjectInTable(function); | 1183 intptr_t object_table_index = FindOrAddObjectInTable(code); |
| 1187 ASSERT(dest_index == FrameSize()); | 1184 ASSERT(dest_index == FrameSize()); |
| 1188 instructions_.Add(new DeoptPcMarkerInstr(object_table_index)); | 1185 instructions_.Add(new DeoptPcMarkerInstr(object_table_index)); |
| 1189 } | 1186 } |
| 1190 | 1187 |
| 1191 | 1188 |
| 1192 void DeoptInfoBuilder::AddPp(const Function& function, intptr_t dest_index) { | 1189 void DeoptInfoBuilder::AddPp(const Code& code, |
| 1193 intptr_t object_table_index = FindOrAddObjectInTable(function); | 1190 intptr_t dest_index) { |
| 1191 intptr_t object_table_index = FindOrAddObjectInTable(code); | |
| 1194 ASSERT(dest_index == FrameSize()); | 1192 ASSERT(dest_index == FrameSize()); |
| 1195 instructions_.Add(new DeoptPpInstr(object_table_index)); | 1193 instructions_.Add(new DeoptPpInstr(object_table_index)); |
| 1196 } | 1194 } |
| 1197 | 1195 |
| 1198 | 1196 |
| 1199 void DeoptInfoBuilder::AddCopy(Value* value, | 1197 void DeoptInfoBuilder::AddCopy(Value* value, |
| 1200 const Location& source_loc, | 1198 const Location& source_loc, |
| 1201 const intptr_t dest_index) { | 1199 const intptr_t dest_index) { |
| 1202 DeoptInstr* deopt_instr = NULL; | 1200 DeoptInstr* deopt_instr = NULL; |
| 1203 if (source_loc.IsConstant()) { | 1201 if (source_loc.IsConstant()) { |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1411 Smi* offset, | 1409 Smi* offset, |
| 1412 DeoptInfo* info, | 1410 DeoptInfo* info, |
| 1413 Smi* reason) { | 1411 Smi* reason) { |
| 1414 intptr_t i = index * kEntrySize; | 1412 intptr_t i = index * kEntrySize; |
| 1415 *offset ^= table.At(i); | 1413 *offset ^= table.At(i); |
| 1416 *info ^= table.At(i + 1); | 1414 *info ^= table.At(i + 1); |
| 1417 *reason ^= table.At(i + 2); | 1415 *reason ^= table.At(i + 2); |
| 1418 } | 1416 } |
| 1419 | 1417 |
| 1420 } // namespace dart | 1418 } // namespace dart |
| OLD | NEW |