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/compiler.h" |
9 #include "vm/intermediate_language.h" | 10 #include "vm/intermediate_language.h" |
10 #include "vm/locations.h" | 11 #include "vm/locations.h" |
11 #include "vm/parser.h" | 12 #include "vm/parser.h" |
12 #include "vm/stack_frame.h" | 13 #include "vm/stack_frame.h" |
13 #include "vm/thread.h" | 14 #include "vm/thread.h" |
14 | 15 |
15 namespace dart { | 16 namespace dart { |
16 | 17 |
17 DEFINE_FLAG(bool, compress_deopt_info, true, | 18 DEFINE_FLAG(bool, compress_deopt_info, true, |
18 "Compress the size of the deoptimization info for optimized code."); | 19 "Compress the size of the deoptimization info for optimized code."); |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 } | 371 } |
371 | 372 |
372 virtual DeoptInstr::Kind kind() const { return kRetAddress; } | 373 virtual DeoptInstr::Kind kind() const { return kRetAddress; } |
373 | 374 |
374 virtual const char* ArgumentsToCString() const { | 375 virtual const char* ArgumentsToCString() const { |
375 return Thread::Current()->zone()->PrintToString( | 376 return Thread::Current()->zone()->PrintToString( |
376 "%" Pd ", %" Pd "", object_table_index_, deopt_id_); | 377 "%" Pd ", %" Pd "", object_table_index_, deopt_id_); |
377 } | 378 } |
378 | 379 |
379 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 380 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
380 Code& code = Code::Handle(deopt_context->zone()); | 381 *dest_addr = Smi::RawValue(0); |
381 code ^= deopt_context->ObjectAt(object_table_index_); | 382 deopt_context->DeferRetAddrMaterialization( |
382 ASSERT(!code.IsNull()); | 383 object_table_index_, deopt_id_, dest_addr); |
383 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, | |
384 RawPcDescriptors::kDeopt); | |
385 ASSERT(continue_at_pc != 0); | |
386 *dest_addr = continue_at_pc; | |
387 | |
388 uword pc = code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kIcCall); | |
389 if (pc != 0) { | |
390 // If the deoptimization happened at an IC call, update the IC data | |
391 // to avoid repeated deoptimization at the same site next time around. | |
392 ICData& ic_data = ICData::Handle(); | |
393 CodePatcher::GetInstanceCallAt(pc, code, &ic_data); | |
394 if (!ic_data.IsNull()) { | |
395 ic_data.AddDeoptReason(deopt_context->deopt_reason()); | |
396 } | |
397 } else { | |
398 const Function& function = Function::Handle(code.function()); | |
399 if (deopt_context->HasDeoptFlag(ICData::kHoisted)) { | |
400 // Prevent excessive deoptimization. | |
401 function.set_allows_hoisting_check_class(false); | |
402 } | |
403 | |
404 if (deopt_context->HasDeoptFlag(ICData::kGeneralized)) { | |
405 function.set_allows_bounds_check_generalization(false); | |
406 } | |
407 } | |
408 } | 384 } |
409 | 385 |
410 intptr_t object_table_index() const { return object_table_index_; } | 386 intptr_t object_table_index() const { return object_table_index_; } |
411 intptr_t deopt_id() const { return deopt_id_; } | 387 intptr_t deopt_id() const { return deopt_id_; } |
412 | 388 |
413 private: | 389 private: |
414 static const intptr_t kFieldWidth = kBitsPerWord / 2; | 390 static const intptr_t kFieldWidth = kBitsPerWord / 2; |
415 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { }; | 391 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { }; |
416 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; | 392 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; |
417 | 393 |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 | 610 |
635 virtual intptr_t source_index() const { return object_table_index_; } | 611 virtual intptr_t source_index() const { return object_table_index_; } |
636 virtual DeoptInstr::Kind kind() const { return kPcMarker; } | 612 virtual DeoptInstr::Kind kind() const { return kPcMarker; } |
637 | 613 |
638 virtual const char* ArgumentsToCString() const { | 614 virtual const char* ArgumentsToCString() const { |
639 return Thread::Current()->zone()->PrintToString( | 615 return Thread::Current()->zone()->PrintToString( |
640 "%" Pd "", object_table_index_); | 616 "%" Pd "", object_table_index_); |
641 } | 617 } |
642 | 618 |
643 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 619 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
644 Code& code = Code::Handle(deopt_context->zone()); | 620 *dest_addr = Smi::RawValue(0); |
645 code ^= deopt_context->ObjectAt(object_table_index_); | 621 deopt_context->DeferPcMarkerMaterialization( |
646 if (code.IsNull()) { | 622 object_table_index_, dest_addr); |
647 // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0. | |
648 *dest_addr = 0; | |
649 return; | |
650 } | |
651 const Function& function = | |
652 Function::Handle(deopt_context->zone(), code.function()); | |
653 ASSERT(function.HasCode()); | |
654 const intptr_t pc_marker = | |
655 code.EntryPoint() + Assembler::EntryPointToPcMarkerOffset(); | |
656 *dest_addr = pc_marker; | |
657 // Increment the deoptimization counter. This effectively increments each | |
658 // function occurring in the optimized frame. | |
659 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | |
660 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | |
661 OS::PrintErr("Deoptimizing %s (count %d)\n", | |
662 function.ToFullyQualifiedCString(), | |
663 function.deoptimization_counter()); | |
664 } | |
665 // Clear invocation counter so that hopefully the function gets reoptimized | |
666 // only after more feedback has been collected. | |
667 function.set_usage_counter(0); | |
668 if (function.HasOptimizedCode()) { | |
669 function.SwitchToUnoptimizedCode(); | |
670 } | |
671 } | 623 } |
672 | 624 |
673 private: | 625 private: |
674 intptr_t object_table_index_; | 626 intptr_t object_table_index_; |
675 | 627 |
676 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); | 628 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); |
677 }; | 629 }; |
678 | 630 |
679 | 631 |
680 // Deoptimization instruction creating a pool pointer for the code of | 632 // Deoptimization instruction creating a pool pointer for the code of |
681 // function at 'object_table_index'. | 633 // function at 'object_table_index'. |
682 class DeoptPpInstr : public DeoptInstr { | 634 class DeoptPpInstr : public DeoptInstr { |
683 public: | 635 public: |
684 explicit DeoptPpInstr(intptr_t object_table_index) | 636 explicit DeoptPpInstr(intptr_t object_table_index) |
685 : object_table_index_(object_table_index) { | 637 : object_table_index_(object_table_index) { |
686 ASSERT(object_table_index >= 0); | 638 ASSERT(object_table_index >= 0); |
687 } | 639 } |
688 | 640 |
689 virtual intptr_t source_index() const { return object_table_index_; } | 641 virtual intptr_t source_index() const { return object_table_index_; } |
690 virtual DeoptInstr::Kind kind() const { return kPp; } | 642 virtual DeoptInstr::Kind kind() const { return kPp; } |
691 | 643 |
692 virtual const char* ArgumentsToCString() const { | 644 virtual const char* ArgumentsToCString() const { |
693 return Thread::Current()->zone()->PrintToString( | 645 return Thread::Current()->zone()->PrintToString( |
694 "%" Pd "", object_table_index_); | 646 "%" Pd "", object_table_index_); |
695 } | 647 } |
696 | 648 |
697 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 649 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
698 Code& code = Code::Handle(deopt_context->zone()); | 650 *dest_addr = Smi::RawValue(0); |
699 code ^= deopt_context->ObjectAt(object_table_index_); | 651 deopt_context->DeferPpMaterialization(object_table_index_, |
700 ASSERT(!code.IsNull()); | 652 reinterpret_cast<RawObject**>(dest_addr)); |
701 const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool()); | |
702 *dest_addr = pp; | |
703 } | 653 } |
704 | 654 |
705 private: | 655 private: |
706 intptr_t object_table_index_; | 656 intptr_t object_table_index_; |
707 | 657 |
708 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); | 658 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); |
709 }; | 659 }; |
710 | 660 |
711 | 661 |
712 // Deoptimization instruction copying the caller saved FP from optimized frame. | 662 // Deoptimization instruction copying the caller saved FP from optimized frame. |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, | 833 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, |
884 const Array& object_table, | 834 const Array& object_table, |
885 Code* code) { | 835 Code* code) { |
886 ASSERT(instr->kind() == kRetAddress); | 836 ASSERT(instr->kind() == kRetAddress); |
887 DeoptRetAddressInstr* ret_address_instr = | 837 DeoptRetAddressInstr* ret_address_instr = |
888 static_cast<DeoptRetAddressInstr*>(instr); | 838 static_cast<DeoptRetAddressInstr*>(instr); |
889 // The following assert may trigger when displaying a backtrace | 839 // The following assert may trigger when displaying a backtrace |
890 // from the simulator. | 840 // from the simulator. |
891 ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id())); | 841 ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id())); |
892 ASSERT(!object_table.IsNull()); | 842 ASSERT(!object_table.IsNull()); |
| 843 Function& function = Function::Handle(); |
| 844 function ^= object_table.At(ret_address_instr->object_table_index()); |
893 ASSERT(code != NULL); | 845 ASSERT(code != NULL); |
894 *code ^= object_table.At(ret_address_instr->object_table_index()); | 846 Compiler::EnsureUnoptimizedCode(Thread::Current(), function); |
| 847 *code ^= function.unoptimized_code(); |
895 ASSERT(!code->IsNull()); | 848 ASSERT(!code->IsNull()); |
896 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), | 849 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), |
897 RawPcDescriptors::kDeopt); | 850 RawPcDescriptors::kDeopt); |
898 ASSERT(res != 0); | 851 ASSERT(res != 0); |
899 return res; | 852 return res; |
900 } | 853 } |
901 | 854 |
902 | 855 |
903 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { | 856 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { |
904 Kind kind = static_cast<Kind>(kind_as_int); | 857 Kind kind = static_cast<Kind>(kind_as_int); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1076 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); | 1029 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); |
1077 } else { | 1030 } else { |
1078 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || | 1031 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || |
1079 (stack_slot_kind == Location::kDoubleStackSlot)); | 1032 (stack_slot_kind == Location::kDoubleStackSlot)); |
1080 ASSERT(loc.kind() == stack_slot_kind); | 1033 ASSERT(loc.kind() == stack_slot_kind); |
1081 return FpuRegisterSource( | 1034 return FpuRegisterSource( |
1082 FpuRegisterSource::kStackSlot, CalculateStackIndex(loc)); | 1035 FpuRegisterSource::kStackSlot, CalculateStackIndex(loc)); |
1083 } | 1036 } |
1084 } | 1037 } |
1085 | 1038 |
1086 void DeoptInfoBuilder::AddReturnAddress(const Code& code, | 1039 void DeoptInfoBuilder::AddReturnAddress(const Function& function, |
1087 intptr_t deopt_id, | 1040 intptr_t deopt_id, |
1088 intptr_t dest_index) { | 1041 intptr_t dest_index) { |
1089 // Check that deopt_id exists. | 1042 const intptr_t object_table_index = FindOrAddObjectInTable(function); |
1090 // TODO(vegorov): verify after deoptimization targets as well. | |
1091 #ifdef DEBUG | |
1092 ASSERT(Isolate::IsDeoptAfter(deopt_id) || | |
1093 (code.GetPcForDeoptId(deopt_id, RawPcDescriptors::kDeopt) != 0)); | |
1094 #endif | |
1095 const intptr_t object_table_index = FindOrAddObjectInTable(code); | |
1096 ASSERT(dest_index == FrameSize()); | 1043 ASSERT(dest_index == FrameSize()); |
1097 instructions_.Add( | 1044 instructions_.Add( |
1098 new(zone()) DeoptRetAddressInstr(object_table_index, deopt_id)); | 1045 new(zone()) DeoptRetAddressInstr(object_table_index, deopt_id)); |
1099 } | 1046 } |
1100 | 1047 |
1101 | 1048 |
1102 void DeoptInfoBuilder::AddPcMarker(const Code& code, | 1049 void DeoptInfoBuilder::AddPcMarker(const Function& function, |
1103 intptr_t dest_index) { | 1050 intptr_t dest_index) { |
1104 intptr_t object_table_index = FindOrAddObjectInTable(code); | 1051 intptr_t object_table_index = FindOrAddObjectInTable(function); |
1105 ASSERT(dest_index == FrameSize()); | 1052 ASSERT(dest_index == FrameSize()); |
1106 instructions_.Add(new(zone()) DeoptPcMarkerInstr(object_table_index)); | 1053 instructions_.Add(new(zone()) DeoptPcMarkerInstr(object_table_index)); |
1107 } | 1054 } |
1108 | 1055 |
1109 | 1056 |
1110 void DeoptInfoBuilder::AddPp(const Code& code, | 1057 void DeoptInfoBuilder::AddPp(const Function& function, |
1111 intptr_t dest_index) { | 1058 intptr_t dest_index) { |
1112 intptr_t object_table_index = FindOrAddObjectInTable(code); | 1059 intptr_t object_table_index = FindOrAddObjectInTable(function); |
1113 ASSERT(dest_index == FrameSize()); | 1060 ASSERT(dest_index == FrameSize()); |
1114 instructions_.Add(new(zone()) DeoptPpInstr(object_table_index)); | 1061 instructions_.Add(new(zone()) DeoptPpInstr(object_table_index)); |
1115 } | 1062 } |
1116 | 1063 |
1117 | 1064 |
1118 void DeoptInfoBuilder::AddCopy(Value* value, | 1065 void DeoptInfoBuilder::AddCopy(Value* value, |
1119 const Location& source_loc, | 1066 const Location& source_loc, |
1120 const intptr_t dest_index) { | 1067 const intptr_t dest_index) { |
1121 DeoptInstr* deopt_instr = NULL; | 1068 DeoptInstr* deopt_instr = NULL; |
1122 if (source_loc.IsConstant()) { | 1069 if (source_loc.IsConstant()) { |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1354 Smi* offset, | 1301 Smi* offset, |
1355 DeoptInfo* info, | 1302 DeoptInfo* info, |
1356 Smi* reason) { | 1303 Smi* reason) { |
1357 intptr_t i = index * kEntrySize; | 1304 intptr_t i = index * kEntrySize; |
1358 *offset ^= table.At(i); | 1305 *offset ^= table.At(i); |
1359 *info ^= table.At(i + 1); | 1306 *info ^= table.At(i + 1); |
1360 *reason ^= table.At(i + 2); | 1307 *reason ^= table.At(i + 2); |
1361 } | 1308 } |
1362 | 1309 |
1363 } // namespace dart | 1310 } // namespace dart |
OLD | NEW |