| 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, | 20 DEFINE_FLAG(bool, |
| 21 compress_deopt_info, | 21 compress_deopt_info, |
| 22 true, | 22 true, |
| 23 "Compress the size of the deoptimization info for optimized code."); | 23 "Compress the size of the deoptimization info for optimized code."); |
| 24 DECLARE_FLAG(bool, trace_deoptimization); | 24 DECLARE_FLAG(bool, trace_deoptimization); |
| 25 DECLARE_FLAG(bool, trace_deoptimization_verbose); | 25 DECLARE_FLAG(bool, trace_deoptimization_verbose); |
| 26 | 26 |
| 27 | |
| 28 DeoptContext::DeoptContext(const StackFrame* frame, | 27 DeoptContext::DeoptContext(const StackFrame* frame, |
| 29 const Code& code, | 28 const Code& code, |
| 30 DestFrameOptions dest_options, | 29 DestFrameOptions dest_options, |
| 31 fpu_register_t* fpu_registers, | 30 fpu_register_t* fpu_registers, |
| 32 intptr_t* cpu_registers, | 31 intptr_t* cpu_registers, |
| 33 bool is_lazy_deopt, | 32 bool is_lazy_deopt, |
| 34 bool deoptimizing_code) | 33 bool deoptimizing_code) |
| 35 : code_(code.raw()), | 34 : code_(code.raw()), |
| 36 object_pool_(code.GetObjectPool()), | 35 object_pool_(code.GetObjectPool()), |
| 37 deopt_info_(TypedData::null()), | 36 deopt_info_(TypedData::null()), |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | 124 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| 126 THR_Print( | 125 THR_Print( |
| 127 "Deoptimizing (reason %d '%s') at " | 126 "Deoptimizing (reason %d '%s') at " |
| 128 "pc=%" Pp " fp=%" Pp " '%s' (count %d)\n", | 127 "pc=%" Pp " fp=%" Pp " '%s' (count %d)\n", |
| 129 deopt_reason(), DeoptReasonToCString(deopt_reason()), frame->pc(), | 128 deopt_reason(), DeoptReasonToCString(deopt_reason()), frame->pc(), |
| 130 frame->fp(), function.ToFullyQualifiedCString(), | 129 frame->fp(), function.ToFullyQualifiedCString(), |
| 131 function.deoptimization_counter()); | 130 function.deoptimization_counter()); |
| 132 } | 131 } |
| 133 } | 132 } |
| 134 | 133 |
| 135 | |
| 136 DeoptContext::~DeoptContext() { | 134 DeoptContext::~DeoptContext() { |
| 137 // Delete memory for source frame and registers. | 135 // Delete memory for source frame and registers. |
| 138 if (source_frame_is_allocated_) { | 136 if (source_frame_is_allocated_) { |
| 139 delete[] source_frame_; | 137 delete[] source_frame_; |
| 140 } | 138 } |
| 141 source_frame_ = NULL; | 139 source_frame_ = NULL; |
| 142 delete[] fpu_registers_; | 140 delete[] fpu_registers_; |
| 143 delete[] cpu_registers_; | 141 delete[] cpu_registers_; |
| 144 fpu_registers_ = NULL; | 142 fpu_registers_ = NULL; |
| 145 cpu_registers_ = NULL; | 143 cpu_registers_ = NULL; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 176 timeline_event->CopyArgument(0, "function", function_name.ToCString()); | 174 timeline_event->CopyArgument(0, "function", function_name.ToCString()); |
| 177 timeline_event->CopyArgument(1, "reason", reason); | 175 timeline_event->CopyArgument(1, "reason", reason); |
| 178 timeline_event->FormatArgument(2, "deoptimizationCount", "%d", counter); | 176 timeline_event->FormatArgument(2, "deoptimizationCount", "%d", counter); |
| 179 timeline_event->Complete(); | 177 timeline_event->Complete(); |
| 180 } | 178 } |
| 181 } | 179 } |
| 182 } | 180 } |
| 183 #endif // !PRODUCT | 181 #endif // !PRODUCT |
| 184 } | 182 } |
| 185 | 183 |
| 186 | |
| 187 void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 184 void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 188 visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_pool_)); | 185 visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_pool_)); |
| 189 visitor->VisitPointer(reinterpret_cast<RawObject**>(&deopt_info_)); | 186 visitor->VisitPointer(reinterpret_cast<RawObject**>(&deopt_info_)); |
| 190 | 187 |
| 191 // Visit any object pointers on the destination stack. | 188 // Visit any object pointers on the destination stack. |
| 192 if (dest_frame_is_allocated_) { | 189 if (dest_frame_is_allocated_) { |
| 193 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 190 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
| 194 if (dest_frame_[i] != 0) { | 191 if (dest_frame_[i] != 0) { |
| 195 visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i])); | 192 visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i])); |
| 196 } | 193 } |
| 197 } | 194 } |
| 198 } | 195 } |
| 199 } | 196 } |
| 200 | 197 |
| 201 | |
| 202 intptr_t DeoptContext::DestStackAdjustment() const { | 198 intptr_t DeoptContext::DestStackAdjustment() const { |
| 203 return dest_frame_size_ - kDartFrameFixedSize - num_args_ | 199 return dest_frame_size_ - kDartFrameFixedSize - num_args_ |
| 204 #if !defined(TARGET_ARCH_DBC) | 200 #if !defined(TARGET_ARCH_DBC) |
| 205 - 1 // For fp. | 201 - 1 // For fp. |
| 206 #endif | 202 #endif |
| 207 - kParamEndSlotFromFp; | 203 - kParamEndSlotFromFp; |
| 208 } | 204 } |
| 209 | 205 |
| 210 | |
| 211 intptr_t DeoptContext::GetSourceFp() const { | 206 intptr_t DeoptContext::GetSourceFp() const { |
| 212 #if !defined(TARGET_ARCH_DBC) | 207 #if !defined(TARGET_ARCH_DBC) |
| 213 return source_frame_[source_frame_size_ - 1 - num_args_ - | 208 return source_frame_[source_frame_size_ - 1 - num_args_ - |
| 214 kParamEndSlotFromFp]; | 209 kParamEndSlotFromFp]; |
| 215 #else | 210 #else |
| 216 return source_frame_[num_args_ + kDartFrameFixedSize + | 211 return source_frame_[num_args_ + kDartFrameFixedSize + |
| 217 kSavedCallerFpSlotFromFp]; | 212 kSavedCallerFpSlotFromFp]; |
| 218 #endif | 213 #endif |
| 219 } | 214 } |
| 220 | 215 |
| 221 | |
| 222 intptr_t DeoptContext::GetSourcePp() const { | 216 intptr_t DeoptContext::GetSourcePp() const { |
| 223 #if !defined(TARGET_ARCH_DBC) | 217 #if !defined(TARGET_ARCH_DBC) |
| 224 return source_frame_[source_frame_size_ - 1 - num_args_ - | 218 return source_frame_[source_frame_size_ - 1 - num_args_ - |
| 225 kParamEndSlotFromFp + | 219 kParamEndSlotFromFp + |
| 226 StackFrame::SavedCallerPpSlotFromFp()]; | 220 StackFrame::SavedCallerPpSlotFromFp()]; |
| 227 #else | 221 #else |
| 228 UNREACHABLE(); | 222 UNREACHABLE(); |
| 229 return 0; | 223 return 0; |
| 230 #endif | 224 #endif |
| 231 } | 225 } |
| 232 | 226 |
| 233 | |
| 234 intptr_t DeoptContext::GetSourcePc() const { | 227 intptr_t DeoptContext::GetSourcePc() const { |
| 235 #if !defined(TARGET_ARCH_DBC) | 228 #if !defined(TARGET_ARCH_DBC) |
| 236 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; | 229 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; |
| 237 #else | 230 #else |
| 238 return source_frame_[num_args_ + kDartFrameFixedSize + | 231 return source_frame_[num_args_ + kDartFrameFixedSize + |
| 239 kSavedCallerPcSlotFromFp]; | 232 kSavedCallerPcSlotFromFp]; |
| 240 #endif | 233 #endif |
| 241 } | 234 } |
| 242 | 235 |
| 243 | |
| 244 intptr_t DeoptContext::GetCallerFp() const { | 236 intptr_t DeoptContext::GetCallerFp() const { |
| 245 return caller_fp_; | 237 return caller_fp_; |
| 246 } | 238 } |
| 247 | 239 |
| 248 | |
| 249 void DeoptContext::SetCallerFp(intptr_t caller_fp) { | 240 void DeoptContext::SetCallerFp(intptr_t caller_fp) { |
| 250 caller_fp_ = caller_fp; | 241 caller_fp_ = caller_fp; |
| 251 } | 242 } |
| 252 | 243 |
| 253 | |
| 254 static bool IsObjectInstruction(DeoptInstr::Kind kind) { | 244 static bool IsObjectInstruction(DeoptInstr::Kind kind) { |
| 255 switch (kind) { | 245 switch (kind) { |
| 256 case DeoptInstr::kConstant: | 246 case DeoptInstr::kConstant: |
| 257 case DeoptInstr::kPp: | 247 case DeoptInstr::kPp: |
| 258 case DeoptInstr::kCallerPp: | 248 case DeoptInstr::kCallerPp: |
| 259 case DeoptInstr::kMaterializedObjectRef: | 249 case DeoptInstr::kMaterializedObjectRef: |
| 260 case DeoptInstr::kFloat32x4: | 250 case DeoptInstr::kFloat32x4: |
| 261 case DeoptInstr::kInt32x4: | 251 case DeoptInstr::kInt32x4: |
| 262 case DeoptInstr::kFloat64x2: | 252 case DeoptInstr::kFloat64x2: |
| 263 case DeoptInstr::kWord: | 253 case DeoptInstr::kWord: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 277 case DeoptInstr::kMaterializeObject: | 267 case DeoptInstr::kMaterializeObject: |
| 278 default: | 268 default: |
| 279 // We should not encounter these instructions when filling stack slots. | 269 // We should not encounter these instructions when filling stack slots. |
| 280 UNREACHABLE(); | 270 UNREACHABLE(); |
| 281 return false; | 271 return false; |
| 282 } | 272 } |
| 283 UNREACHABLE(); | 273 UNREACHABLE(); |
| 284 return false; | 274 return false; |
| 285 } | 275 } |
| 286 | 276 |
| 287 | |
| 288 void DeoptContext::FillDestFrame() { | 277 void DeoptContext::FillDestFrame() { |
| 289 const Code& code = Code::Handle(code_); | 278 const Code& code = Code::Handle(code_); |
| 290 const TypedData& deopt_info = TypedData::Handle(deopt_info_); | 279 const TypedData& deopt_info = TypedData::Handle(deopt_info_); |
| 291 | 280 |
| 292 GrowableArray<DeoptInstr*> deopt_instructions; | 281 GrowableArray<DeoptInstr*> deopt_instructions; |
| 293 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 282 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
| 294 ASSERT(!deopt_table.IsNull()); | 283 ASSERT(!deopt_table.IsNull()); |
| 295 DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions); | 284 DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions); |
| 296 | 285 |
| 297 const intptr_t len = deopt_instructions.length(); | 286 const intptr_t len = deopt_instructions.length(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 | 326 |
| 338 if (FLAG_trace_deoptimization_verbose) { | 327 if (FLAG_trace_deoptimization_verbose) { |
| 339 for (intptr_t i = 0; i < frame_size; i++) { | 328 for (intptr_t i = 0; i < frame_size; i++) { |
| 340 intptr_t* to_addr = GetDestFrameAddressAt(i); | 329 intptr_t* to_addr = GetDestFrameAddressAt(i); |
| 341 THR_Print("*%" Pd ". [%p] 0x%" Px " [%s]\n", i, to_addr, *to_addr, | 330 THR_Print("*%" Pd ". [%p] 0x%" Px " [%s]\n", i, to_addr, *to_addr, |
| 342 deopt_instructions[i + (len - frame_size)]->ToCString()); | 331 deopt_instructions[i + (len - frame_size)]->ToCString()); |
| 343 } | 332 } |
| 344 } | 333 } |
| 345 } | 334 } |
| 346 | 335 |
| 347 | |
| 348 intptr_t* DeoptContext::CatchEntryState(intptr_t num_vars) { | 336 intptr_t* DeoptContext::CatchEntryState(intptr_t num_vars) { |
| 349 const Code& code = Code::Handle(code_); | 337 const Code& code = Code::Handle(code_); |
| 350 const TypedData& deopt_info = TypedData::Handle(deopt_info_); | 338 const TypedData& deopt_info = TypedData::Handle(deopt_info_); |
| 351 GrowableArray<DeoptInstr*> deopt_instructions; | 339 GrowableArray<DeoptInstr*> deopt_instructions; |
| 352 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 340 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
| 353 ASSERT(!deopt_table.IsNull()); | 341 ASSERT(!deopt_table.IsNull()); |
| 354 DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions); | 342 DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions); |
| 355 | 343 |
| 356 intptr_t* state = new intptr_t[2 * num_vars + 1]; | 344 intptr_t* state = new intptr_t[2 * num_vars + 1]; |
| 357 state[0] = num_vars; | 345 state[0] = num_vars; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 373 intptr_t dest_index = i - params; | 361 intptr_t dest_index = i - params; |
| 374 #endif | 362 #endif |
| 375 CatchEntryStatePair p = instr->ToCatchEntryStatePair(this, dest_index); | 363 CatchEntryStatePair p = instr->ToCatchEntryStatePair(this, dest_index); |
| 376 state[1 + 2 * i] = p.src; | 364 state[1 + 2 * i] = p.src; |
| 377 state[2 + 2 * i] = p.dest; | 365 state[2 + 2 * i] = p.dest; |
| 378 } | 366 } |
| 379 | 367 |
| 380 return state; | 368 return state; |
| 381 } | 369 } |
| 382 | 370 |
| 383 | |
| 384 static void FillDeferredSlots(DeoptContext* deopt_context, | 371 static void FillDeferredSlots(DeoptContext* deopt_context, |
| 385 DeferredSlot** slot_list) { | 372 DeferredSlot** slot_list) { |
| 386 DeferredSlot* slot = *slot_list; | 373 DeferredSlot* slot = *slot_list; |
| 387 *slot_list = NULL; | 374 *slot_list = NULL; |
| 388 | 375 |
| 389 while (slot != NULL) { | 376 while (slot != NULL) { |
| 390 DeferredSlot* current = slot; | 377 DeferredSlot* current = slot; |
| 391 slot = slot->next(); | 378 slot = slot->next(); |
| 392 | 379 |
| 393 current->Materialize(deopt_context); | 380 current->Materialize(deopt_context); |
| 394 | 381 |
| 395 delete current; | 382 delete current; |
| 396 } | 383 } |
| 397 } | 384 } |
| 398 | 385 |
| 399 | |
| 400 // Materializes all deferred objects. Returns the total number of | 386 // Materializes all deferred objects. Returns the total number of |
| 401 // artificial arguments used during deoptimization. | 387 // artificial arguments used during deoptimization. |
| 402 intptr_t DeoptContext::MaterializeDeferredObjects() { | 388 intptr_t DeoptContext::MaterializeDeferredObjects() { |
| 403 // Populate slots with references to all unboxed "primitive" values (doubles, | 389 // Populate slots with references to all unboxed "primitive" values (doubles, |
| 404 // mints, simd) and deferred objects. Deferred objects are only allocated | 390 // mints, simd) and deferred objects. Deferred objects are only allocated |
| 405 // but not filled with data. This is done later because deferred objects | 391 // but not filled with data. This is done later because deferred objects |
| 406 // can references each other. | 392 // can references each other. |
| 407 FillDeferredSlots(this, &deferred_slots_); | 393 FillDeferredSlots(this, &deferred_slots_); |
| 408 | 394 |
| 409 // Compute total number of artificial arguments used during deoptimization. | 395 // Compute total number of artificial arguments used during deoptimization. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 431 char line_buffer[80]; | 417 char line_buffer[80]; |
| 432 OS::SNPrint(line_buffer, sizeof(line_buffer), " Line %" Pd ": '%s'", line, | 418 OS::SNPrint(line_buffer, sizeof(line_buffer), " Line %" Pd ": '%s'", line, |
| 433 line_string.ToCString()); | 419 line_string.ToCString()); |
| 434 THR_Print("%s\n", line_buffer); | 420 THR_Print("%s\n", line_buffer); |
| 435 THR_Print(" Deopt args: %" Pd "\n", deopt_arg_count); | 421 THR_Print(" Deopt args: %" Pd "\n", deopt_arg_count); |
| 436 } | 422 } |
| 437 | 423 |
| 438 return deopt_arg_count; | 424 return deopt_arg_count; |
| 439 } | 425 } |
| 440 | 426 |
| 441 | |
| 442 RawArray* DeoptContext::DestFrameAsArray() { | 427 RawArray* DeoptContext::DestFrameAsArray() { |
| 443 ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_); | 428 ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_); |
| 444 const Array& dest_array = Array::Handle(zone(), Array::New(dest_frame_size_)); | 429 const Array& dest_array = Array::Handle(zone(), Array::New(dest_frame_size_)); |
| 445 PassiveObject& obj = PassiveObject::Handle(zone()); | 430 PassiveObject& obj = PassiveObject::Handle(zone()); |
| 446 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 431 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
| 447 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); | 432 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); |
| 448 dest_array.SetAt(i, obj); | 433 dest_array.SetAt(i, obj); |
| 449 } | 434 } |
| 450 return dest_array.raw(); | 435 return dest_array.raw(); |
| 451 } | 436 } |
| 452 | 437 |
| 453 | |
| 454 // Deoptimization instruction creating return address using function and | 438 // Deoptimization instruction creating return address using function and |
| 455 // deopt-id stored at 'object_table_index'. | 439 // deopt-id stored at 'object_table_index'. |
| 456 class DeoptRetAddressInstr : public DeoptInstr { | 440 class DeoptRetAddressInstr : public DeoptInstr { |
| 457 public: | 441 public: |
| 458 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) | 442 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) |
| 459 : object_table_index_(object_table_index), deopt_id_(deopt_id) { | 443 : object_table_index_(object_table_index), deopt_id_(deopt_id) { |
| 460 ASSERT(object_table_index >= 0); | 444 ASSERT(object_table_index >= 0); |
| 461 ASSERT(deopt_id >= 0); | 445 ASSERT(deopt_id >= 0); |
| 462 } | 446 } |
| 463 | 447 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 492 }; | 476 }; |
| 493 class DeoptId | 477 class DeoptId |
| 494 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; | 478 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; |
| 495 | 479 |
| 496 const intptr_t object_table_index_; | 480 const intptr_t object_table_index_; |
| 497 const intptr_t deopt_id_; | 481 const intptr_t deopt_id_; |
| 498 | 482 |
| 499 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddressInstr); | 483 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddressInstr); |
| 500 }; | 484 }; |
| 501 | 485 |
| 502 | |
| 503 // Deoptimization instruction moving a constant stored at 'object_table_index'. | 486 // Deoptimization instruction moving a constant stored at 'object_table_index'. |
| 504 class DeoptConstantInstr : public DeoptInstr { | 487 class DeoptConstantInstr : public DeoptInstr { |
| 505 public: | 488 public: |
| 506 explicit DeoptConstantInstr(intptr_t object_table_index) | 489 explicit DeoptConstantInstr(intptr_t object_table_index) |
| 507 : object_table_index_(object_table_index) { | 490 : object_table_index_(object_table_index) { |
| 508 ASSERT(object_table_index >= 0); | 491 ASSERT(object_table_index >= 0); |
| 509 } | 492 } |
| 510 | 493 |
| 511 virtual intptr_t source_index() const { return object_table_index_; } | 494 virtual intptr_t source_index() const { return object_table_index_; } |
| 512 virtual DeoptInstr::Kind kind() const { return kConstant; } | 495 virtual DeoptInstr::Kind kind() const { return kConstant; } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 526 intptr_t dest_slot) { | 509 intptr_t dest_slot) { |
| 527 return CatchEntryStatePair::FromConstant(object_table_index_, dest_slot); | 510 return CatchEntryStatePair::FromConstant(object_table_index_, dest_slot); |
| 528 } | 511 } |
| 529 | 512 |
| 530 private: | 513 private: |
| 531 const intptr_t object_table_index_; | 514 const intptr_t object_table_index_; |
| 532 | 515 |
| 533 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | 516 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); |
| 534 }; | 517 }; |
| 535 | 518 |
| 536 | |
| 537 // Deoptimization instruction moving value from optimized frame at | 519 // Deoptimization instruction moving value from optimized frame at |
| 538 // 'source_index' to specified slots in the unoptimized frame. | 520 // 'source_index' to specified slots in the unoptimized frame. |
| 539 // 'source_index' represents the slot index of the frame (0 being | 521 // 'source_index' represents the slot index of the frame (0 being |
| 540 // first argument) and accounts for saved return address, frame | 522 // first argument) and accounts for saved return address, frame |
| 541 // pointer, pool pointer and pc marker. | 523 // pointer, pool pointer and pc marker. |
| 542 // Deoptimization instruction moving a CPU register. | 524 // Deoptimization instruction moving a CPU register. |
| 543 class DeoptWordInstr : public DeoptInstr { | 525 class DeoptWordInstr : public DeoptInstr { |
| 544 public: | 526 public: |
| 545 explicit DeoptWordInstr(intptr_t source_index) : source_(source_index) {} | 527 explicit DeoptWordInstr(intptr_t source_index) : source_(source_index) {} |
| 546 | 528 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 560 return CatchEntryStatePair::FromMove(source_.StackSlot(deopt_context), | 542 return CatchEntryStatePair::FromMove(source_.StackSlot(deopt_context), |
| 561 dest_slot); | 543 dest_slot); |
| 562 } | 544 } |
| 563 | 545 |
| 564 private: | 546 private: |
| 565 const CpuRegisterSource source_; | 547 const CpuRegisterSource source_; |
| 566 | 548 |
| 567 DISALLOW_COPY_AND_ASSIGN(DeoptWordInstr); | 549 DISALLOW_COPY_AND_ASSIGN(DeoptWordInstr); |
| 568 }; | 550 }; |
| 569 | 551 |
| 570 | |
| 571 class DeoptIntegerInstrBase : public DeoptInstr { | 552 class DeoptIntegerInstrBase : public DeoptInstr { |
| 572 public: | 553 public: |
| 573 DeoptIntegerInstrBase() {} | 554 DeoptIntegerInstrBase() {} |
| 574 | 555 |
| 575 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 556 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 576 const int64_t value = GetValue(deopt_context); | 557 const int64_t value = GetValue(deopt_context); |
| 577 if (Smi::IsValid(value)) { | 558 if (Smi::IsValid(value)) { |
| 578 *dest_addr = Smi::RawValue(static_cast<intptr_t>(value)); | 559 *dest_addr = Smi::RawValue(static_cast<intptr_t>(value)); |
| 579 } else { | 560 } else { |
| 580 *dest_addr = Smi::RawValue(0); | 561 *dest_addr = Smi::RawValue(0); |
| 581 deopt_context->DeferMintMaterialization( | 562 deopt_context->DeferMintMaterialization( |
| 582 value, reinterpret_cast<RawMint**>(dest_addr)); | 563 value, reinterpret_cast<RawMint**>(dest_addr)); |
| 583 } | 564 } |
| 584 } | 565 } |
| 585 | 566 |
| 586 virtual int64_t GetValue(DeoptContext* deopt_context) = 0; | 567 virtual int64_t GetValue(DeoptContext* deopt_context) = 0; |
| 587 | 568 |
| 588 private: | 569 private: |
| 589 DISALLOW_COPY_AND_ASSIGN(DeoptIntegerInstrBase); | 570 DISALLOW_COPY_AND_ASSIGN(DeoptIntegerInstrBase); |
| 590 }; | 571 }; |
| 591 | 572 |
| 592 | |
| 593 class DeoptMintPairInstr : public DeoptIntegerInstrBase { | 573 class DeoptMintPairInstr : public DeoptIntegerInstrBase { |
| 594 public: | 574 public: |
| 595 explicit DeoptMintPairInstr(intptr_t source_index) | 575 explicit DeoptMintPairInstr(intptr_t source_index) |
| 596 : DeoptIntegerInstrBase(), | 576 : DeoptIntegerInstrBase(), |
| 597 lo_(LoRegister::decode(source_index)), | 577 lo_(LoRegister::decode(source_index)), |
| 598 hi_(HiRegister::decode(source_index)) {} | 578 hi_(HiRegister::decode(source_index)) {} |
| 599 | 579 |
| 600 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) | 580 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) |
| 601 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} | 581 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} |
| 602 | 582 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 621 class LoRegister : public BitField<intptr_t, intptr_t, 0, kFieldWidth> {}; | 601 class LoRegister : public BitField<intptr_t, intptr_t, 0, kFieldWidth> {}; |
| 622 class HiRegister | 602 class HiRegister |
| 623 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; | 603 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; |
| 624 | 604 |
| 625 const CpuRegisterSource lo_; | 605 const CpuRegisterSource lo_; |
| 626 const CpuRegisterSource hi_; | 606 const CpuRegisterSource hi_; |
| 627 | 607 |
| 628 DISALLOW_COPY_AND_ASSIGN(DeoptMintPairInstr); | 608 DISALLOW_COPY_AND_ASSIGN(DeoptMintPairInstr); |
| 629 }; | 609 }; |
| 630 | 610 |
| 631 | |
| 632 template <DeoptInstr::Kind K, typename T> | 611 template <DeoptInstr::Kind K, typename T> |
| 633 class DeoptIntInstr : public DeoptIntegerInstrBase { | 612 class DeoptIntInstr : public DeoptIntegerInstrBase { |
| 634 public: | 613 public: |
| 635 explicit DeoptIntInstr(intptr_t source_index) | 614 explicit DeoptIntInstr(intptr_t source_index) |
| 636 : DeoptIntegerInstrBase(), source_(source_index) {} | 615 : DeoptIntegerInstrBase(), source_(source_index) {} |
| 637 | 616 |
| 638 explicit DeoptIntInstr(const CpuRegisterSource& source) | 617 explicit DeoptIntInstr(const CpuRegisterSource& source) |
| 639 : DeoptIntegerInstrBase(), source_(source) {} | 618 : DeoptIntegerInstrBase(), source_(source) {} |
| 640 | 619 |
| 641 virtual intptr_t source_index() const { return source_.source_index(); } | 620 virtual intptr_t source_index() const { return source_.source_index(); } |
| 642 virtual DeoptInstr::Kind kind() const { return K; } | 621 virtual DeoptInstr::Kind kind() const { return K; } |
| 643 | 622 |
| 644 virtual const char* ArgumentsToCString() const { return source_.ToCString(); } | 623 virtual const char* ArgumentsToCString() const { return source_.ToCString(); } |
| 645 | 624 |
| 646 virtual int64_t GetValue(DeoptContext* deopt_context) { | 625 virtual int64_t GetValue(DeoptContext* deopt_context) { |
| 647 return static_cast<int64_t>(source_.Value<T>(deopt_context)); | 626 return static_cast<int64_t>(source_.Value<T>(deopt_context)); |
| 648 } | 627 } |
| 649 | 628 |
| 650 private: | 629 private: |
| 651 const CpuRegisterSource source_; | 630 const CpuRegisterSource source_; |
| 652 | 631 |
| 653 DISALLOW_COPY_AND_ASSIGN(DeoptIntInstr); | 632 DISALLOW_COPY_AND_ASSIGN(DeoptIntInstr); |
| 654 }; | 633 }; |
| 655 | 634 |
| 656 | |
| 657 typedef DeoptIntInstr<DeoptInstr::kUint32, uint32_t> DeoptUint32Instr; | 635 typedef DeoptIntInstr<DeoptInstr::kUint32, uint32_t> DeoptUint32Instr; |
| 658 typedef DeoptIntInstr<DeoptInstr::kInt32, int32_t> DeoptInt32Instr; | 636 typedef DeoptIntInstr<DeoptInstr::kInt32, int32_t> DeoptInt32Instr; |
| 659 typedef DeoptIntInstr<DeoptInstr::kMint, int64_t> DeoptMintInstr; | 637 typedef DeoptIntInstr<DeoptInstr::kMint, int64_t> DeoptMintInstr; |
| 660 | 638 |
| 661 | |
| 662 template <DeoptInstr::Kind K, typename Type, typename RawObjectType> | 639 template <DeoptInstr::Kind K, typename Type, typename RawObjectType> |
| 663 class DeoptFpuInstr : public DeoptInstr { | 640 class DeoptFpuInstr : public DeoptInstr { |
| 664 public: | 641 public: |
| 665 explicit DeoptFpuInstr(intptr_t source_index) : source_(source_index) {} | 642 explicit DeoptFpuInstr(intptr_t source_index) : source_(source_index) {} |
| 666 | 643 |
| 667 explicit DeoptFpuInstr(const FpuRegisterSource& source) : source_(source) {} | 644 explicit DeoptFpuInstr(const FpuRegisterSource& source) : source_(source) {} |
| 668 | 645 |
| 669 virtual intptr_t source_index() const { return source_.source_index(); } | 646 virtual intptr_t source_index() const { return source_.source_index(); } |
| 670 virtual DeoptInstr::Kind kind() const { return K; } | 647 virtual DeoptInstr::Kind kind() const { return K; } |
| 671 | 648 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 StubCode::FrameAwaitingMaterialization_entry()->code(); | 710 StubCode::FrameAwaitingMaterialization_entry()->code(); |
| 734 deopt_context->DeferPcMarkerMaterialization(object_table_index_, dest_addr); | 711 deopt_context->DeferPcMarkerMaterialization(object_table_index_, dest_addr); |
| 735 } | 712 } |
| 736 | 713 |
| 737 private: | 714 private: |
| 738 intptr_t object_table_index_; | 715 intptr_t object_table_index_; |
| 739 | 716 |
| 740 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); | 717 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); |
| 741 }; | 718 }; |
| 742 | 719 |
| 743 | |
| 744 // Deoptimization instruction creating a pool pointer for the code of | 720 // Deoptimization instruction creating a pool pointer for the code of |
| 745 // function at 'object_table_index'. | 721 // function at 'object_table_index'. |
| 746 class DeoptPpInstr : public DeoptInstr { | 722 class DeoptPpInstr : public DeoptInstr { |
| 747 public: | 723 public: |
| 748 explicit DeoptPpInstr(intptr_t object_table_index) | 724 explicit DeoptPpInstr(intptr_t object_table_index) |
| 749 : object_table_index_(object_table_index) { | 725 : object_table_index_(object_table_index) { |
| 750 ASSERT(object_table_index >= 0); | 726 ASSERT(object_table_index >= 0); |
| 751 } | 727 } |
| 752 | 728 |
| 753 virtual intptr_t source_index() const { return object_table_index_; } | 729 virtual intptr_t source_index() const { return object_table_index_; } |
| 754 virtual DeoptInstr::Kind kind() const { return kPp; } | 730 virtual DeoptInstr::Kind kind() const { return kPp; } |
| 755 | 731 |
| 756 virtual const char* ArgumentsToCString() const { | 732 virtual const char* ArgumentsToCString() const { |
| 757 return Thread::Current()->zone()->PrintToString("%" Pd "", | 733 return Thread::Current()->zone()->PrintToString("%" Pd "", |
| 758 object_table_index_); | 734 object_table_index_); |
| 759 } | 735 } |
| 760 | 736 |
| 761 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 737 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 762 *dest_addr = Smi::RawValue(0); | 738 *dest_addr = Smi::RawValue(0); |
| 763 deopt_context->DeferPpMaterialization( | 739 deopt_context->DeferPpMaterialization( |
| 764 object_table_index_, reinterpret_cast<RawObject**>(dest_addr)); | 740 object_table_index_, reinterpret_cast<RawObject**>(dest_addr)); |
| 765 } | 741 } |
| 766 | 742 |
| 767 private: | 743 private: |
| 768 intptr_t object_table_index_; | 744 intptr_t object_table_index_; |
| 769 | 745 |
| 770 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); | 746 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); |
| 771 }; | 747 }; |
| 772 | 748 |
| 773 | |
| 774 // Deoptimization instruction copying the caller saved FP from optimized frame. | 749 // Deoptimization instruction copying the caller saved FP from optimized frame. |
| 775 class DeoptCallerFpInstr : public DeoptInstr { | 750 class DeoptCallerFpInstr : public DeoptInstr { |
| 776 public: | 751 public: |
| 777 DeoptCallerFpInstr() {} | 752 DeoptCallerFpInstr() {} |
| 778 | 753 |
| 779 virtual intptr_t source_index() const { return 0; } | 754 virtual intptr_t source_index() const { return 0; } |
| 780 virtual DeoptInstr::Kind kind() const { return kCallerFp; } | 755 virtual DeoptInstr::Kind kind() const { return kCallerFp; } |
| 781 | 756 |
| 782 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 757 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 783 *dest_addr = deopt_context->GetCallerFp(); | 758 *dest_addr = deopt_context->GetCallerFp(); |
| 784 deopt_context->SetCallerFp( | 759 deopt_context->SetCallerFp( |
| 785 reinterpret_cast<intptr_t>(dest_addr - kSavedCallerFpSlotFromFp)); | 760 reinterpret_cast<intptr_t>(dest_addr - kSavedCallerFpSlotFromFp)); |
| 786 } | 761 } |
| 787 | 762 |
| 788 private: | 763 private: |
| 789 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | 764 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); |
| 790 }; | 765 }; |
| 791 | 766 |
| 792 | |
| 793 // Deoptimization instruction copying the caller saved PP from optimized frame. | 767 // Deoptimization instruction copying the caller saved PP from optimized frame. |
| 794 class DeoptCallerPpInstr : public DeoptInstr { | 768 class DeoptCallerPpInstr : public DeoptInstr { |
| 795 public: | 769 public: |
| 796 DeoptCallerPpInstr() {} | 770 DeoptCallerPpInstr() {} |
| 797 | 771 |
| 798 virtual intptr_t source_index() const { return 0; } | 772 virtual intptr_t source_index() const { return 0; } |
| 799 virtual DeoptInstr::Kind kind() const { return kCallerPp; } | 773 virtual DeoptInstr::Kind kind() const { return kCallerPp; } |
| 800 | 774 |
| 801 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 775 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 802 *dest_addr = deopt_context->GetSourcePp(); | 776 *dest_addr = deopt_context->GetSourcePp(); |
| 803 } | 777 } |
| 804 | 778 |
| 805 private: | 779 private: |
| 806 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPpInstr); | 780 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPpInstr); |
| 807 }; | 781 }; |
| 808 | 782 |
| 809 | |
| 810 // Deoptimization instruction copying the caller return address from optimized | 783 // Deoptimization instruction copying the caller return address from optimized |
| 811 // frame. | 784 // frame. |
| 812 class DeoptCallerPcInstr : public DeoptInstr { | 785 class DeoptCallerPcInstr : public DeoptInstr { |
| 813 public: | 786 public: |
| 814 DeoptCallerPcInstr() {} | 787 DeoptCallerPcInstr() {} |
| 815 | 788 |
| 816 virtual intptr_t source_index() const { return 0; } | 789 virtual intptr_t source_index() const { return 0; } |
| 817 virtual DeoptInstr::Kind kind() const { return kCallerPc; } | 790 virtual DeoptInstr::Kind kind() const { return kCallerPc; } |
| 818 | 791 |
| 819 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 792 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 820 *dest_addr = deopt_context->GetSourcePc(); | 793 *dest_addr = deopt_context->GetSourcePc(); |
| 821 } | 794 } |
| 822 | 795 |
| 823 private: | 796 private: |
| 824 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 797 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
| 825 }; | 798 }; |
| 826 | 799 |
| 827 | |
| 828 // Write reference to a materialized object with the given index into the | 800 // Write reference to a materialized object with the given index into the |
| 829 // stack slot. | 801 // stack slot. |
| 830 class DeoptMaterializedObjectRefInstr : public DeoptInstr { | 802 class DeoptMaterializedObjectRefInstr : public DeoptInstr { |
| 831 public: | 803 public: |
| 832 explicit DeoptMaterializedObjectRefInstr(intptr_t index) : index_(index) { | 804 explicit DeoptMaterializedObjectRefInstr(intptr_t index) : index_(index) { |
| 833 ASSERT(index >= 0); | 805 ASSERT(index >= 0); |
| 834 } | 806 } |
| 835 | 807 |
| 836 virtual intptr_t source_index() const { return index_; } | 808 virtual intptr_t source_index() const { return index_; } |
| 837 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } | 809 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } |
| 838 | 810 |
| 839 virtual const char* ArgumentsToCString() const { | 811 virtual const char* ArgumentsToCString() const { |
| 840 return Thread::Current()->zone()->PrintToString("#%" Pd "", index_); | 812 return Thread::Current()->zone()->PrintToString("#%" Pd "", index_); |
| 841 } | 813 } |
| 842 | 814 |
| 843 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 815 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 844 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | 816 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 845 deopt_context->DeferMaterializedObjectRef(index_, dest_addr); | 817 deopt_context->DeferMaterializedObjectRef(index_, dest_addr); |
| 846 } | 818 } |
| 847 | 819 |
| 848 private: | 820 private: |
| 849 intptr_t index_; | 821 intptr_t index_; |
| 850 | 822 |
| 851 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); | 823 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); |
| 852 }; | 824 }; |
| 853 | 825 |
| 854 | |
| 855 // Materialize object with the given number of fields. | 826 // Materialize object with the given number of fields. |
| 856 // Arguments for materialization (class and field-value pairs) are pushed | 827 // Arguments for materialization (class and field-value pairs) are pushed |
| 857 // to the expression stack of the bottom-most frame. | 828 // to the expression stack of the bottom-most frame. |
| 858 class DeoptMaterializeObjectInstr : public DeoptInstr { | 829 class DeoptMaterializeObjectInstr : public DeoptInstr { |
| 859 public: | 830 public: |
| 860 explicit DeoptMaterializeObjectInstr(intptr_t field_count) | 831 explicit DeoptMaterializeObjectInstr(intptr_t field_count) |
| 861 : field_count_(field_count) { | 832 : field_count_(field_count) { |
| 862 ASSERT(field_count >= 0); | 833 ASSERT(field_count >= 0); |
| 863 } | 834 } |
| 864 | 835 |
| 865 virtual intptr_t source_index() const { return field_count_; } | 836 virtual intptr_t source_index() const { return field_count_; } |
| 866 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } | 837 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } |
| 867 | 838 |
| 868 virtual const char* ArgumentsToCString() const { | 839 virtual const char* ArgumentsToCString() const { |
| 869 return Thread::Current()->zone()->PrintToString("%" Pd "", field_count_); | 840 return Thread::Current()->zone()->PrintToString("%" Pd "", field_count_); |
| 870 } | 841 } |
| 871 | 842 |
| 872 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 843 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 873 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. | 844 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. |
| 874 UNREACHABLE(); | 845 UNREACHABLE(); |
| 875 } | 846 } |
| 876 | 847 |
| 877 private: | 848 private: |
| 878 intptr_t field_count_; | 849 intptr_t field_count_; |
| 879 | 850 |
| 880 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); | 851 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); |
| 881 }; | 852 }; |
| 882 | 853 |
| 883 | |
| 884 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, | 854 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, |
| 885 const ObjectPool& object_table, | 855 const ObjectPool& object_table, |
| 886 Code* code) { | 856 Code* code) { |
| 887 ASSERT(instr->kind() == kRetAddress); | 857 ASSERT(instr->kind() == kRetAddress); |
| 888 DeoptRetAddressInstr* ret_address_instr = | 858 DeoptRetAddressInstr* ret_address_instr = |
| 889 static_cast<DeoptRetAddressInstr*>(instr); | 859 static_cast<DeoptRetAddressInstr*>(instr); |
| 890 // The following assert may trigger when displaying a backtrace | 860 // The following assert may trigger when displaying a backtrace |
| 891 // from the simulator. | 861 // from the simulator. |
| 892 ASSERT(Thread::IsDeoptAfter(ret_address_instr->deopt_id())); | 862 ASSERT(Thread::IsDeoptAfter(ret_address_instr->deopt_id())); |
| 893 ASSERT(!object_table.IsNull()); | 863 ASSERT(!object_table.IsNull()); |
| 894 Thread* thread = Thread::Current(); | 864 Thread* thread = Thread::Current(); |
| 895 Zone* zone = thread->zone(); | 865 Zone* zone = thread->zone(); |
| 896 Function& function = Function::Handle(zone); | 866 Function& function = Function::Handle(zone); |
| 897 function ^= object_table.ObjectAt(ret_address_instr->object_table_index()); | 867 function ^= object_table.ObjectAt(ret_address_instr->object_table_index()); |
| 898 ASSERT(code != NULL); | 868 ASSERT(code != NULL); |
| 899 const Error& error = | 869 const Error& error = |
| 900 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); | 870 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); |
| 901 if (!error.IsNull()) { | 871 if (!error.IsNull()) { |
| 902 Exceptions::PropagateError(error); | 872 Exceptions::PropagateError(error); |
| 903 } | 873 } |
| 904 *code ^= function.unoptimized_code(); | 874 *code ^= function.unoptimized_code(); |
| 905 ASSERT(!code->IsNull()); | 875 ASSERT(!code->IsNull()); |
| 906 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), | 876 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), |
| 907 RawPcDescriptors::kDeopt); | 877 RawPcDescriptors::kDeopt); |
| 908 ASSERT(res != 0); | 878 ASSERT(res != 0); |
| 909 return res; | 879 return res; |
| 910 } | 880 } |
| 911 | 881 |
| 912 | |
| 913 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { | 882 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { |
| 914 Kind kind = static_cast<Kind>(kind_as_int); | 883 Kind kind = static_cast<Kind>(kind_as_int); |
| 915 switch (kind) { | 884 switch (kind) { |
| 916 case kWord: | 885 case kWord: |
| 917 return new DeoptWordInstr(source_index); | 886 return new DeoptWordInstr(source_index); |
| 918 case kDouble: | 887 case kDouble: |
| 919 return new DeoptDoubleInstr(source_index); | 888 return new DeoptDoubleInstr(source_index); |
| 920 case kMint: | 889 case kMint: |
| 921 return new DeoptMintInstr(source_index); | 890 return new DeoptMintInstr(source_index); |
| 922 case kMintPair: | 891 case kMintPair: |
| (...skipping 24 matching lines...) Expand all Loading... |
| 947 return new DeoptCallerPcInstr(); | 916 return new DeoptCallerPcInstr(); |
| 948 case kMaterializedObjectRef: | 917 case kMaterializedObjectRef: |
| 949 return new DeoptMaterializedObjectRefInstr(source_index); | 918 return new DeoptMaterializedObjectRefInstr(source_index); |
| 950 case kMaterializeObject: | 919 case kMaterializeObject: |
| 951 return new DeoptMaterializeObjectInstr(source_index); | 920 return new DeoptMaterializeObjectInstr(source_index); |
| 952 } | 921 } |
| 953 UNREACHABLE(); | 922 UNREACHABLE(); |
| 954 return NULL; | 923 return NULL; |
| 955 } | 924 } |
| 956 | 925 |
| 957 | |
| 958 const char* DeoptInstr::KindToCString(Kind kind) { | 926 const char* DeoptInstr::KindToCString(Kind kind) { |
| 959 switch (kind) { | 927 switch (kind) { |
| 960 case kWord: | 928 case kWord: |
| 961 return "word"; | 929 return "word"; |
| 962 case kDouble: | 930 case kDouble: |
| 963 return "double"; | 931 return "double"; |
| 964 case kMint: | 932 case kMint: |
| 965 case kMintPair: | 933 case kMintPair: |
| 966 return "mint"; | 934 return "mint"; |
| 967 case kInt32: | 935 case kInt32: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 990 return "callerpc"; | 958 return "callerpc"; |
| 991 case kMaterializedObjectRef: | 959 case kMaterializedObjectRef: |
| 992 return "ref"; | 960 return "ref"; |
| 993 case kMaterializeObject: | 961 case kMaterializeObject: |
| 994 return "mat"; | 962 return "mat"; |
| 995 } | 963 } |
| 996 UNREACHABLE(); | 964 UNREACHABLE(); |
| 997 return NULL; | 965 return NULL; |
| 998 } | 966 } |
| 999 | 967 |
| 1000 | |
| 1001 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { | 968 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { |
| 1002 public: | 969 public: |
| 1003 // Construct the root node representing the implicit "shared" terminator | 970 // Construct the root node representing the implicit "shared" terminator |
| 1004 // at the end of each deopt info. | 971 // at the end of each deopt info. |
| 1005 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) {} | 972 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) {} |
| 1006 | 973 |
| 1007 // Construct a node representing a written instruction. | 974 // Construct a node representing a written instruction. |
| 1008 TrieNode(DeoptInstr* instruction, intptr_t info_number) | 975 TrieNode(DeoptInstr* instruction, intptr_t info_number) |
| 1009 : instruction_(instruction), info_number_(info_number), children_(4) {} | 976 : instruction_(instruction), info_number_(info_number), children_(4) {} |
| 1010 | 977 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1022 return NULL; | 989 return NULL; |
| 1023 } | 990 } |
| 1024 | 991 |
| 1025 private: | 992 private: |
| 1026 const DeoptInstr* instruction_; // Instruction that was written. | 993 const DeoptInstr* instruction_; // Instruction that was written. |
| 1027 const intptr_t info_number_; // Index of the deopt info it was written to. | 994 const intptr_t info_number_; // Index of the deopt info it was written to. |
| 1028 | 995 |
| 1029 GrowableArray<TrieNode*> children_; | 996 GrowableArray<TrieNode*> children_; |
| 1030 }; | 997 }; |
| 1031 | 998 |
| 1032 | |
| 1033 DeoptInfoBuilder::DeoptInfoBuilder(Zone* zone, | 999 DeoptInfoBuilder::DeoptInfoBuilder(Zone* zone, |
| 1034 const intptr_t num_args, | 1000 const intptr_t num_args, |
| 1035 Assembler* assembler) | 1001 Assembler* assembler) |
| 1036 : zone_(zone), | 1002 : zone_(zone), |
| 1037 instructions_(), | 1003 instructions_(), |
| 1038 num_args_(num_args), | 1004 num_args_(num_args), |
| 1039 assembler_(assembler), | 1005 assembler_(assembler), |
| 1040 trie_root_(new (zone) TrieNode()), | 1006 trie_root_(new (zone) TrieNode()), |
| 1041 current_info_number_(0), | 1007 current_info_number_(0), |
| 1042 frame_start_(-1), | 1008 frame_start_(-1), |
| 1043 materializations_() {} | 1009 materializations_() {} |
| 1044 | 1010 |
| 1045 | |
| 1046 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { | 1011 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { |
| 1047 return assembler_->object_pool_wrapper().FindObject(obj); | 1012 return assembler_->object_pool_wrapper().FindObject(obj); |
| 1048 } | 1013 } |
| 1049 | 1014 |
| 1050 | |
| 1051 intptr_t DeoptInfoBuilder::CalculateStackIndex( | 1015 intptr_t DeoptInfoBuilder::CalculateStackIndex( |
| 1052 const Location& source_loc) const { | 1016 const Location& source_loc) const { |
| 1053 return source_loc.stack_index() < 0 | 1017 return source_loc.stack_index() < 0 |
| 1054 ? source_loc.stack_index() + num_args_ | 1018 ? source_loc.stack_index() + num_args_ |
| 1055 : source_loc.stack_index() + num_args_ + kDartFrameFixedSize; | 1019 : source_loc.stack_index() + num_args_ + kDartFrameFixedSize; |
| 1056 } | 1020 } |
| 1057 | 1021 |
| 1058 | |
| 1059 CpuRegisterSource DeoptInfoBuilder::ToCpuRegisterSource(const Location& loc) { | 1022 CpuRegisterSource DeoptInfoBuilder::ToCpuRegisterSource(const Location& loc) { |
| 1060 if (loc.IsRegister()) { | 1023 if (loc.IsRegister()) { |
| 1061 return CpuRegisterSource(CpuRegisterSource::kRegister, loc.reg()); | 1024 return CpuRegisterSource(CpuRegisterSource::kRegister, loc.reg()); |
| 1062 } else { | 1025 } else { |
| 1063 ASSERT(loc.IsStackSlot()); | 1026 ASSERT(loc.IsStackSlot()); |
| 1064 return CpuRegisterSource(CpuRegisterSource::kStackSlot, | 1027 return CpuRegisterSource(CpuRegisterSource::kStackSlot, |
| 1065 CalculateStackIndex(loc)); | 1028 CalculateStackIndex(loc)); |
| 1066 } | 1029 } |
| 1067 } | 1030 } |
| 1068 | 1031 |
| 1069 | |
| 1070 FpuRegisterSource DeoptInfoBuilder::ToFpuRegisterSource( | 1032 FpuRegisterSource DeoptInfoBuilder::ToFpuRegisterSource( |
| 1071 const Location& loc, | 1033 const Location& loc, |
| 1072 Location::Kind stack_slot_kind) { | 1034 Location::Kind stack_slot_kind) { |
| 1073 if (loc.IsFpuRegister()) { | 1035 if (loc.IsFpuRegister()) { |
| 1074 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); | 1036 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); |
| 1075 #if defined(TARGET_ARCH_DBC) | 1037 #if defined(TARGET_ARCH_DBC) |
| 1076 } else if (loc.IsRegister()) { | 1038 } else if (loc.IsRegister()) { |
| 1077 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg()); | 1039 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg()); |
| 1078 #endif | 1040 #endif |
| 1079 } else { | 1041 } else { |
| 1080 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || | 1042 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || |
| 1081 (stack_slot_kind == Location::kDoubleStackSlot)); | 1043 (stack_slot_kind == Location::kDoubleStackSlot)); |
| 1082 ASSERT(loc.kind() == stack_slot_kind); | 1044 ASSERT(loc.kind() == stack_slot_kind); |
| 1083 return FpuRegisterSource(FpuRegisterSource::kStackSlot, | 1045 return FpuRegisterSource(FpuRegisterSource::kStackSlot, |
| 1084 CalculateStackIndex(loc)); | 1046 CalculateStackIndex(loc)); |
| 1085 } | 1047 } |
| 1086 } | 1048 } |
| 1087 | 1049 |
| 1088 void DeoptInfoBuilder::AddReturnAddress(const Function& function, | 1050 void DeoptInfoBuilder::AddReturnAddress(const Function& function, |
| 1089 intptr_t deopt_id, | 1051 intptr_t deopt_id, |
| 1090 intptr_t dest_index) { | 1052 intptr_t dest_index) { |
| 1091 const intptr_t object_table_index = FindOrAddObjectInTable(function); | 1053 const intptr_t object_table_index = FindOrAddObjectInTable(function); |
| 1092 ASSERT(dest_index == FrameSize()); | 1054 ASSERT(dest_index == FrameSize()); |
| 1093 instructions_.Add(new (zone()) | 1055 instructions_.Add(new (zone()) |
| 1094 DeoptRetAddressInstr(object_table_index, deopt_id)); | 1056 DeoptRetAddressInstr(object_table_index, deopt_id)); |
| 1095 } | 1057 } |
| 1096 | 1058 |
| 1097 | |
| 1098 void DeoptInfoBuilder::AddPcMarker(const Function& function, | 1059 void DeoptInfoBuilder::AddPcMarker(const Function& function, |
| 1099 intptr_t dest_index) { | 1060 intptr_t dest_index) { |
| 1100 intptr_t object_table_index = FindOrAddObjectInTable(function); | 1061 intptr_t object_table_index = FindOrAddObjectInTable(function); |
| 1101 ASSERT(dest_index == FrameSize()); | 1062 ASSERT(dest_index == FrameSize()); |
| 1102 instructions_.Add(new (zone()) DeoptPcMarkerInstr(object_table_index)); | 1063 instructions_.Add(new (zone()) DeoptPcMarkerInstr(object_table_index)); |
| 1103 } | 1064 } |
| 1104 | 1065 |
| 1105 | |
| 1106 void DeoptInfoBuilder::AddPp(const Function& function, intptr_t dest_index) { | 1066 void DeoptInfoBuilder::AddPp(const Function& function, intptr_t dest_index) { |
| 1107 intptr_t object_table_index = FindOrAddObjectInTable(function); | 1067 intptr_t object_table_index = FindOrAddObjectInTable(function); |
| 1108 ASSERT(dest_index == FrameSize()); | 1068 ASSERT(dest_index == FrameSize()); |
| 1109 instructions_.Add(new (zone()) DeoptPpInstr(object_table_index)); | 1069 instructions_.Add(new (zone()) DeoptPpInstr(object_table_index)); |
| 1110 } | 1070 } |
| 1111 | 1071 |
| 1112 | |
| 1113 void DeoptInfoBuilder::AddCopy(Value* value, | 1072 void DeoptInfoBuilder::AddCopy(Value* value, |
| 1114 const Location& source_loc, | 1073 const Location& source_loc, |
| 1115 const intptr_t dest_index) { | 1074 const intptr_t dest_index) { |
| 1116 DeoptInstr* deopt_instr = NULL; | 1075 DeoptInstr* deopt_instr = NULL; |
| 1117 if (source_loc.IsConstant()) { | 1076 if (source_loc.IsConstant()) { |
| 1118 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); | 1077 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); |
| 1119 deopt_instr = new (zone()) DeoptConstantInstr(object_table_index); | 1078 deopt_instr = new (zone()) DeoptConstantInstr(object_table_index); |
| 1120 } else if (source_loc.IsInvalid() && | 1079 } else if (source_loc.IsInvalid() && |
| 1121 value->definition()->IsMaterializeObject()) { | 1080 value->definition()->IsMaterializeObject()) { |
| 1122 const intptr_t index = | 1081 const intptr_t index = |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1176 default: | 1135 default: |
| 1177 UNREACHABLE(); | 1136 UNREACHABLE(); |
| 1178 break; | 1137 break; |
| 1179 } | 1138 } |
| 1180 } | 1139 } |
| 1181 ASSERT(dest_index == FrameSize()); | 1140 ASSERT(dest_index == FrameSize()); |
| 1182 ASSERT(deopt_instr != NULL); | 1141 ASSERT(deopt_instr != NULL); |
| 1183 instructions_.Add(deopt_instr); | 1142 instructions_.Add(deopt_instr); |
| 1184 } | 1143 } |
| 1185 | 1144 |
| 1186 | |
| 1187 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { | 1145 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { |
| 1188 ASSERT(dest_index == FrameSize()); | 1146 ASSERT(dest_index == FrameSize()); |
| 1189 instructions_.Add(new (zone()) DeoptCallerFpInstr()); | 1147 instructions_.Add(new (zone()) DeoptCallerFpInstr()); |
| 1190 } | 1148 } |
| 1191 | 1149 |
| 1192 | |
| 1193 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { | 1150 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { |
| 1194 ASSERT(dest_index == FrameSize()); | 1151 ASSERT(dest_index == FrameSize()); |
| 1195 instructions_.Add(new (zone()) DeoptCallerPpInstr()); | 1152 instructions_.Add(new (zone()) DeoptCallerPpInstr()); |
| 1196 } | 1153 } |
| 1197 | 1154 |
| 1198 | |
| 1199 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { | 1155 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { |
| 1200 ASSERT(dest_index == FrameSize()); | 1156 ASSERT(dest_index == FrameSize()); |
| 1201 instructions_.Add(new (zone()) DeoptCallerPcInstr()); | 1157 instructions_.Add(new (zone()) DeoptCallerPcInstr()); |
| 1202 } | 1158 } |
| 1203 | 1159 |
| 1204 | |
| 1205 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { | 1160 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { |
| 1206 ASSERT(dest_index == FrameSize()); | 1161 ASSERT(dest_index == FrameSize()); |
| 1207 intptr_t object_table_index = FindOrAddObjectInTable(obj); | 1162 intptr_t object_table_index = FindOrAddObjectInTable(obj); |
| 1208 instructions_.Add(new (zone()) DeoptConstantInstr(object_table_index)); | 1163 instructions_.Add(new (zone()) DeoptConstantInstr(object_table_index)); |
| 1209 } | 1164 } |
| 1210 | 1165 |
| 1211 | |
| 1212 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { | 1166 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { |
| 1213 const intptr_t index = FindMaterialization(mat); | 1167 const intptr_t index = FindMaterialization(mat); |
| 1214 if (index >= 0) { | 1168 if (index >= 0) { |
| 1215 return; // Already added. | 1169 return; // Already added. |
| 1216 } | 1170 } |
| 1217 materializations_.Add(mat); | 1171 materializations_.Add(mat); |
| 1218 | 1172 |
| 1219 // Count initialized fields and emit kMaterializeObject instruction. | 1173 // Count initialized fields and emit kMaterializeObject instruction. |
| 1220 // There is no need to write nulls into fields because object is null | 1174 // There is no need to write nulls into fields because object is null |
| 1221 // initialized by default. | 1175 // initialized by default. |
| 1222 intptr_t non_null_fields = 0; | 1176 intptr_t non_null_fields = 0; |
| 1223 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1177 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 1224 if (!mat->InputAt(i)->BindsToConstantNull()) { | 1178 if (!mat->InputAt(i)->BindsToConstantNull()) { |
| 1225 non_null_fields++; | 1179 non_null_fields++; |
| 1226 } | 1180 } |
| 1227 } | 1181 } |
| 1228 | 1182 |
| 1229 instructions_.Add(new (zone()) DeoptMaterializeObjectInstr(non_null_fields)); | 1183 instructions_.Add(new (zone()) DeoptMaterializeObjectInstr(non_null_fields)); |
| 1230 | 1184 |
| 1231 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1185 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 1232 MaterializeObjectInstr* nested_mat = | 1186 MaterializeObjectInstr* nested_mat = |
| 1233 mat->InputAt(i)->definition()->AsMaterializeObject(); | 1187 mat->InputAt(i)->definition()->AsMaterializeObject(); |
| 1234 if (nested_mat != NULL) { | 1188 if (nested_mat != NULL) { |
| 1235 AddMaterialization(nested_mat); | 1189 AddMaterialization(nested_mat); |
| 1236 } | 1190 } |
| 1237 } | 1191 } |
| 1238 } | 1192 } |
| 1239 | 1193 |
| 1240 | |
| 1241 intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) { | 1194 intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) { |
| 1242 ASSERT(dest_index == kDartFrameFixedSize); | 1195 ASSERT(dest_index == kDartFrameFixedSize); |
| 1243 for (intptr_t i = 0; i < materializations_.length(); i++) { | 1196 for (intptr_t i = 0; i < materializations_.length(); i++) { |
| 1244 MaterializeObjectInstr* mat = materializations_[i]; | 1197 MaterializeObjectInstr* mat = materializations_[i]; |
| 1245 // Class of the instance to allocate. | 1198 // Class of the instance to allocate. |
| 1246 AddConstant(mat->cls(), dest_index++); | 1199 AddConstant(mat->cls(), dest_index++); |
| 1247 AddConstant(Smi::ZoneHandle(Smi::New(mat->num_variables())), dest_index++); | 1200 AddConstant(Smi::ZoneHandle(Smi::New(mat->num_variables())), dest_index++); |
| 1248 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1201 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 1249 if (!mat->InputAt(i)->BindsToConstantNull()) { | 1202 if (!mat->InputAt(i)->BindsToConstantNull()) { |
| 1250 // Emit offset-value pair. | 1203 // Emit offset-value pair. |
| 1251 AddConstant(Smi::ZoneHandle(Smi::New(mat->FieldOffsetAt(i))), | 1204 AddConstant(Smi::ZoneHandle(Smi::New(mat->FieldOffsetAt(i))), |
| 1252 dest_index++); | 1205 dest_index++); |
| 1253 AddCopy(mat->InputAt(i), mat->LocationAt(i), dest_index++); | 1206 AddCopy(mat->InputAt(i), mat->LocationAt(i), dest_index++); |
| 1254 } | 1207 } |
| 1255 } | 1208 } |
| 1256 } | 1209 } |
| 1257 return dest_index; | 1210 return dest_index; |
| 1258 } | 1211 } |
| 1259 | 1212 |
| 1260 | |
| 1261 intptr_t DeoptInfoBuilder::FindMaterialization( | 1213 intptr_t DeoptInfoBuilder::FindMaterialization( |
| 1262 MaterializeObjectInstr* mat) const { | 1214 MaterializeObjectInstr* mat) const { |
| 1263 for (intptr_t i = 0; i < materializations_.length(); i++) { | 1215 for (intptr_t i = 0; i < materializations_.length(); i++) { |
| 1264 if (materializations_[i] == mat) { | 1216 if (materializations_[i] == mat) { |
| 1265 return i; | 1217 return i; |
| 1266 } | 1218 } |
| 1267 } | 1219 } |
| 1268 return -1; | 1220 return -1; |
| 1269 } | 1221 } |
| 1270 | 1222 |
| 1271 | |
| 1272 static uint8_t* ZoneReAlloc(uint8_t* ptr, | 1223 static uint8_t* ZoneReAlloc(uint8_t* ptr, |
| 1273 intptr_t old_size, | 1224 intptr_t old_size, |
| 1274 intptr_t new_size) { | 1225 intptr_t new_size) { |
| 1275 return Thread::Current()->zone()->Realloc<uint8_t>(ptr, old_size, new_size); | 1226 return Thread::Current()->zone()->Realloc<uint8_t>(ptr, old_size, new_size); |
| 1276 } | 1227 } |
| 1277 | 1228 |
| 1278 | |
| 1279 RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) { | 1229 RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) { |
| 1280 intptr_t length = instructions_.length(); | 1230 intptr_t length = instructions_.length(); |
| 1281 | 1231 |
| 1282 // Count the number of instructions that are a shared suffix of some deopt | 1232 // Count the number of instructions that are a shared suffix of some deopt |
| 1283 // info already written. | 1233 // info already written. |
| 1284 TrieNode* suffix = trie_root_; | 1234 TrieNode* suffix = trie_root_; |
| 1285 intptr_t suffix_length = 0; | 1235 intptr_t suffix_length = 0; |
| 1286 if (FLAG_compress_deopt_info) { | 1236 if (FLAG_compress_deopt_info) { |
| 1287 for (intptr_t i = length - 1; i >= 0; --i) { | 1237 for (intptr_t i = length - 1; i >= 0; --i) { |
| 1288 TrieNode* node = suffix->FindChild(*instructions_[i]); | 1238 TrieNode* node = suffix->FindChild(*instructions_[i]); |
| 1289 if (node == NULL) break; | 1239 if (node == NULL) break; |
| 1290 suffix = node; | 1240 suffix = node; |
| 1291 ++suffix_length; | 1241 ++suffix_length; |
| 1292 } | 1242 } |
| 1293 } | 1243 } |
| 1294 | 1244 |
| 1295 | |
| 1296 // Allocate space for the translation. If the shared suffix is longer | 1245 // Allocate space for the translation. If the shared suffix is longer |
| 1297 // than one instruction, we replace it with a single suffix instruction. | 1246 // than one instruction, we replace it with a single suffix instruction. |
| 1298 const bool use_suffix = suffix_length > 1; | 1247 const bool use_suffix = suffix_length > 1; |
| 1299 if (use_suffix) { | 1248 if (use_suffix) { |
| 1300 length -= (suffix_length - 1); | 1249 length -= (suffix_length - 1); |
| 1301 } | 1250 } |
| 1302 | 1251 |
| 1303 uint8_t* buffer; | 1252 uint8_t* buffer; |
| 1304 typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer; | 1253 typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer; |
| 1305 WriteStream stream(&buffer, ZoneReAlloc, 2 * length * kWordSize); | 1254 WriteStream stream(&buffer, ZoneReAlloc, 2 * length * kWordSize); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1337 ASSERT( | 1286 ASSERT( |
| 1338 DeoptInfo::VerifyDecompression(instructions_, deopt_table, deopt_info)); | 1287 DeoptInfo::VerifyDecompression(instructions_, deopt_table, deopt_info)); |
| 1339 instructions_.Clear(); | 1288 instructions_.Clear(); |
| 1340 materializations_.Clear(); | 1289 materializations_.Clear(); |
| 1341 frame_start_ = -1; | 1290 frame_start_ = -1; |
| 1342 | 1291 |
| 1343 ++current_info_number_; | 1292 ++current_info_number_; |
| 1344 return deopt_info.raw(); | 1293 return deopt_info.raw(); |
| 1345 } | 1294 } |
| 1346 | 1295 |
| 1347 | |
| 1348 intptr_t DeoptTable::SizeFor(intptr_t length) { | 1296 intptr_t DeoptTable::SizeFor(intptr_t length) { |
| 1349 return length * kEntrySize; | 1297 return length * kEntrySize; |
| 1350 } | 1298 } |
| 1351 | 1299 |
| 1352 void DeoptTable::SetEntry(const Array& table, | 1300 void DeoptTable::SetEntry(const Array& table, |
| 1353 intptr_t index, | 1301 intptr_t index, |
| 1354 const Smi& offset, | 1302 const Smi& offset, |
| 1355 const TypedData& info, | 1303 const TypedData& info, |
| 1356 const Smi& reason) { | 1304 const Smi& reason) { |
| 1357 ASSERT((table.Length() % kEntrySize) == 0); | 1305 ASSERT((table.Length() % kEntrySize) == 0); |
| 1358 intptr_t i = index * kEntrySize; | 1306 intptr_t i = index * kEntrySize; |
| 1359 table.SetAt(i, offset); | 1307 table.SetAt(i, offset); |
| 1360 table.SetAt(i + 1, info); | 1308 table.SetAt(i + 1, info); |
| 1361 table.SetAt(i + 2, reason); | 1309 table.SetAt(i + 2, reason); |
| 1362 } | 1310 } |
| 1363 | 1311 |
| 1364 | |
| 1365 intptr_t DeoptTable::GetLength(const Array& table) { | 1312 intptr_t DeoptTable::GetLength(const Array& table) { |
| 1366 ASSERT((table.Length() % kEntrySize) == 0); | 1313 ASSERT((table.Length() % kEntrySize) == 0); |
| 1367 return table.Length() / kEntrySize; | 1314 return table.Length() / kEntrySize; |
| 1368 } | 1315 } |
| 1369 | 1316 |
| 1370 | |
| 1371 void DeoptTable::GetEntry(const Array& table, | 1317 void DeoptTable::GetEntry(const Array& table, |
| 1372 intptr_t index, | 1318 intptr_t index, |
| 1373 Smi* offset, | 1319 Smi* offset, |
| 1374 TypedData* info, | 1320 TypedData* info, |
| 1375 Smi* reason) { | 1321 Smi* reason) { |
| 1376 intptr_t i = index * kEntrySize; | 1322 intptr_t i = index * kEntrySize; |
| 1377 *offset ^= table.At(i); | 1323 *offset ^= table.At(i); |
| 1378 *info ^= table.At(i + 1); | 1324 *info ^= table.At(i + 1); |
| 1379 *reason ^= table.At(i + 2); | 1325 *reason ^= table.At(i + 2); |
| 1380 } | 1326 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1478 GrowableArray<DeoptInstr*> unpacked; | 1424 GrowableArray<DeoptInstr*> unpacked; |
| 1479 Unpack(deopt_table, packed, &unpacked); | 1425 Unpack(deopt_table, packed, &unpacked); |
| 1480 ASSERT(unpacked.length() == original.length()); | 1426 ASSERT(unpacked.length() == original.length()); |
| 1481 for (intptr_t i = 0; i < unpacked.length(); ++i) { | 1427 for (intptr_t i = 0; i < unpacked.length(); ++i) { |
| 1482 ASSERT(unpacked[i]->Equals(*original[i])); | 1428 ASSERT(unpacked[i]->Equals(*original[i])); |
| 1483 } | 1429 } |
| 1484 return true; | 1430 return true; |
| 1485 } | 1431 } |
| 1486 | 1432 |
| 1487 } // namespace dart | 1433 } // namespace dart |
| OLD | NEW |