| 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/disassembler.h" | 10 #include "vm/disassembler.h" |
| 11 #include "vm/intermediate_language.h" | 11 #include "vm/intermediate_language.h" |
| 12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
| 13 #include "vm/parser.h" | 13 #include "vm/parser.h" |
| 14 #include "vm/stack_frame.h" | 14 #include "vm/stack_frame.h" |
| 15 #include "vm/thread.h" | 15 #include "vm/thread.h" |
| 16 #include "vm/timeline.h" | 16 #include "vm/timeline.h" |
| 17 | 17 |
| 18 namespace dart { | 18 namespace dart { |
| 19 | 19 |
| 20 DEFINE_FLAG(bool, compress_deopt_info, true, | 20 DEFINE_FLAG(bool, |
| 21 compress_deopt_info, |
| 22 true, |
| 21 "Compress the size of the deoptimization info for optimized code."); | 23 "Compress the size of the deoptimization info for optimized code."); |
| 22 DECLARE_FLAG(bool, trace_deoptimization); | 24 DECLARE_FLAG(bool, trace_deoptimization); |
| 23 DECLARE_FLAG(bool, trace_deoptimization_verbose); | 25 DECLARE_FLAG(bool, trace_deoptimization_verbose); |
| 24 | 26 |
| 25 | 27 |
| 26 DeoptContext::DeoptContext(const StackFrame* frame, | 28 DeoptContext::DeoptContext(const StackFrame* frame, |
| 27 const Code& code, | 29 const Code& code, |
| 28 DestFrameOptions dest_options, | 30 DestFrameOptions dest_options, |
| 29 fpu_register_t* fpu_registers, | 31 fpu_register_t* fpu_registers, |
| 30 intptr_t* cpu_registers, | 32 intptr_t* cpu_registers, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 ASSERT(!deopt_info.IsNull()); | 65 ASSERT(!deopt_info.IsNull()); |
| 64 deopt_info_ = deopt_info.raw(); | 66 deopt_info_ = deopt_info.raw(); |
| 65 | 67 |
| 66 const Function& function = Function::Handle(code.function()); | 68 const Function& function = Function::Handle(code.function()); |
| 67 | 69 |
| 68 // Do not include incoming arguments if there are optional arguments | 70 // Do not include incoming arguments if there are optional arguments |
| 69 // (they are copied into local space at method entry). | 71 // (they are copied into local space at method entry). |
| 70 num_args_ = | 72 num_args_ = |
| 71 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 73 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 72 | 74 |
| 73 // The fixed size section of the (fake) Dart frame called via a stub by the | 75 // The fixed size section of the (fake) Dart frame called via a stub by the |
| 74 // optimized function contains FP, PP (ARM and MIPS only), PC-marker and | 76 // optimized function contains FP, PP (ARM and MIPS only), PC-marker and |
| 75 // return-address. This section is copied as well, so that its contained | 77 // return-address. This section is copied as well, so that its contained |
| 76 // values can be updated before returning to the deoptimized function. | 78 // values can be updated before returning to the deoptimized function. |
| 77 // Note: on DBC stack grows upwards unlike on all other architectures. | 79 // Note: on DBC stack grows upwards unlike on all other architectures. |
| 78 #if defined(TARGET_ARCH_DBC) | 80 #if defined(TARGET_ARCH_DBC) |
| 79 ASSERT(frame->sp() >= frame->fp()); | 81 ASSERT(frame->sp() >= frame->fp()); |
| 80 const intptr_t frame_size = (frame->sp() - frame->fp()) / kWordSize; | 82 const intptr_t frame_size = (frame->sp() - frame->fp()) / kWordSize; |
| 81 #else | 83 #else |
| 82 ASSERT(frame->fp() >= frame->sp()); | 84 ASSERT(frame->fp() >= frame->sp()); |
| 83 const intptr_t frame_size = (frame->fp() - frame->sp()) / kWordSize; | 85 const intptr_t frame_size = (frame->fp() - frame->sp()) / kWordSize; |
| 84 #endif | 86 #endif |
| 85 | 87 |
| 86 source_frame_size_ = | 88 source_frame_size_ = +kDartFrameFixedSize // For saved values below sp. |
| 87 + kDartFrameFixedSize // For saved values below sp. | 89 + frame_size // For frame size incl. sp. |
| 88 + frame_size // For frame size incl. sp. | 90 + 1 // For fp. |
| 89 + 1 // For fp. | 91 + kParamEndSlotFromFp // For saved values above fp. |
| 90 + kParamEndSlotFromFp // For saved values above fp. | 92 + num_args_; // For arguments. |
| 91 + num_args_; // For arguments. | |
| 92 | 93 |
| 93 source_frame_ = FrameBase(frame); | 94 source_frame_ = FrameBase(frame); |
| 94 | 95 |
| 95 if (dest_options == kDestIsOriginalFrame) { | 96 if (dest_options == kDestIsOriginalFrame) { |
| 96 // Work from a copy of the source frame. | 97 // Work from a copy of the source frame. |
| 97 intptr_t* original_frame = source_frame_; | 98 intptr_t* original_frame = source_frame_; |
| 98 source_frame_ = new intptr_t[source_frame_size_]; | 99 source_frame_ = new intptr_t[source_frame_size_]; |
| 99 ASSERT(source_frame_ != NULL); | 100 ASSERT(source_frame_ != NULL); |
| 100 for (intptr_t i = 0; i < source_frame_size_; i++) { | 101 for (intptr_t i = 0; i < source_frame_size_; i++) { |
| 101 source_frame_[i] = original_frame[i]; | 102 source_frame_[i] = original_frame[i]; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 118 if (dest_options != kDestIsAllocated) { | 119 if (dest_options != kDestIsAllocated) { |
| 119 // kDestIsAllocated is used by the debugger to generate a stack trace | 120 // kDestIsAllocated is used by the debugger to generate a stack trace |
| 120 // and does not signal a real deopt. | 121 // and does not signal a real deopt. |
| 121 deopt_start_micros_ = OS::GetCurrentMonotonicMicros(); | 122 deopt_start_micros_ = OS::GetCurrentMonotonicMicros(); |
| 122 } | 123 } |
| 123 | 124 |
| 124 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | 125 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| 125 THR_Print( | 126 THR_Print( |
| 126 "Deoptimizing (reason %d '%s') at " | 127 "Deoptimizing (reason %d '%s') at " |
| 127 "pc=%" Pp " fp=%" Pp " '%s' (count %d)\n", | 128 "pc=%" Pp " fp=%" Pp " '%s' (count %d)\n", |
| 128 deopt_reason(), | 129 deopt_reason(), DeoptReasonToCString(deopt_reason()), frame->pc(), |
| 129 DeoptReasonToCString(deopt_reason()), | 130 frame->fp(), function.ToFullyQualifiedCString(), |
| 130 frame->pc(), | |
| 131 frame->fp(), | |
| 132 function.ToFullyQualifiedCString(), | |
| 133 function.deoptimization_counter()); | 131 function.deoptimization_counter()); |
| 134 } | 132 } |
| 135 } | 133 } |
| 136 | 134 |
| 137 | 135 |
| 138 DeoptContext::~DeoptContext() { | 136 DeoptContext::~DeoptContext() { |
| 139 // Delete memory for source frame and registers. | 137 // Delete memory for source frame and registers. |
| 140 if (source_frame_is_allocated_) { | 138 if (source_frame_is_allocated_) { |
| 141 delete[] source_frame_; | 139 delete[] source_frame_; |
| 142 } | 140 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 165 // Allocate all Dart objects needed before calling StartEvent, | 163 // Allocate all Dart objects needed before calling StartEvent, |
| 166 // which blocks safe points until Complete is called. | 164 // which blocks safe points until Complete is called. |
| 167 const Code& code = Code::Handle(zone(), code_); | 165 const Code& code = Code::Handle(zone(), code_); |
| 168 const Function& function = Function::Handle(zone(), code.function()); | 166 const Function& function = Function::Handle(zone(), code.function()); |
| 169 const String& function_name = | 167 const String& function_name = |
| 170 String::Handle(zone(), function.QualifiedScrubbedName()); | 168 String::Handle(zone(), function.QualifiedScrubbedName()); |
| 171 const char* reason = DeoptReasonToCString(deopt_reason()); | 169 const char* reason = DeoptReasonToCString(deopt_reason()); |
| 172 const int counter = function.deoptimization_counter(); | 170 const int counter = function.deoptimization_counter(); |
| 173 TimelineEvent* timeline_event = compiler_stream->StartEvent(); | 171 TimelineEvent* timeline_event = compiler_stream->StartEvent(); |
| 174 if (timeline_event != NULL) { | 172 if (timeline_event != NULL) { |
| 175 timeline_event->Duration("Deoptimize", | 173 timeline_event->Duration("Deoptimize", deopt_start_micros_, |
| 176 deopt_start_micros_, | |
| 177 OS::GetCurrentMonotonicMicros()); | 174 OS::GetCurrentMonotonicMicros()); |
| 178 timeline_event->SetNumArguments(3); | 175 timeline_event->SetNumArguments(3); |
| 179 timeline_event->CopyArgument(0, "function", function_name.ToCString()); | 176 timeline_event->CopyArgument(0, "function", function_name.ToCString()); |
| 180 timeline_event->CopyArgument(1, "reason", reason); | 177 timeline_event->CopyArgument(1, "reason", reason); |
| 181 timeline_event->FormatArgument(2, "deoptimizationCount", "%d", counter); | 178 timeline_event->FormatArgument(2, "deoptimizationCount", "%d", counter); |
| 182 timeline_event->Complete(); | 179 timeline_event->Complete(); |
| 183 } | 180 } |
| 184 } | 181 } |
| 185 } | 182 } |
| 186 #endif // !PRODUCT | 183 #endif // !PRODUCT |
| 187 } | 184 } |
| 188 | 185 |
| 189 | 186 |
| 190 void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 187 void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 191 visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_pool_)); | 188 visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_pool_)); |
| 192 visitor->VisitPointer(reinterpret_cast<RawObject**>(&deopt_info_)); | 189 visitor->VisitPointer(reinterpret_cast<RawObject**>(&deopt_info_)); |
| 193 | 190 |
| 194 // Visit any object pointers on the destination stack. | 191 // Visit any object pointers on the destination stack. |
| 195 if (dest_frame_is_allocated_) { | 192 if (dest_frame_is_allocated_) { |
| 196 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 193 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
| 197 if (dest_frame_[i] != 0) { | 194 if (dest_frame_[i] != 0) { |
| 198 visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i])); | 195 visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i])); |
| 199 } | 196 } |
| 200 } | 197 } |
| 201 } | 198 } |
| 202 } | 199 } |
| 203 | 200 |
| 204 | 201 |
| 205 intptr_t DeoptContext::DestStackAdjustment() const { | 202 intptr_t DeoptContext::DestStackAdjustment() const { |
| 206 return dest_frame_size_ | 203 return dest_frame_size_ - kDartFrameFixedSize - num_args_ |
| 207 - kDartFrameFixedSize | |
| 208 - num_args_ | |
| 209 #if !defined(TARGET_ARCH_DBC) | 204 #if !defined(TARGET_ARCH_DBC) |
| 210 - 1 // For fp. | 205 - 1 // For fp. |
| 211 #endif | 206 #endif |
| 212 - kParamEndSlotFromFp; | 207 - kParamEndSlotFromFp; |
| 213 } | 208 } |
| 214 | 209 |
| 215 | 210 |
| 216 intptr_t DeoptContext::GetSourceFp() const { | 211 intptr_t DeoptContext::GetSourceFp() const { |
| 217 #if !defined(TARGET_ARCH_DBC) | 212 #if !defined(TARGET_ARCH_DBC) |
| 218 return source_frame_[source_frame_size_ - 1 - num_args_ - | 213 return source_frame_[source_frame_size_ - 1 - num_args_ - |
| 219 kParamEndSlotFromFp]; | 214 kParamEndSlotFromFp]; |
| 220 #else | 215 #else |
| 221 return source_frame_[num_args_ + kDartFrameFixedSize + | 216 return source_frame_[num_args_ + kDartFrameFixedSize + |
| 222 kSavedCallerFpSlotFromFp]; | 217 kSavedCallerFpSlotFromFp]; |
| 223 #endif | 218 #endif |
| 224 } | 219 } |
| 225 | 220 |
| 226 | 221 |
| 227 intptr_t DeoptContext::GetSourcePp() const { | 222 intptr_t DeoptContext::GetSourcePp() const { |
| 228 #if !defined(TARGET_ARCH_DBC) | 223 #if !defined(TARGET_ARCH_DBC) |
| 229 return source_frame_[source_frame_size_ - 1 - num_args_ - | 224 return source_frame_[source_frame_size_ - 1 - num_args_ - |
| 230 kParamEndSlotFromFp + | 225 kParamEndSlotFromFp + |
| 231 StackFrame::SavedCallerPpSlotFromFp()]; | 226 StackFrame::SavedCallerPpSlotFromFp()]; |
| 232 #else | 227 #else |
| 233 UNREACHABLE(); | 228 UNREACHABLE(); |
| 234 return 0; | 229 return 0; |
| 235 #endif | 230 #endif |
| 236 } | 231 } |
| 237 | 232 |
| 238 | 233 |
| 239 intptr_t DeoptContext::GetSourcePc() const { | 234 intptr_t DeoptContext::GetSourcePc() const { |
| 240 #if !defined(TARGET_ARCH_DBC) | 235 #if !defined(TARGET_ARCH_DBC) |
| 241 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; | 236 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; |
| 242 #else | 237 #else |
| 243 return source_frame_[num_args_ + kDartFrameFixedSize + | 238 return source_frame_[num_args_ + kDartFrameFixedSize + |
| 244 kSavedCallerPcSlotFromFp]; | 239 kSavedCallerPcSlotFromFp]; |
| 245 #endif | 240 #endif |
| 246 } | 241 } |
| 247 | 242 |
| 248 | 243 |
| 249 intptr_t DeoptContext::GetCallerFp() const { | 244 intptr_t DeoptContext::GetCallerFp() const { |
| 250 return caller_fp_; | 245 return caller_fp_; |
| 251 } | 246 } |
| 252 | 247 |
| 253 | 248 |
| 254 void DeoptContext::SetCallerFp(intptr_t caller_fp) { | 249 void DeoptContext::SetCallerFp(intptr_t caller_fp) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 // objects until the frame is fully reconstructed and it is safe to perform | 307 // objects until the frame is fully reconstructed and it is safe to perform |
| 313 // GC. | 308 // GC. |
| 314 // Arguments (class of the instance to allocate and field-value pairs) are | 309 // Arguments (class of the instance to allocate and field-value pairs) are |
| 315 // described as part of the expression stack for the bottom-most deoptimized | 310 // described as part of the expression stack for the bottom-most deoptimized |
| 316 // frame. They will be used during materialization and removed from the stack | 311 // frame. They will be used during materialization and removed from the stack |
| 317 // right before control switches to the unoptimized code. | 312 // right before control switches to the unoptimized code. |
| 318 const intptr_t num_materializations = | 313 const intptr_t num_materializations = |
| 319 DeoptInfo::NumMaterializations(deopt_instructions); | 314 DeoptInfo::NumMaterializations(deopt_instructions); |
| 320 PrepareForDeferredMaterialization(num_materializations); | 315 PrepareForDeferredMaterialization(num_materializations); |
| 321 for (intptr_t from_index = 0, to_index = kDartFrameFixedSize; | 316 for (intptr_t from_index = 0, to_index = kDartFrameFixedSize; |
| 322 from_index < num_materializations; | 317 from_index < num_materializations; from_index++) { |
| 323 from_index++) { | |
| 324 const intptr_t field_count = | 318 const intptr_t field_count = |
| 325 DeoptInstr::GetFieldCount(deopt_instructions[from_index]); | 319 DeoptInstr::GetFieldCount(deopt_instructions[from_index]); |
| 326 intptr_t* args = GetDestFrameAddressAt(to_index); | 320 intptr_t* args = GetDestFrameAddressAt(to_index); |
| 327 DeferredObject* obj = new DeferredObject(field_count, args); | 321 DeferredObject* obj = new DeferredObject(field_count, args); |
| 328 SetDeferredObjectAt(from_index, obj); | 322 SetDeferredObjectAt(from_index, obj); |
| 329 to_index += obj->ArgumentCount(); | 323 to_index += obj->ArgumentCount(); |
| 330 } | 324 } |
| 331 | 325 |
| 332 // Populate stack frames. | 326 // Populate stack frames. |
| 333 for (intptr_t to_index = frame_size - 1, from_index = len - 1; | 327 for (intptr_t to_index = frame_size - 1, from_index = len - 1; to_index >= 0; |
| 334 to_index >= 0; | |
| 335 to_index--, from_index--) { | 328 to_index--, from_index--) { |
| 336 intptr_t* to_addr = GetDestFrameAddressAt(to_index); | 329 intptr_t* to_addr = GetDestFrameAddressAt(to_index); |
| 337 DeoptInstr* instr = deopt_instructions[from_index]; | 330 DeoptInstr* instr = deopt_instructions[from_index]; |
| 338 if (!objects_only || IsObjectInstruction(instr->kind())) { | 331 if (!objects_only || IsObjectInstruction(instr->kind())) { |
| 339 instr->Execute(this, to_addr); | 332 instr->Execute(this, to_addr); |
| 340 } else { | 333 } else { |
| 341 *reinterpret_cast<RawObject**>(to_addr) = Object::null(); | 334 *reinterpret_cast<RawObject**>(to_addr) = Object::null(); |
| 342 } | 335 } |
| 343 } | 336 } |
| 344 | 337 |
| 345 if (FLAG_trace_deoptimization_verbose) { | 338 if (FLAG_trace_deoptimization_verbose) { |
| 346 for (intptr_t i = 0; i < frame_size; i++) { | 339 for (intptr_t i = 0; i < frame_size; i++) { |
| 347 intptr_t* to_addr = GetDestFrameAddressAt(i); | 340 intptr_t* to_addr = GetDestFrameAddressAt(i); |
| 348 THR_Print("*%" Pd ". [%p] 0x%" Px " [%s]\n", | 341 THR_Print("*%" Pd ". [%p] 0x%" Px " [%s]\n", i, to_addr, *to_addr, |
| 349 i, | |
| 350 to_addr, | |
| 351 *to_addr, | |
| 352 deopt_instructions[i + (len - frame_size)]->ToCString()); | 342 deopt_instructions[i + (len - frame_size)]->ToCString()); |
| 353 } | 343 } |
| 354 } | 344 } |
| 355 } | 345 } |
| 356 | 346 |
| 357 | 347 |
| 358 static void FillDeferredSlots(DeoptContext* deopt_context, | 348 static void FillDeferredSlots(DeoptContext* deopt_context, |
| 359 DeferredSlot** slot_list) { | 349 DeferredSlot** slot_list) { |
| 360 DeferredSlot* slot = *slot_list; | 350 DeferredSlot* slot = *slot_list; |
| 361 *slot_list = NULL; | 351 *slot_list = NULL; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 ASSERT(top_frame != NULL); | 385 ASSERT(top_frame != NULL); |
| 396 const Code& code = Code::Handle(top_frame->LookupDartCode()); | 386 const Code& code = Code::Handle(top_frame->LookupDartCode()); |
| 397 const Function& top_function = Function::Handle(code.function()); | 387 const Function& top_function = Function::Handle(code.function()); |
| 398 const Script& script = Script::Handle(top_function.script()); | 388 const Script& script = Script::Handle(top_function.script()); |
| 399 const TokenPosition token_pos = code.GetTokenIndexOfPC(top_frame->pc()); | 389 const TokenPosition token_pos = code.GetTokenIndexOfPC(top_frame->pc()); |
| 400 intptr_t line, column; | 390 intptr_t line, column; |
| 401 script.GetTokenLocation(token_pos, &line, &column); | 391 script.GetTokenLocation(token_pos, &line, &column); |
| 402 String& line_string = String::Handle(script.GetLine(line)); | 392 String& line_string = String::Handle(script.GetLine(line)); |
| 403 THR_Print(" Function: %s\n", top_function.ToFullyQualifiedCString()); | 393 THR_Print(" Function: %s\n", top_function.ToFullyQualifiedCString()); |
| 404 char line_buffer[80]; | 394 char line_buffer[80]; |
| 405 OS::SNPrint(line_buffer, sizeof(line_buffer), " Line %" Pd ": '%s'", | 395 OS::SNPrint(line_buffer, sizeof(line_buffer), " Line %" Pd ": '%s'", line, |
| 406 line, line_string.ToCString()); | 396 line_string.ToCString()); |
| 407 THR_Print("%s\n", line_buffer); | 397 THR_Print("%s\n", line_buffer); |
| 408 THR_Print(" Deopt args: %" Pd "\n", deopt_arg_count); | 398 THR_Print(" Deopt args: %" Pd "\n", deopt_arg_count); |
| 409 } | 399 } |
| 410 | 400 |
| 411 return deopt_arg_count; | 401 return deopt_arg_count; |
| 412 } | 402 } |
| 413 | 403 |
| 414 | 404 |
| 415 RawArray* DeoptContext::DestFrameAsArray() { | 405 RawArray* DeoptContext::DestFrameAsArray() { |
| 416 ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_); | 406 ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_); |
| 417 const Array& dest_array = | 407 const Array& dest_array = Array::Handle(zone(), Array::New(dest_frame_size_)); |
| 418 Array::Handle(zone(), Array::New(dest_frame_size_)); | |
| 419 PassiveObject& obj = PassiveObject::Handle(zone()); | 408 PassiveObject& obj = PassiveObject::Handle(zone()); |
| 420 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 409 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
| 421 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); | 410 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); |
| 422 dest_array.SetAt(i, obj); | 411 dest_array.SetAt(i, obj); |
| 423 } | 412 } |
| 424 return dest_array.raw(); | 413 return dest_array.raw(); |
| 425 } | 414 } |
| 426 | 415 |
| 427 | 416 |
| 428 // Deoptimization instruction creating return address using function and | 417 // Deoptimization instruction creating return address using function and |
| 429 // deopt-id stored at 'object_table_index'. | 418 // deopt-id stored at 'object_table_index'. |
| 430 class DeoptRetAddressInstr : public DeoptInstr { | 419 class DeoptRetAddressInstr : public DeoptInstr { |
| 431 public: | 420 public: |
| 432 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) | 421 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) |
| 433 : object_table_index_(object_table_index), deopt_id_(deopt_id) { | 422 : object_table_index_(object_table_index), deopt_id_(deopt_id) { |
| 434 ASSERT(object_table_index >= 0); | 423 ASSERT(object_table_index >= 0); |
| 435 ASSERT(deopt_id >= 0); | 424 ASSERT(deopt_id >= 0); |
| 436 } | 425 } |
| 437 | 426 |
| 438 explicit DeoptRetAddressInstr(intptr_t source_index) | 427 explicit DeoptRetAddressInstr(intptr_t source_index) |
| 439 : object_table_index_(ObjectTableIndex::decode(source_index)), | 428 : object_table_index_(ObjectTableIndex::decode(source_index)), |
| 440 deopt_id_(DeoptId::decode(source_index)) { | 429 deopt_id_(DeoptId::decode(source_index)) {} |
| 441 } | |
| 442 | 430 |
| 443 virtual intptr_t source_index() const { | 431 virtual intptr_t source_index() const { |
| 444 return ObjectTableIndex::encode(object_table_index_) | | 432 return ObjectTableIndex::encode(object_table_index_) | |
| 445 DeoptId::encode(deopt_id_); | 433 DeoptId::encode(deopt_id_); |
| 446 } | 434 } |
| 447 | 435 |
| 448 virtual DeoptInstr::Kind kind() const { return kRetAddress; } | 436 virtual DeoptInstr::Kind kind() const { return kRetAddress; } |
| 449 | 437 |
| 450 virtual const char* ArgumentsToCString() const { | 438 virtual const char* ArgumentsToCString() const { |
| 451 return Thread::Current()->zone()->PrintToString( | 439 return Thread::Current()->zone()->PrintToString( |
| 452 "%" Pd ", %" Pd "", object_table_index_, deopt_id_); | 440 "%" Pd ", %" Pd "", object_table_index_, deopt_id_); |
| 453 } | 441 } |
| 454 | 442 |
| 455 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 443 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 456 *dest_addr = Smi::RawValue(0); | 444 *dest_addr = Smi::RawValue(0); |
| 457 deopt_context->DeferRetAddrMaterialization( | 445 deopt_context->DeferRetAddrMaterialization(object_table_index_, deopt_id_, |
| 458 object_table_index_, deopt_id_, dest_addr); | 446 dest_addr); |
| 459 } | 447 } |
| 460 | 448 |
| 461 intptr_t object_table_index() const { return object_table_index_; } | 449 intptr_t object_table_index() const { return object_table_index_; } |
| 462 intptr_t deopt_id() const { return deopt_id_; } | 450 intptr_t deopt_id() const { return deopt_id_; } |
| 463 | 451 |
| 464 private: | 452 private: |
| 465 static const intptr_t kFieldWidth = kBitsPerWord / 2; | 453 static const intptr_t kFieldWidth = kBitsPerWord / 2; |
| 466 class ObjectTableIndex : | 454 class ObjectTableIndex : public BitField<intptr_t, intptr_t, 0, kFieldWidth> { |
| 467 public BitField<intptr_t, intptr_t, 0, kFieldWidth> { }; | 455 }; |
| 468 class DeoptId : | 456 class DeoptId |
| 469 public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> { }; | 457 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; |
| 470 | 458 |
| 471 const intptr_t object_table_index_; | 459 const intptr_t object_table_index_; |
| 472 const intptr_t deopt_id_; | 460 const intptr_t deopt_id_; |
| 473 | 461 |
| 474 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddressInstr); | 462 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddressInstr); |
| 475 }; | 463 }; |
| 476 | 464 |
| 477 | 465 |
| 478 // Deoptimization instruction moving a constant stored at 'object_table_index'. | 466 // Deoptimization instruction moving a constant stored at 'object_table_index'. |
| 479 class DeoptConstantInstr : public DeoptInstr { | 467 class DeoptConstantInstr : public DeoptInstr { |
| 480 public: | 468 public: |
| 481 explicit DeoptConstantInstr(intptr_t object_table_index) | 469 explicit DeoptConstantInstr(intptr_t object_table_index) |
| 482 : object_table_index_(object_table_index) { | 470 : object_table_index_(object_table_index) { |
| 483 ASSERT(object_table_index >= 0); | 471 ASSERT(object_table_index >= 0); |
| 484 } | 472 } |
| 485 | 473 |
| 486 virtual intptr_t source_index() const { return object_table_index_; } | 474 virtual intptr_t source_index() const { return object_table_index_; } |
| 487 virtual DeoptInstr::Kind kind() const { return kConstant; } | 475 virtual DeoptInstr::Kind kind() const { return kConstant; } |
| 488 | 476 |
| 489 virtual const char* ArgumentsToCString() const { | 477 virtual const char* ArgumentsToCString() const { |
| 490 return Thread::Current()->zone()->PrintToString( | 478 return Thread::Current()->zone()->PrintToString("%" Pd "", |
| 491 "%" Pd "", object_table_index_); | 479 object_table_index_); |
| 492 } | 480 } |
| 493 | 481 |
| 494 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 482 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 495 const PassiveObject& obj = PassiveObject::Handle( | 483 const PassiveObject& obj = PassiveObject::Handle( |
| 496 deopt_context->zone(), deopt_context->ObjectAt(object_table_index_)); | 484 deopt_context->zone(), deopt_context->ObjectAt(object_table_index_)); |
| 497 *reinterpret_cast<RawObject**>(dest_addr) = obj.raw(); | 485 *reinterpret_cast<RawObject**>(dest_addr) = obj.raw(); |
| 498 } | 486 } |
| 499 | 487 |
| 500 private: | 488 private: |
| 501 const intptr_t object_table_index_; | 489 const intptr_t object_table_index_; |
| 502 | 490 |
| 503 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | 491 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); |
| 504 }; | 492 }; |
| 505 | 493 |
| 506 | 494 |
| 507 // Deoptimization instruction moving value from optimized frame at | 495 // Deoptimization instruction moving value from optimized frame at |
| 508 // 'source_index' to specified slots in the unoptimized frame. | 496 // 'source_index' to specified slots in the unoptimized frame. |
| 509 // 'source_index' represents the slot index of the frame (0 being | 497 // 'source_index' represents the slot index of the frame (0 being |
| 510 // first argument) and accounts for saved return address, frame | 498 // first argument) and accounts for saved return address, frame |
| 511 // pointer, pool pointer and pc marker. | 499 // pointer, pool pointer and pc marker. |
| 512 // Deoptimization instruction moving a CPU register. | 500 // Deoptimization instruction moving a CPU register. |
| 513 class DeoptWordInstr: public DeoptInstr { | 501 class DeoptWordInstr : public DeoptInstr { |
| 514 public: | 502 public: |
| 515 explicit DeoptWordInstr(intptr_t source_index) | 503 explicit DeoptWordInstr(intptr_t source_index) : source_(source_index) {} |
| 516 : source_(source_index) {} | |
| 517 | 504 |
| 518 explicit DeoptWordInstr(const CpuRegisterSource& source) | 505 explicit DeoptWordInstr(const CpuRegisterSource& source) : source_(source) {} |
| 519 : source_(source) {} | |
| 520 | 506 |
| 521 virtual intptr_t source_index() const { return source_.source_index(); } | 507 virtual intptr_t source_index() const { return source_.source_index(); } |
| 522 virtual DeoptInstr::Kind kind() const { return kWord; } | 508 virtual DeoptInstr::Kind kind() const { return kWord; } |
| 523 | 509 |
| 524 virtual const char* ArgumentsToCString() const { | 510 virtual const char* ArgumentsToCString() const { return source_.ToCString(); } |
| 525 return source_.ToCString(); | |
| 526 } | |
| 527 | 511 |
| 528 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 512 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 529 *dest_addr = source_.Value<intptr_t>(deopt_context); | 513 *dest_addr = source_.Value<intptr_t>(deopt_context); |
| 530 } | 514 } |
| 531 | 515 |
| 532 private: | 516 private: |
| 533 const CpuRegisterSource source_; | 517 const CpuRegisterSource source_; |
| 534 | 518 |
| 535 DISALLOW_COPY_AND_ASSIGN(DeoptWordInstr); | 519 DISALLOW_COPY_AND_ASSIGN(DeoptWordInstr); |
| 536 }; | 520 }; |
| 537 | 521 |
| 538 | 522 |
| 539 class DeoptIntegerInstrBase: public DeoptInstr { | 523 class DeoptIntegerInstrBase : public DeoptInstr { |
| 540 public: | 524 public: |
| 541 DeoptIntegerInstrBase() { } | 525 DeoptIntegerInstrBase() {} |
| 542 | 526 |
| 543 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 527 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 544 const int64_t value = GetValue(deopt_context); | 528 const int64_t value = GetValue(deopt_context); |
| 545 if (Smi::IsValid(value)) { | 529 if (Smi::IsValid(value)) { |
| 546 *dest_addr = Smi::RawValue(static_cast<intptr_t>(value)); | 530 *dest_addr = Smi::RawValue(static_cast<intptr_t>(value)); |
| 547 } else { | 531 } else { |
| 548 *dest_addr = Smi::RawValue(0); | 532 *dest_addr = Smi::RawValue(0); |
| 549 deopt_context->DeferMintMaterialization( | 533 deopt_context->DeferMintMaterialization( |
| 550 value, reinterpret_cast<RawMint**>(dest_addr)); | 534 value, reinterpret_cast<RawMint**>(dest_addr)); |
| 551 } | 535 } |
| 552 } | 536 } |
| 553 | 537 |
| 554 virtual int64_t GetValue(DeoptContext* deopt_context) = 0; | 538 virtual int64_t GetValue(DeoptContext* deopt_context) = 0; |
| 555 | 539 |
| 556 private: | 540 private: |
| 557 DISALLOW_COPY_AND_ASSIGN(DeoptIntegerInstrBase); | 541 DISALLOW_COPY_AND_ASSIGN(DeoptIntegerInstrBase); |
| 558 }; | 542 }; |
| 559 | 543 |
| 560 | 544 |
| 561 class DeoptMintPairInstr: public DeoptIntegerInstrBase { | 545 class DeoptMintPairInstr : public DeoptIntegerInstrBase { |
| 562 public: | 546 public: |
| 563 explicit DeoptMintPairInstr(intptr_t source_index) | 547 explicit DeoptMintPairInstr(intptr_t source_index) |
| 564 : DeoptIntegerInstrBase(), | 548 : DeoptIntegerInstrBase(), |
| 565 lo_(LoRegister::decode(source_index)), | 549 lo_(LoRegister::decode(source_index)), |
| 566 hi_(HiRegister::decode(source_index)) { | 550 hi_(HiRegister::decode(source_index)) {} |
| 567 } | |
| 568 | 551 |
| 569 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) | 552 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) |
| 570 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} | 553 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} |
| 571 | 554 |
| 572 virtual intptr_t source_index() const { | 555 virtual intptr_t source_index() const { |
| 573 return LoRegister::encode(lo_.source_index()) | | 556 return LoRegister::encode(lo_.source_index()) | |
| 574 HiRegister::encode(hi_.source_index()); | 557 HiRegister::encode(hi_.source_index()); |
| 575 } | 558 } |
| 576 virtual DeoptInstr::Kind kind() const { return kMintPair; } | 559 virtual DeoptInstr::Kind kind() const { return kMintPair; } |
| 577 | 560 |
| 578 virtual const char* ArgumentsToCString() const { | 561 virtual const char* ArgumentsToCString() const { |
| 579 return Thread::Current()->zone()->PrintToString( | 562 return Thread::Current()->zone()->PrintToString("%s,%s", lo_.ToCString(), |
| 580 "%s,%s", | 563 hi_.ToCString()); |
| 581 lo_.ToCString(), | |
| 582 hi_.ToCString()); | |
| 583 } | 564 } |
| 584 | 565 |
| 585 virtual int64_t GetValue(DeoptContext* deopt_context) { | 566 virtual int64_t GetValue(DeoptContext* deopt_context) { |
| 586 return Utils::LowHighTo64Bits( | 567 return Utils::LowHighTo64Bits(lo_.Value<uint32_t>(deopt_context), |
| 587 lo_.Value<uint32_t>(deopt_context), hi_.Value<int32_t>(deopt_context)); | 568 hi_.Value<int32_t>(deopt_context)); |
| 588 } | 569 } |
| 589 | 570 |
| 590 private: | 571 private: |
| 591 static const intptr_t kFieldWidth = kBitsPerWord / 2; | 572 static const intptr_t kFieldWidth = kBitsPerWord / 2; |
| 592 class LoRegister : public BitField<intptr_t, intptr_t, 0, kFieldWidth> { }; | 573 class LoRegister : public BitField<intptr_t, intptr_t, 0, kFieldWidth> {}; |
| 593 class HiRegister : | 574 class HiRegister |
| 594 public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> { }; | 575 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; |
| 595 | 576 |
| 596 const CpuRegisterSource lo_; | 577 const CpuRegisterSource lo_; |
| 597 const CpuRegisterSource hi_; | 578 const CpuRegisterSource hi_; |
| 598 | 579 |
| 599 DISALLOW_COPY_AND_ASSIGN(DeoptMintPairInstr); | 580 DISALLOW_COPY_AND_ASSIGN(DeoptMintPairInstr); |
| 600 }; | 581 }; |
| 601 | 582 |
| 602 | 583 |
| 603 template<DeoptInstr::Kind K, typename T> | 584 template <DeoptInstr::Kind K, typename T> |
| 604 class DeoptIntInstr : public DeoptIntegerInstrBase { | 585 class DeoptIntInstr : public DeoptIntegerInstrBase { |
| 605 public: | 586 public: |
| 606 explicit DeoptIntInstr(intptr_t source_index) | 587 explicit DeoptIntInstr(intptr_t source_index) |
| 607 : DeoptIntegerInstrBase(), source_(source_index) { | 588 : DeoptIntegerInstrBase(), source_(source_index) {} |
| 608 } | |
| 609 | 589 |
| 610 explicit DeoptIntInstr(const CpuRegisterSource& source) | 590 explicit DeoptIntInstr(const CpuRegisterSource& source) |
| 611 : DeoptIntegerInstrBase(), source_(source) { | 591 : DeoptIntegerInstrBase(), source_(source) {} |
| 612 } | |
| 613 | 592 |
| 614 virtual intptr_t source_index() const { return source_.source_index(); } | 593 virtual intptr_t source_index() const { return source_.source_index(); } |
| 615 virtual DeoptInstr::Kind kind() const { return K; } | 594 virtual DeoptInstr::Kind kind() const { return K; } |
| 616 | 595 |
| 617 virtual const char* ArgumentsToCString() const { | 596 virtual const char* ArgumentsToCString() const { return source_.ToCString(); } |
| 618 return source_.ToCString(); | |
| 619 } | |
| 620 | 597 |
| 621 virtual int64_t GetValue(DeoptContext* deopt_context) { | 598 virtual int64_t GetValue(DeoptContext* deopt_context) { |
| 622 return static_cast<int64_t>(source_.Value<T>(deopt_context)); | 599 return static_cast<int64_t>(source_.Value<T>(deopt_context)); |
| 623 } | 600 } |
| 624 | 601 |
| 625 private: | 602 private: |
| 626 const CpuRegisterSource source_; | 603 const CpuRegisterSource source_; |
| 627 | 604 |
| 628 DISALLOW_COPY_AND_ASSIGN(DeoptIntInstr); | 605 DISALLOW_COPY_AND_ASSIGN(DeoptIntInstr); |
| 629 }; | 606 }; |
| 630 | 607 |
| 631 | 608 |
| 632 typedef DeoptIntInstr<DeoptInstr::kUint32, uint32_t> DeoptUint32Instr; | 609 typedef DeoptIntInstr<DeoptInstr::kUint32, uint32_t> DeoptUint32Instr; |
| 633 typedef DeoptIntInstr<DeoptInstr::kInt32, int32_t> DeoptInt32Instr; | 610 typedef DeoptIntInstr<DeoptInstr::kInt32, int32_t> DeoptInt32Instr; |
| 634 typedef DeoptIntInstr<DeoptInstr::kMint, int64_t> DeoptMintInstr; | 611 typedef DeoptIntInstr<DeoptInstr::kMint, int64_t> DeoptMintInstr; |
| 635 | 612 |
| 636 | 613 |
| 637 template<DeoptInstr::Kind K, | 614 template <DeoptInstr::Kind K, typename Type, typename RawObjectType> |
| 638 typename Type, | 615 class DeoptFpuInstr : public DeoptInstr { |
| 639 typename RawObjectType> | |
| 640 class DeoptFpuInstr: public DeoptInstr { | |
| 641 public: | 616 public: |
| 642 explicit DeoptFpuInstr(intptr_t source_index) | 617 explicit DeoptFpuInstr(intptr_t source_index) : source_(source_index) {} |
| 643 : source_(source_index) {} | |
| 644 | 618 |
| 645 explicit DeoptFpuInstr(const FpuRegisterSource& source) | 619 explicit DeoptFpuInstr(const FpuRegisterSource& source) : source_(source) {} |
| 646 : source_(source) {} | |
| 647 | 620 |
| 648 virtual intptr_t source_index() const { return source_.source_index(); } | 621 virtual intptr_t source_index() const { return source_.source_index(); } |
| 649 virtual DeoptInstr::Kind kind() const { return K; } | 622 virtual DeoptInstr::Kind kind() const { return K; } |
| 650 | 623 |
| 651 virtual const char* ArgumentsToCString() const { | 624 virtual const char* ArgumentsToCString() const { return source_.ToCString(); } |
| 652 return source_.ToCString(); | |
| 653 } | |
| 654 | 625 |
| 655 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 626 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 656 *dest_addr = Smi::RawValue(0); | 627 *dest_addr = Smi::RawValue(0); |
| 657 deopt_context->DeferMaterialization( | 628 deopt_context->DeferMaterialization( |
| 658 source_.Value<Type>(deopt_context), | 629 source_.Value<Type>(deopt_context), |
| 659 reinterpret_cast<RawObjectType**>(dest_addr)); | 630 reinterpret_cast<RawObjectType**>(dest_addr)); |
| 660 } | 631 } |
| 661 | 632 |
| 662 private: | 633 private: |
| 663 const FpuRegisterSource source_; | 634 const FpuRegisterSource source_; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 683 public: | 654 public: |
| 684 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | 655 explicit DeoptPcMarkerInstr(intptr_t object_table_index) |
| 685 : object_table_index_(object_table_index) { | 656 : object_table_index_(object_table_index) { |
| 686 ASSERT(object_table_index >= 0); | 657 ASSERT(object_table_index >= 0); |
| 687 } | 658 } |
| 688 | 659 |
| 689 virtual intptr_t source_index() const { return object_table_index_; } | 660 virtual intptr_t source_index() const { return object_table_index_; } |
| 690 virtual DeoptInstr::Kind kind() const { return kPcMarker; } | 661 virtual DeoptInstr::Kind kind() const { return kPcMarker; } |
| 691 | 662 |
| 692 virtual const char* ArgumentsToCString() const { | 663 virtual const char* ArgumentsToCString() const { |
| 693 return Thread::Current()->zone()->PrintToString( | 664 return Thread::Current()->zone()->PrintToString("%" Pd "", |
| 694 "%" Pd "", object_table_index_); | 665 object_table_index_); |
| 695 } | 666 } |
| 696 | 667 |
| 697 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 668 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 698 Function& function = Function::Handle(deopt_context->zone()); | 669 Function& function = Function::Handle(deopt_context->zone()); |
| 699 function ^= deopt_context->ObjectAt(object_table_index_); | 670 function ^= deopt_context->ObjectAt(object_table_index_); |
| 700 if (function.IsNull()) { | 671 if (function.IsNull()) { |
| 701 *reinterpret_cast<RawObject**>(dest_addr) = deopt_context->is_lazy_deopt() | 672 *reinterpret_cast<RawObject**>(dest_addr) = |
| 702 ? StubCode::DeoptimizeLazyFromReturn_entry()->code() | 673 deopt_context->is_lazy_deopt() |
| 703 : StubCode::Deoptimize_entry()->code(); | 674 ? StubCode::DeoptimizeLazyFromReturn_entry()->code() |
| 675 : StubCode::Deoptimize_entry()->code(); |
| 704 return; | 676 return; |
| 705 } | 677 } |
| 706 | 678 |
| 707 // We don't always have the Code object for the frame's corresponding | 679 // We don't always have the Code object for the frame's corresponding |
| 708 // unoptimized code as it may have been collected. Use a stub as the pc | 680 // unoptimized code as it may have been collected. Use a stub as the pc |
| 709 // marker until we can recreate that Code object during deferred | 681 // marker until we can recreate that Code object during deferred |
| 710 // materialization to maintain the invariant that Dart frames always have | 682 // materialization to maintain the invariant that Dart frames always have |
| 711 // a pc marker. | 683 // a pc marker. |
| 712 *reinterpret_cast<RawObject**>(dest_addr) = | 684 *reinterpret_cast<RawObject**>(dest_addr) = |
| 713 StubCode::FrameAwaitingMaterialization_entry()->code(); | 685 StubCode::FrameAwaitingMaterialization_entry()->code(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 727 public: | 699 public: |
| 728 explicit DeoptPpInstr(intptr_t object_table_index) | 700 explicit DeoptPpInstr(intptr_t object_table_index) |
| 729 : object_table_index_(object_table_index) { | 701 : object_table_index_(object_table_index) { |
| 730 ASSERT(object_table_index >= 0); | 702 ASSERT(object_table_index >= 0); |
| 731 } | 703 } |
| 732 | 704 |
| 733 virtual intptr_t source_index() const { return object_table_index_; } | 705 virtual intptr_t source_index() const { return object_table_index_; } |
| 734 virtual DeoptInstr::Kind kind() const { return kPp; } | 706 virtual DeoptInstr::Kind kind() const { return kPp; } |
| 735 | 707 |
| 736 virtual const char* ArgumentsToCString() const { | 708 virtual const char* ArgumentsToCString() const { |
| 737 return Thread::Current()->zone()->PrintToString( | 709 return Thread::Current()->zone()->PrintToString("%" Pd "", |
| 738 "%" Pd "", object_table_index_); | 710 object_table_index_); |
| 739 } | 711 } |
| 740 | 712 |
| 741 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 713 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 742 *dest_addr = Smi::RawValue(0); | 714 *dest_addr = Smi::RawValue(0); |
| 743 deopt_context->DeferPpMaterialization(object_table_index_, | 715 deopt_context->DeferPpMaterialization( |
| 744 reinterpret_cast<RawObject**>(dest_addr)); | 716 object_table_index_, reinterpret_cast<RawObject**>(dest_addr)); |
| 745 } | 717 } |
| 746 | 718 |
| 747 private: | 719 private: |
| 748 intptr_t object_table_index_; | 720 intptr_t object_table_index_; |
| 749 | 721 |
| 750 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); | 722 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); |
| 751 }; | 723 }; |
| 752 | 724 |
| 753 | 725 |
| 754 // Deoptimization instruction copying the caller saved FP from optimized frame. | 726 // Deoptimization instruction copying the caller saved FP from optimized frame. |
| 755 class DeoptCallerFpInstr : public DeoptInstr { | 727 class DeoptCallerFpInstr : public DeoptInstr { |
| 756 public: | 728 public: |
| 757 DeoptCallerFpInstr() {} | 729 DeoptCallerFpInstr() {} |
| 758 | 730 |
| 759 virtual intptr_t source_index() const { return 0; } | 731 virtual intptr_t source_index() const { return 0; } |
| 760 virtual DeoptInstr::Kind kind() const { return kCallerFp; } | 732 virtual DeoptInstr::Kind kind() const { return kCallerFp; } |
| 761 | 733 |
| 762 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 734 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 763 *dest_addr = deopt_context->GetCallerFp(); | 735 *dest_addr = deopt_context->GetCallerFp(); |
| 764 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>( | 736 deopt_context->SetCallerFp( |
| 765 dest_addr - kSavedCallerFpSlotFromFp)); | 737 reinterpret_cast<intptr_t>(dest_addr - kSavedCallerFpSlotFromFp)); |
| 766 } | 738 } |
| 767 | 739 |
| 768 private: | 740 private: |
| 769 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | 741 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); |
| 770 }; | 742 }; |
| 771 | 743 |
| 772 | 744 |
| 773 // Deoptimization instruction copying the caller saved PP from optimized frame. | 745 // Deoptimization instruction copying the caller saved PP from optimized frame. |
| 774 class DeoptCallerPpInstr : public DeoptInstr { | 746 class DeoptCallerPpInstr : public DeoptInstr { |
| 775 public: | 747 public: |
| (...skipping 26 matching lines...) Expand all Loading... |
| 802 | 774 |
| 803 private: | 775 private: |
| 804 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 776 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
| 805 }; | 777 }; |
| 806 | 778 |
| 807 | 779 |
| 808 // Write reference to a materialized object with the given index into the | 780 // Write reference to a materialized object with the given index into the |
| 809 // stack slot. | 781 // stack slot. |
| 810 class DeoptMaterializedObjectRefInstr : public DeoptInstr { | 782 class DeoptMaterializedObjectRefInstr : public DeoptInstr { |
| 811 public: | 783 public: |
| 812 explicit DeoptMaterializedObjectRefInstr(intptr_t index) | 784 explicit DeoptMaterializedObjectRefInstr(intptr_t index) : index_(index) { |
| 813 : index_(index) { | |
| 814 ASSERT(index >= 0); | 785 ASSERT(index >= 0); |
| 815 } | 786 } |
| 816 | 787 |
| 817 virtual intptr_t source_index() const { return index_; } | 788 virtual intptr_t source_index() const { return index_; } |
| 818 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } | 789 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } |
| 819 | 790 |
| 820 virtual const char* ArgumentsToCString() const { | 791 virtual const char* ArgumentsToCString() const { |
| 821 return Thread::Current()->zone()->PrintToString( | 792 return Thread::Current()->zone()->PrintToString("#%" Pd "", index_); |
| 822 "#%" Pd "", index_); | |
| 823 } | 793 } |
| 824 | 794 |
| 825 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 795 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 826 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | 796 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 827 deopt_context->DeferMaterializedObjectRef( | 797 deopt_context->DeferMaterializedObjectRef(index_, dest_addr); |
| 828 index_, dest_addr); | |
| 829 } | 798 } |
| 830 | 799 |
| 831 private: | 800 private: |
| 832 intptr_t index_; | 801 intptr_t index_; |
| 833 | 802 |
| 834 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); | 803 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); |
| 835 }; | 804 }; |
| 836 | 805 |
| 837 | 806 |
| 838 // Materialize object with the given number of fields. | 807 // Materialize object with the given number of fields. |
| 839 // Arguments for materialization (class and field-value pairs) are pushed | 808 // Arguments for materialization (class and field-value pairs) are pushed |
| 840 // to the expression stack of the bottom-most frame. | 809 // to the expression stack of the bottom-most frame. |
| 841 class DeoptMaterializeObjectInstr : public DeoptInstr { | 810 class DeoptMaterializeObjectInstr : public DeoptInstr { |
| 842 public: | 811 public: |
| 843 explicit DeoptMaterializeObjectInstr(intptr_t field_count) | 812 explicit DeoptMaterializeObjectInstr(intptr_t field_count) |
| 844 : field_count_(field_count) { | 813 : field_count_(field_count) { |
| 845 ASSERT(field_count >= 0); | 814 ASSERT(field_count >= 0); |
| 846 } | 815 } |
| 847 | 816 |
| 848 virtual intptr_t source_index() const { return field_count_; } | 817 virtual intptr_t source_index() const { return field_count_; } |
| 849 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } | 818 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } |
| 850 | 819 |
| 851 virtual const char* ArgumentsToCString() const { | 820 virtual const char* ArgumentsToCString() const { |
| 852 return Thread::Current()->zone()->PrintToString( | 821 return Thread::Current()->zone()->PrintToString("%" Pd "", field_count_); |
| 853 "%" Pd "", field_count_); | |
| 854 } | 822 } |
| 855 | 823 |
| 856 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 824 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 857 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. | 825 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. |
| 858 UNREACHABLE(); | 826 UNREACHABLE(); |
| 859 } | 827 } |
| 860 | 828 |
| 861 private: | 829 private: |
| 862 intptr_t field_count_; | 830 intptr_t field_count_; |
| 863 | 831 |
| 864 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); | 832 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); |
| 865 }; | 833 }; |
| 866 | 834 |
| 867 | 835 |
| 868 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, | 836 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, |
| 869 const ObjectPool& object_table, | 837 const ObjectPool& object_table, |
| 870 Code* code) { | 838 Code* code) { |
| 871 ASSERT(instr->kind() == kRetAddress); | 839 ASSERT(instr->kind() == kRetAddress); |
| 872 DeoptRetAddressInstr* ret_address_instr = | 840 DeoptRetAddressInstr* ret_address_instr = |
| 873 static_cast<DeoptRetAddressInstr*>(instr); | 841 static_cast<DeoptRetAddressInstr*>(instr); |
| 874 // The following assert may trigger when displaying a backtrace | 842 // The following assert may trigger when displaying a backtrace |
| 875 // from the simulator. | 843 // from the simulator. |
| 876 ASSERT(Thread::IsDeoptAfter(ret_address_instr->deopt_id())); | 844 ASSERT(Thread::IsDeoptAfter(ret_address_instr->deopt_id())); |
| 877 ASSERT(!object_table.IsNull()); | 845 ASSERT(!object_table.IsNull()); |
| 878 Thread* thread = Thread::Current(); | 846 Thread* thread = Thread::Current(); |
| 879 Zone* zone = thread->zone(); | 847 Zone* zone = thread->zone(); |
| 880 Function& function = Function::Handle(zone); | 848 Function& function = Function::Handle(zone); |
| 881 function ^= object_table.ObjectAt(ret_address_instr->object_table_index()); | 849 function ^= object_table.ObjectAt(ret_address_instr->object_table_index()); |
| 882 ASSERT(code != NULL); | 850 ASSERT(code != NULL); |
| 883 const Error& error = Error::Handle(zone, | 851 const Error& error = |
| 884 Compiler::EnsureUnoptimizedCode(thread, function)); | 852 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); |
| 885 if (!error.IsNull()) { | 853 if (!error.IsNull()) { |
| 886 Exceptions::PropagateError(error); | 854 Exceptions::PropagateError(error); |
| 887 } | 855 } |
| 888 *code ^= function.unoptimized_code(); | 856 *code ^= function.unoptimized_code(); |
| 889 ASSERT(!code->IsNull()); | 857 ASSERT(!code->IsNull()); |
| 890 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), | 858 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), |
| 891 RawPcDescriptors::kDeopt); | 859 RawPcDescriptors::kDeopt); |
| 892 ASSERT(res != 0); | 860 ASSERT(res != 0); |
| 893 return res; | 861 return res; |
| 894 } | 862 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 979 } | 947 } |
| 980 UNREACHABLE(); | 948 UNREACHABLE(); |
| 981 return NULL; | 949 return NULL; |
| 982 } | 950 } |
| 983 | 951 |
| 984 | 952 |
| 985 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { | 953 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { |
| 986 public: | 954 public: |
| 987 // Construct the root node representing the implicit "shared" terminator | 955 // Construct the root node representing the implicit "shared" terminator |
| 988 // at the end of each deopt info. | 956 // at the end of each deopt info. |
| 989 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) { } | 957 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) {} |
| 990 | 958 |
| 991 // Construct a node representing a written instruction. | 959 // Construct a node representing a written instruction. |
| 992 TrieNode(DeoptInstr* instruction, intptr_t info_number) | 960 TrieNode(DeoptInstr* instruction, intptr_t info_number) |
| 993 : instruction_(instruction), info_number_(info_number), children_(4) { } | 961 : instruction_(instruction), info_number_(info_number), children_(4) {} |
| 994 | 962 |
| 995 intptr_t info_number() const { return info_number_; } | 963 intptr_t info_number() const { return info_number_; } |
| 996 | 964 |
| 997 void AddChild(TrieNode* child) { | 965 void AddChild(TrieNode* child) { |
| 998 if (child != NULL) children_.Add(child); | 966 if (child != NULL) children_.Add(child); |
| 999 } | 967 } |
| 1000 | 968 |
| 1001 TrieNode* FindChild(const DeoptInstr& instruction) { | 969 TrieNode* FindChild(const DeoptInstr& instruction) { |
| 1002 for (intptr_t i = 0; i < children_.length(); ++i) { | 970 for (intptr_t i = 0; i < children_.length(); ++i) { |
| 1003 TrieNode* child = children_[i]; | 971 TrieNode* child = children_[i]; |
| 1004 if (child->instruction_->Equals(instruction)) return child; | 972 if (child->instruction_->Equals(instruction)) return child; |
| 1005 } | 973 } |
| 1006 return NULL; | 974 return NULL; |
| 1007 } | 975 } |
| 1008 | 976 |
| 1009 private: | 977 private: |
| 1010 const DeoptInstr* instruction_; // Instruction that was written. | 978 const DeoptInstr* instruction_; // Instruction that was written. |
| 1011 const intptr_t info_number_; // Index of the deopt info it was written to. | 979 const intptr_t info_number_; // Index of the deopt info it was written to. |
| 1012 | 980 |
| 1013 GrowableArray<TrieNode*> children_; | 981 GrowableArray<TrieNode*> children_; |
| 1014 }; | 982 }; |
| 1015 | 983 |
| 1016 | 984 |
| 1017 DeoptInfoBuilder::DeoptInfoBuilder(Zone* zone, | 985 DeoptInfoBuilder::DeoptInfoBuilder(Zone* zone, |
| 1018 const intptr_t num_args, | 986 const intptr_t num_args, |
| 1019 Assembler* assembler) | 987 Assembler* assembler) |
| 1020 : zone_(zone), | 988 : zone_(zone), |
| 1021 instructions_(), | 989 instructions_(), |
| 1022 num_args_(num_args), | 990 num_args_(num_args), |
| 1023 assembler_(assembler), | 991 assembler_(assembler), |
| 1024 trie_root_(new(zone) TrieNode()), | 992 trie_root_(new (zone) TrieNode()), |
| 1025 current_info_number_(0), | 993 current_info_number_(0), |
| 1026 frame_start_(-1), | 994 frame_start_(-1), |
| 1027 materializations_() { | 995 materializations_() {} |
| 1028 } | |
| 1029 | 996 |
| 1030 | 997 |
| 1031 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { | 998 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { |
| 1032 return assembler_->object_pool_wrapper().FindObject(obj); | 999 return assembler_->object_pool_wrapper().FindObject(obj); |
| 1033 } | 1000 } |
| 1034 | 1001 |
| 1035 | 1002 |
| 1036 intptr_t DeoptInfoBuilder::CalculateStackIndex( | 1003 intptr_t DeoptInfoBuilder::CalculateStackIndex( |
| 1037 const Location& source_loc) const { | 1004 const Location& source_loc) const { |
| 1038 return source_loc.stack_index() < 0 ? | 1005 return source_loc.stack_index() < 0 |
| 1039 source_loc.stack_index() + num_args_ : | 1006 ? source_loc.stack_index() + num_args_ |
| 1040 source_loc.stack_index() + num_args_ + kDartFrameFixedSize; | 1007 : source_loc.stack_index() + num_args_ + kDartFrameFixedSize; |
| 1041 } | 1008 } |
| 1042 | 1009 |
| 1043 | 1010 |
| 1044 CpuRegisterSource DeoptInfoBuilder::ToCpuRegisterSource(const Location& loc) { | 1011 CpuRegisterSource DeoptInfoBuilder::ToCpuRegisterSource(const Location& loc) { |
| 1045 if (loc.IsRegister()) { | 1012 if (loc.IsRegister()) { |
| 1046 return CpuRegisterSource(CpuRegisterSource::kRegister, loc.reg()); | 1013 return CpuRegisterSource(CpuRegisterSource::kRegister, loc.reg()); |
| 1047 } else { | 1014 } else { |
| 1048 ASSERT(loc.IsStackSlot()); | 1015 ASSERT(loc.IsStackSlot()); |
| 1049 return CpuRegisterSource( | 1016 return CpuRegisterSource(CpuRegisterSource::kStackSlot, |
| 1050 CpuRegisterSource::kStackSlot, CalculateStackIndex(loc)); | 1017 CalculateStackIndex(loc)); |
| 1051 } | 1018 } |
| 1052 } | 1019 } |
| 1053 | 1020 |
| 1054 | 1021 |
| 1055 FpuRegisterSource DeoptInfoBuilder::ToFpuRegisterSource( | 1022 FpuRegisterSource DeoptInfoBuilder::ToFpuRegisterSource( |
| 1056 const Location& loc, | 1023 const Location& loc, |
| 1057 Location::Kind stack_slot_kind) { | 1024 Location::Kind stack_slot_kind) { |
| 1058 if (loc.IsFpuRegister()) { | 1025 if (loc.IsFpuRegister()) { |
| 1059 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); | 1026 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); |
| 1060 #if defined(TARGET_ARCH_DBC) | 1027 #if defined(TARGET_ARCH_DBC) |
| 1061 } else if (loc.IsRegister()) { | 1028 } else if (loc.IsRegister()) { |
| 1062 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg()); | 1029 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg()); |
| 1063 #endif | 1030 #endif |
| 1064 } else { | 1031 } else { |
| 1065 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || | 1032 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || |
| 1066 (stack_slot_kind == Location::kDoubleStackSlot)); | 1033 (stack_slot_kind == Location::kDoubleStackSlot)); |
| 1067 ASSERT(loc.kind() == stack_slot_kind); | 1034 ASSERT(loc.kind() == stack_slot_kind); |
| 1068 return FpuRegisterSource( | 1035 return FpuRegisterSource(FpuRegisterSource::kStackSlot, |
| 1069 FpuRegisterSource::kStackSlot, CalculateStackIndex(loc)); | 1036 CalculateStackIndex(loc)); |
| 1070 } | 1037 } |
| 1071 } | 1038 } |
| 1072 | 1039 |
| 1073 void DeoptInfoBuilder::AddReturnAddress(const Function& function, | 1040 void DeoptInfoBuilder::AddReturnAddress(const Function& function, |
| 1074 intptr_t deopt_id, | 1041 intptr_t deopt_id, |
| 1075 intptr_t dest_index) { | 1042 intptr_t dest_index) { |
| 1076 const intptr_t object_table_index = FindOrAddObjectInTable(function); | 1043 const intptr_t object_table_index = FindOrAddObjectInTable(function); |
| 1077 ASSERT(dest_index == FrameSize()); | 1044 ASSERT(dest_index == FrameSize()); |
| 1078 instructions_.Add( | 1045 instructions_.Add(new (zone()) |
| 1079 new(zone()) DeoptRetAddressInstr(object_table_index, deopt_id)); | 1046 DeoptRetAddressInstr(object_table_index, deopt_id)); |
| 1080 } | 1047 } |
| 1081 | 1048 |
| 1082 | 1049 |
| 1083 void DeoptInfoBuilder::AddPcMarker(const Function& function, | 1050 void DeoptInfoBuilder::AddPcMarker(const Function& function, |
| 1084 intptr_t dest_index) { | 1051 intptr_t dest_index) { |
| 1085 intptr_t object_table_index = FindOrAddObjectInTable(function); | 1052 intptr_t object_table_index = FindOrAddObjectInTable(function); |
| 1086 ASSERT(dest_index == FrameSize()); | 1053 ASSERT(dest_index == FrameSize()); |
| 1087 instructions_.Add(new(zone()) DeoptPcMarkerInstr(object_table_index)); | 1054 instructions_.Add(new (zone()) DeoptPcMarkerInstr(object_table_index)); |
| 1088 } | 1055 } |
| 1089 | 1056 |
| 1090 | 1057 |
| 1091 void DeoptInfoBuilder::AddPp(const Function& function, | 1058 void DeoptInfoBuilder::AddPp(const Function& function, intptr_t dest_index) { |
| 1092 intptr_t dest_index) { | |
| 1093 intptr_t object_table_index = FindOrAddObjectInTable(function); | 1059 intptr_t object_table_index = FindOrAddObjectInTable(function); |
| 1094 ASSERT(dest_index == FrameSize()); | 1060 ASSERT(dest_index == FrameSize()); |
| 1095 instructions_.Add(new(zone()) DeoptPpInstr(object_table_index)); | 1061 instructions_.Add(new (zone()) DeoptPpInstr(object_table_index)); |
| 1096 } | 1062 } |
| 1097 | 1063 |
| 1098 | 1064 |
| 1099 void DeoptInfoBuilder::AddCopy(Value* value, | 1065 void DeoptInfoBuilder::AddCopy(Value* value, |
| 1100 const Location& source_loc, | 1066 const Location& source_loc, |
| 1101 const intptr_t dest_index) { | 1067 const intptr_t dest_index) { |
| 1102 DeoptInstr* deopt_instr = NULL; | 1068 DeoptInstr* deopt_instr = NULL; |
| 1103 if (source_loc.IsConstant()) { | 1069 if (source_loc.IsConstant()) { |
| 1104 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); | 1070 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); |
| 1105 deopt_instr = new(zone()) DeoptConstantInstr(object_table_index); | 1071 deopt_instr = new (zone()) DeoptConstantInstr(object_table_index); |
| 1106 } else if (source_loc.IsInvalid() && | 1072 } else if (source_loc.IsInvalid() && |
| 1107 value->definition()->IsMaterializeObject()) { | 1073 value->definition()->IsMaterializeObject()) { |
| 1108 const intptr_t index = FindMaterialization( | 1074 const intptr_t index = |
| 1109 value->definition()->AsMaterializeObject()); | 1075 FindMaterialization(value->definition()->AsMaterializeObject()); |
| 1110 ASSERT(index >= 0); | 1076 ASSERT(index >= 0); |
| 1111 deopt_instr = new(zone()) DeoptMaterializedObjectRefInstr(index); | 1077 deopt_instr = new (zone()) DeoptMaterializedObjectRefInstr(index); |
| 1112 } else { | 1078 } else { |
| 1113 ASSERT(!source_loc.IsInvalid()); | 1079 ASSERT(!source_loc.IsInvalid()); |
| 1114 switch (value->definition()->representation()) { | 1080 switch (value->definition()->representation()) { |
| 1115 case kTagged: | 1081 case kTagged: |
| 1116 deopt_instr = new(zone()) DeoptWordInstr( | 1082 deopt_instr = |
| 1117 ToCpuRegisterSource(source_loc)); | 1083 new (zone()) DeoptWordInstr(ToCpuRegisterSource(source_loc)); |
| 1118 break; | 1084 break; |
| 1119 case kUnboxedMint: { | 1085 case kUnboxedMint: { |
| 1120 if (source_loc.IsPairLocation()) { | 1086 if (source_loc.IsPairLocation()) { |
| 1121 PairLocation* pair = source_loc.AsPairLocation(); | 1087 PairLocation* pair = source_loc.AsPairLocation(); |
| 1122 deopt_instr = new(zone()) DeoptMintPairInstr( | 1088 deopt_instr = |
| 1123 ToCpuRegisterSource(pair->At(0)), | 1089 new (zone()) DeoptMintPairInstr(ToCpuRegisterSource(pair->At(0)), |
| 1124 ToCpuRegisterSource(pair->At(1))); | 1090 ToCpuRegisterSource(pair->At(1))); |
| 1125 } else { | 1091 } else { |
| 1126 ASSERT(!source_loc.IsPairLocation()); | 1092 ASSERT(!source_loc.IsPairLocation()); |
| 1127 deopt_instr = new(zone()) DeoptMintInstr( | 1093 deopt_instr = |
| 1128 ToCpuRegisterSource(source_loc)); | 1094 new (zone()) DeoptMintInstr(ToCpuRegisterSource(source_loc)); |
| 1129 } | 1095 } |
| 1130 break; | 1096 break; |
| 1131 } | 1097 } |
| 1132 case kUnboxedInt32: | 1098 case kUnboxedInt32: |
| 1133 deopt_instr = new(zone()) DeoptInt32Instr( | 1099 deopt_instr = |
| 1134 ToCpuRegisterSource(source_loc)); | 1100 new (zone()) DeoptInt32Instr(ToCpuRegisterSource(source_loc)); |
| 1135 break; | 1101 break; |
| 1136 case kUnboxedUint32: | 1102 case kUnboxedUint32: |
| 1137 deopt_instr = new(zone()) DeoptUint32Instr( | 1103 deopt_instr = |
| 1138 ToCpuRegisterSource(source_loc)); | 1104 new (zone()) DeoptUint32Instr(ToCpuRegisterSource(source_loc)); |
| 1139 break; | 1105 break; |
| 1140 case kUnboxedDouble: | 1106 case kUnboxedDouble: |
| 1141 deopt_instr = new(zone()) DeoptDoubleInstr( | 1107 deopt_instr = new (zone()) DeoptDoubleInstr( |
| 1142 ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot)); | 1108 ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot)); |
| 1143 break; | 1109 break; |
| 1144 case kUnboxedFloat32x4: | 1110 case kUnboxedFloat32x4: |
| 1145 deopt_instr = new(zone()) DeoptFloat32x4Instr( | 1111 deopt_instr = new (zone()) DeoptFloat32x4Instr( |
| 1146 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); | 1112 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
| 1147 break; | 1113 break; |
| 1148 case kUnboxedFloat64x2: | 1114 case kUnboxedFloat64x2: |
| 1149 deopt_instr = new(zone()) DeoptFloat64x2Instr( | 1115 deopt_instr = new (zone()) DeoptFloat64x2Instr( |
| 1150 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); | 1116 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
| 1151 break; | 1117 break; |
| 1152 case kUnboxedInt32x4: | 1118 case kUnboxedInt32x4: |
| 1153 deopt_instr = new(zone()) DeoptInt32x4Instr( | 1119 deopt_instr = new (zone()) DeoptInt32x4Instr( |
| 1154 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); | 1120 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
| 1155 break; | 1121 break; |
| 1156 default: | 1122 default: |
| 1157 UNREACHABLE(); | 1123 UNREACHABLE(); |
| 1158 break; | 1124 break; |
| 1159 } | 1125 } |
| 1160 } | 1126 } |
| 1161 ASSERT(dest_index == FrameSize()); | 1127 ASSERT(dest_index == FrameSize()); |
| 1162 ASSERT(deopt_instr != NULL); | 1128 ASSERT(deopt_instr != NULL); |
| 1163 instructions_.Add(deopt_instr); | 1129 instructions_.Add(deopt_instr); |
| 1164 } | 1130 } |
| 1165 | 1131 |
| 1166 | 1132 |
| 1167 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { | 1133 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { |
| 1168 ASSERT(dest_index == FrameSize()); | 1134 ASSERT(dest_index == FrameSize()); |
| 1169 instructions_.Add(new(zone()) DeoptCallerFpInstr()); | 1135 instructions_.Add(new (zone()) DeoptCallerFpInstr()); |
| 1170 } | 1136 } |
| 1171 | 1137 |
| 1172 | 1138 |
| 1173 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { | 1139 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { |
| 1174 ASSERT(dest_index == FrameSize()); | 1140 ASSERT(dest_index == FrameSize()); |
| 1175 instructions_.Add(new(zone()) DeoptCallerPpInstr()); | 1141 instructions_.Add(new (zone()) DeoptCallerPpInstr()); |
| 1176 } | 1142 } |
| 1177 | 1143 |
| 1178 | 1144 |
| 1179 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { | 1145 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { |
| 1180 ASSERT(dest_index == FrameSize()); | 1146 ASSERT(dest_index == FrameSize()); |
| 1181 instructions_.Add(new(zone()) DeoptCallerPcInstr()); | 1147 instructions_.Add(new (zone()) DeoptCallerPcInstr()); |
| 1182 } | 1148 } |
| 1183 | 1149 |
| 1184 | 1150 |
| 1185 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { | 1151 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { |
| 1186 ASSERT(dest_index == FrameSize()); | 1152 ASSERT(dest_index == FrameSize()); |
| 1187 intptr_t object_table_index = FindOrAddObjectInTable(obj); | 1153 intptr_t object_table_index = FindOrAddObjectInTable(obj); |
| 1188 instructions_.Add(new(zone()) DeoptConstantInstr(object_table_index)); | 1154 instructions_.Add(new (zone()) DeoptConstantInstr(object_table_index)); |
| 1189 } | 1155 } |
| 1190 | 1156 |
| 1191 | 1157 |
| 1192 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { | 1158 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { |
| 1193 const intptr_t index = FindMaterialization(mat); | 1159 const intptr_t index = FindMaterialization(mat); |
| 1194 if (index >= 0) { | 1160 if (index >= 0) { |
| 1195 return; // Already added. | 1161 return; // Already added. |
| 1196 } | 1162 } |
| 1197 materializations_.Add(mat); | 1163 materializations_.Add(mat); |
| 1198 | 1164 |
| 1199 // Count initialized fields and emit kMaterializeObject instruction. | 1165 // Count initialized fields and emit kMaterializeObject instruction. |
| 1200 // There is no need to write nulls into fields because object is null | 1166 // There is no need to write nulls into fields because object is null |
| 1201 // initialized by default. | 1167 // initialized by default. |
| 1202 intptr_t non_null_fields = 0; | 1168 intptr_t non_null_fields = 0; |
| 1203 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1169 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 1204 if (!mat->InputAt(i)->BindsToConstantNull()) { | 1170 if (!mat->InputAt(i)->BindsToConstantNull()) { |
| 1205 non_null_fields++; | 1171 non_null_fields++; |
| 1206 } | 1172 } |
| 1207 } | 1173 } |
| 1208 | 1174 |
| 1209 instructions_.Add( | 1175 instructions_.Add(new (zone()) DeoptMaterializeObjectInstr(non_null_fields)); |
| 1210 new(zone()) DeoptMaterializeObjectInstr(non_null_fields)); | |
| 1211 | 1176 |
| 1212 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1177 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 1213 MaterializeObjectInstr* nested_mat = mat->InputAt(i)->definition()-> | 1178 MaterializeObjectInstr* nested_mat = |
| 1214 AsMaterializeObject(); | 1179 mat->InputAt(i)->definition()->AsMaterializeObject(); |
| 1215 if (nested_mat != NULL) { | 1180 if (nested_mat != NULL) { |
| 1216 AddMaterialization(nested_mat); | 1181 AddMaterialization(nested_mat); |
| 1217 } | 1182 } |
| 1218 } | 1183 } |
| 1219 } | 1184 } |
| 1220 | 1185 |
| 1221 | 1186 |
| 1222 intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) { | 1187 intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) { |
| 1223 ASSERT(dest_index == kDartFrameFixedSize); | 1188 ASSERT(dest_index == kDartFrameFixedSize); |
| 1224 for (intptr_t i = 0; i < materializations_.length(); i++) { | 1189 for (intptr_t i = 0; i < materializations_.length(); i++) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1246 return i; | 1211 return i; |
| 1247 } | 1212 } |
| 1248 } | 1213 } |
| 1249 return -1; | 1214 return -1; |
| 1250 } | 1215 } |
| 1251 | 1216 |
| 1252 | 1217 |
| 1253 static uint8_t* ZoneReAlloc(uint8_t* ptr, | 1218 static uint8_t* ZoneReAlloc(uint8_t* ptr, |
| 1254 intptr_t old_size, | 1219 intptr_t old_size, |
| 1255 intptr_t new_size) { | 1220 intptr_t new_size) { |
| 1256 return Thread::Current()->zone()->Realloc<uint8_t>( | 1221 return Thread::Current()->zone()->Realloc<uint8_t>(ptr, old_size, new_size); |
| 1257 ptr, old_size, new_size); | |
| 1258 } | 1222 } |
| 1259 | 1223 |
| 1260 | 1224 |
| 1261 RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) { | 1225 RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) { |
| 1262 intptr_t length = instructions_.length(); | 1226 intptr_t length = instructions_.length(); |
| 1263 | 1227 |
| 1264 // Count the number of instructions that are a shared suffix of some deopt | 1228 // Count the number of instructions that are a shared suffix of some deopt |
| 1265 // info already written. | 1229 // info already written. |
| 1266 TrieNode* suffix = trie_root_; | 1230 TrieNode* suffix = trie_root_; |
| 1267 intptr_t suffix_length = 0; | 1231 intptr_t suffix_length = 0; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1296 } | 1260 } |
| 1297 | 1261 |
| 1298 // Write the unshared instructions and build their sub-tree. | 1262 // Write the unshared instructions and build their sub-tree. |
| 1299 TrieNode* node = use_suffix ? suffix : trie_root_; | 1263 TrieNode* node = use_suffix ? suffix : trie_root_; |
| 1300 const intptr_t write_count = use_suffix ? length - 1 : length; | 1264 const intptr_t write_count = use_suffix ? length - 1 : length; |
| 1301 for (intptr_t i = write_count - 1; i >= 0; --i) { | 1265 for (intptr_t i = write_count - 1; i >= 0; --i) { |
| 1302 DeoptInstr* instr = instructions_[i]; | 1266 DeoptInstr* instr = instructions_[i]; |
| 1303 Writer::Write(&stream, instr->kind()); | 1267 Writer::Write(&stream, instr->kind()); |
| 1304 Writer::Write(&stream, instr->source_index()); | 1268 Writer::Write(&stream, instr->source_index()); |
| 1305 | 1269 |
| 1306 TrieNode* child = new(zone()) TrieNode(instr, current_info_number_); | 1270 TrieNode* child = new (zone()) TrieNode(instr, current_info_number_); |
| 1307 node->AddChild(child); | 1271 node->AddChild(child); |
| 1308 node = child; | 1272 node = child; |
| 1309 } | 1273 } |
| 1310 | 1274 |
| 1311 const TypedData& deopt_info = TypedData::Handle(zone(), TypedData::New( | 1275 const TypedData& deopt_info = TypedData::Handle( |
| 1312 kTypedDataUint8ArrayCid, stream.bytes_written(), Heap::kOld)); | 1276 zone(), TypedData::New(kTypedDataUint8ArrayCid, stream.bytes_written(), |
| 1277 Heap::kOld)); |
| 1313 { | 1278 { |
| 1314 NoSafepointScope no_safepoint; | 1279 NoSafepointScope no_safepoint; |
| 1315 memmove(deopt_info.DataAddr(0), | 1280 memmove(deopt_info.DataAddr(0), stream.buffer(), stream.bytes_written()); |
| 1316 stream.buffer(), | |
| 1317 stream.bytes_written()); | |
| 1318 } | 1281 } |
| 1319 | 1282 |
| 1320 ASSERT(DeoptInfo::VerifyDecompression( | 1283 ASSERT( |
| 1321 instructions_, deopt_table, deopt_info)); | 1284 DeoptInfo::VerifyDecompression(instructions_, deopt_table, deopt_info)); |
| 1322 instructions_.Clear(); | 1285 instructions_.Clear(); |
| 1323 materializations_.Clear(); | 1286 materializations_.Clear(); |
| 1324 frame_start_ = -1; | 1287 frame_start_ = -1; |
| 1325 | 1288 |
| 1326 ++current_info_number_; | 1289 ++current_info_number_; |
| 1327 return deopt_info.raw(); | 1290 return deopt_info.raw(); |
| 1328 } | 1291 } |
| 1329 | 1292 |
| 1330 | 1293 |
| 1331 intptr_t DeoptTable::SizeFor(intptr_t length) { | 1294 intptr_t DeoptTable::SizeFor(intptr_t length) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1356 Smi* offset, | 1319 Smi* offset, |
| 1357 TypedData* info, | 1320 TypedData* info, |
| 1358 Smi* reason) { | 1321 Smi* reason) { |
| 1359 intptr_t i = index * kEntrySize; | 1322 intptr_t i = index * kEntrySize; |
| 1360 *offset ^= table.At(i); | 1323 *offset ^= table.At(i); |
| 1361 *info ^= table.At(i + 1); | 1324 *info ^= table.At(i + 1); |
| 1362 *reason ^= table.At(i + 2); | 1325 *reason ^= table.At(i + 2); |
| 1363 } | 1326 } |
| 1364 | 1327 |
| 1365 } // namespace dart | 1328 } // namespace dart |
| OLD | NEW |