| 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/compiler.h" |
| 10 #include "vm/intermediate_language.h" | 10 #include "vm/intermediate_language.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 | 59 |
| 60 // Do not include incoming arguments if there are optional arguments | 60 // Do not include incoming arguments if there are optional arguments |
| 61 // (they are copied into local space at method entry). | 61 // (they are copied into local space at method entry). |
| 62 num_args_ = | 62 num_args_ = |
| 63 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 63 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 64 | 64 |
| 65 // The fixed size section of the (fake) Dart frame called via a stub by the | 65 // The fixed size section of the (fake) Dart frame called via a stub by the |
| 66 // optimized function contains FP, PP (ARM and MIPS only), PC-marker and | 66 // optimized function contains FP, PP (ARM and MIPS only), PC-marker and |
| 67 // return-address. This section is copied as well, so that its contained | 67 // return-address. This section is copied as well, so that its contained |
| 68 // values can be updated before returning to the deoptimized function. | 68 // values can be updated before returning to the deoptimized function. |
| 69 // Note: on DBC stack grows upwards unlike on all other architectures. |
| 69 source_frame_size_ = | 70 source_frame_size_ = |
| 70 + kDartFrameFixedSize // For saved values below sp. | 71 + kDartFrameFixedSize // For saved values below sp. |
| 72 #if !defined(TARGET_ARCH_DBC) |
| 71 + ((frame->fp() - frame->sp()) / kWordSize) // For frame size incl. sp. | 73 + ((frame->fp() - frame->sp()) / kWordSize) // For frame size incl. sp. |
| 74 #else |
| 75 + ((frame->sp() - frame->fp()) / kWordSize) // For frame size incl. sp. |
| 76 #endif // !defined(TARGET_ARCH_DBC) |
| 72 + 1 // For fp. | 77 + 1 // For fp. |
| 73 + kParamEndSlotFromFp // For saved values above fp. | 78 + kParamEndSlotFromFp // For saved values above fp. |
| 74 + num_args_; // For arguments. | 79 + num_args_; // For arguments. |
| 75 source_frame_ = reinterpret_cast<intptr_t*>( | 80 |
| 76 frame->sp() - (kDartFrameFixedSize * kWordSize)); | 81 source_frame_ = FrameBase(frame); |
| 77 | 82 |
| 78 if (dest_options == kDestIsOriginalFrame) { | 83 if (dest_options == kDestIsOriginalFrame) { |
| 79 // Work from a copy of the source frame. | 84 // Work from a copy of the source frame. |
| 80 intptr_t* original_frame = source_frame_; | 85 intptr_t* original_frame = source_frame_; |
| 81 source_frame_ = new intptr_t[source_frame_size_]; | 86 source_frame_ = new intptr_t[source_frame_size_]; |
| 82 ASSERT(source_frame_ != NULL); | 87 ASSERT(source_frame_ != NULL); |
| 83 for (intptr_t i = 0; i < source_frame_size_; i++) { | 88 for (intptr_t i = 0; i < source_frame_size_; i++) { |
| 84 source_frame_[i] = original_frame[i]; | 89 source_frame_[i] = original_frame[i]; |
| 85 } | 90 } |
| 86 source_frame_is_allocated_ = true; | 91 source_frame_is_allocated_ = true; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 180 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
| 176 if (dest_frame_[i] != 0) { | 181 if (dest_frame_[i] != 0) { |
| 177 visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i])); | 182 visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i])); |
| 178 } | 183 } |
| 179 } | 184 } |
| 180 } | 185 } |
| 181 } | 186 } |
| 182 | 187 |
| 183 | 188 |
| 184 intptr_t DeoptContext::DestStackAdjustment() const { | 189 intptr_t DeoptContext::DestStackAdjustment() const { |
| 185 return (dest_frame_size_ | 190 return dest_frame_size_ |
| 186 - kDartFrameFixedSize | 191 - kDartFrameFixedSize |
| 187 - num_args_ | 192 - num_args_ |
| 188 - kParamEndSlotFromFp | 193 #if !defined(TARGET_ARCH_DBC) |
| 189 - 1); // For fp. | 194 - 1 // For fp. |
| 195 #endif |
| 196 - kParamEndSlotFromFp; |
| 190 } | 197 } |
| 191 | 198 |
| 192 | 199 |
| 193 intptr_t DeoptContext::GetSourceFp() const { | 200 intptr_t DeoptContext::GetSourceFp() const { |
| 201 #if !defined(TARGET_ARCH_DBC) |
| 194 return source_frame_[source_frame_size_ - 1 - num_args_ - | 202 return source_frame_[source_frame_size_ - 1 - num_args_ - |
| 195 kParamEndSlotFromFp]; | 203 kParamEndSlotFromFp]; |
| 204 #else |
| 205 return source_frame_[num_args_ + kDartFrameFixedSize + |
| 206 kSavedCallerFpSlotFromFp]; |
| 207 #endif |
| 196 } | 208 } |
| 197 | 209 |
| 198 | 210 |
| 199 intptr_t DeoptContext::GetSourcePp() const { | 211 intptr_t DeoptContext::GetSourcePp() const { |
| 212 #if !defined(TARGET_ARCH_DBC) |
| 200 return source_frame_[source_frame_size_ - 1 - num_args_ - | 213 return source_frame_[source_frame_size_ - 1 - num_args_ - |
| 201 kParamEndSlotFromFp + | 214 kParamEndSlotFromFp + |
| 202 StackFrame::SavedCallerPpSlotFromFp()]; | 215 StackFrame::SavedCallerPpSlotFromFp()]; |
| 216 #else |
| 217 UNREACHABLE(); |
| 218 return 0; |
| 219 #endif |
| 203 } | 220 } |
| 204 | 221 |
| 205 | 222 |
| 206 intptr_t DeoptContext::GetSourcePc() const { | 223 intptr_t DeoptContext::GetSourcePc() const { |
| 224 #if !defined(TARGET_ARCH_DBC) |
| 207 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; | 225 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; |
| 226 #else |
| 227 return source_frame_[num_args_ + kDartFrameFixedSize + |
| 228 kSavedCallerPcSlotFromFp]; |
| 229 #endif |
| 208 } | 230 } |
| 209 | 231 |
| 210 | 232 |
| 211 intptr_t DeoptContext::GetCallerFp() const { | 233 intptr_t DeoptContext::GetCallerFp() const { |
| 212 return caller_fp_; | 234 return caller_fp_; |
| 213 } | 235 } |
| 214 | 236 |
| 215 | 237 |
| 216 void DeoptContext::SetCallerFp(intptr_t caller_fp) { | 238 void DeoptContext::SetCallerFp(intptr_t caller_fp) { |
| 217 caller_fp_ = caller_fp; | 239 caller_fp_ = caller_fp; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 intptr_t* to_addr = GetDestFrameAddressAt(to_index); | 320 intptr_t* to_addr = GetDestFrameAddressAt(to_index); |
| 299 DeoptInstr* instr = deopt_instructions[from_index]; | 321 DeoptInstr* instr = deopt_instructions[from_index]; |
| 300 if (!objects_only || IsObjectInstruction(instr->kind())) { | 322 if (!objects_only || IsObjectInstruction(instr->kind())) { |
| 301 instr->Execute(this, to_addr); | 323 instr->Execute(this, to_addr); |
| 302 } else { | 324 } else { |
| 303 *reinterpret_cast<RawObject**>(to_addr) = Object::null(); | 325 *reinterpret_cast<RawObject**>(to_addr) = Object::null(); |
| 304 } | 326 } |
| 305 } | 327 } |
| 306 | 328 |
| 307 if (FLAG_trace_deoptimization_verbose) { | 329 if (FLAG_trace_deoptimization_verbose) { |
| 308 intptr_t* start = dest_frame_; | |
| 309 for (intptr_t i = 0; i < frame_size; i++) { | 330 for (intptr_t i = 0; i < frame_size; i++) { |
| 310 OS::PrintErr("*%" Pd ". [0x%" Px "] 0x%" Px " [%s]\n", | 331 intptr_t* to_addr = GetDestFrameAddressAt(i); |
| 332 OS::PrintErr("*%" Pd ". [%p] 0x%" Px " [%s]\n", |
| 311 i, | 333 i, |
| 312 reinterpret_cast<uword>(&start[i]), | 334 to_addr, |
| 313 start[i], | 335 *to_addr, |
| 314 deopt_instructions[i + (len - frame_size)]->ToCString()); | 336 deopt_instructions[i + (len - frame_size)]->ToCString()); |
| 315 } | 337 } |
| 316 } | 338 } |
| 317 } | 339 } |
| 318 | 340 |
| 319 | 341 |
| 320 static void FillDeferredSlots(DeoptContext* deopt_context, | 342 static void FillDeferredSlots(DeoptContext* deopt_context, |
| 321 DeferredSlot** slot_list) { | 343 DeferredSlot** slot_list) { |
| 322 DeferredSlot* slot = *slot_list; | 344 DeferredSlot* slot = *slot_list; |
| 323 *slot_list = NULL; | 345 *slot_list = NULL; |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 | 675 |
| 654 virtual const char* ArgumentsToCString() const { | 676 virtual const char* ArgumentsToCString() const { |
| 655 return Thread::Current()->zone()->PrintToString( | 677 return Thread::Current()->zone()->PrintToString( |
| 656 "%" Pd "", object_table_index_); | 678 "%" Pd "", object_table_index_); |
| 657 } | 679 } |
| 658 | 680 |
| 659 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 681 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 660 Function& function = Function::Handle(deopt_context->zone()); | 682 Function& function = Function::Handle(deopt_context->zone()); |
| 661 function ^= deopt_context->ObjectAt(object_table_index_); | 683 function ^= deopt_context->ObjectAt(object_table_index_); |
| 662 if (function.IsNull()) { | 684 if (function.IsNull()) { |
| 663 // There are no deoptimization stubs on DBC. | |
| 664 #if !defined(TARGET_ARCH_DBC) | |
| 665 *reinterpret_cast<RawObject**>(dest_addr) = deopt_context->is_lazy_deopt() | 685 *reinterpret_cast<RawObject**>(dest_addr) = deopt_context->is_lazy_deopt() |
| 666 ? StubCode::DeoptimizeLazy_entry()->code() | 686 ? StubCode::DeoptimizeLazy_entry()->code() |
| 667 : StubCode::Deoptimize_entry()->code(); | 687 : StubCode::Deoptimize_entry()->code(); |
| 668 #endif | |
| 669 return; | 688 return; |
| 670 } | 689 } |
| 671 | 690 |
| 672 #if !defined(TARGET_ARCH_DBC) | 691 #if !defined(TARGET_ARCH_DBC) |
| 673 // We don't always have the Code object for the frame's corresponding | 692 // We don't always have the Code object for the frame's corresponding |
| 674 // unoptimized code as it may have been collected. Use a stub as the pc | 693 // unoptimized code as it may have been collected. Use a stub as the pc |
| 675 // marker until we can recreate that Code object during deferred | 694 // marker until we can recreate that Code object during deferred |
| 676 // materialization to maintain the invariant that Dart frames always have | 695 // materialization to maintain the invariant that Dart frames always have |
| 677 // a pc marker. | 696 // a pc marker. |
| 678 *reinterpret_cast<RawObject**>(dest_addr) = | 697 *reinterpret_cast<RawObject**>(dest_addr) = |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 class DeoptCallerFpInstr : public DeoptInstr { | 741 class DeoptCallerFpInstr : public DeoptInstr { |
| 723 public: | 742 public: |
| 724 DeoptCallerFpInstr() {} | 743 DeoptCallerFpInstr() {} |
| 725 | 744 |
| 726 virtual intptr_t source_index() const { return 0; } | 745 virtual intptr_t source_index() const { return 0; } |
| 727 virtual DeoptInstr::Kind kind() const { return kCallerFp; } | 746 virtual DeoptInstr::Kind kind() const { return kCallerFp; } |
| 728 | 747 |
| 729 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 748 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 730 *dest_addr = deopt_context->GetCallerFp(); | 749 *dest_addr = deopt_context->GetCallerFp(); |
| 731 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>( | 750 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>( |
| 732 dest_addr - (kSavedCallerFpSlotFromFp * kWordSize))); | 751 dest_addr - kSavedCallerFpSlotFromFp)); |
| 733 } | 752 } |
| 734 | 753 |
| 735 private: | 754 private: |
| 736 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | 755 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); |
| 737 }; | 756 }; |
| 738 | 757 |
| 739 | 758 |
| 740 // Deoptimization instruction copying the caller saved PP from optimized frame. | 759 // Deoptimization instruction copying the caller saved PP from optimized frame. |
| 741 class DeoptCallerPpInstr : public DeoptInstr { | 760 class DeoptCallerPpInstr : public DeoptInstr { |
| 742 public: | 761 public: |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1319 Smi* offset, | 1338 Smi* offset, |
| 1320 TypedData* info, | 1339 TypedData* info, |
| 1321 Smi* reason) { | 1340 Smi* reason) { |
| 1322 intptr_t i = index * kEntrySize; | 1341 intptr_t i = index * kEntrySize; |
| 1323 *offset ^= table.At(i); | 1342 *offset ^= table.At(i); |
| 1324 *info ^= table.At(i + 1); | 1343 *info ^= table.At(i + 1); |
| 1325 *reason ^= table.At(i + 2); | 1344 *reason ^= table.At(i + 2); |
| 1326 } | 1345 } |
| 1327 | 1346 |
| 1328 } // namespace dart | 1347 } // namespace dart |
| OLD | NEW |