| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/deopt_instructions.h" | 5 #include "vm/deopt_instructions.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 #include "vm/locations.h" | 10 #include "vm/locations.h" |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 | 178 |
| 179 | 179 |
| 180 void DeoptContext::SetCallerFp(intptr_t caller_fp) { | 180 void DeoptContext::SetCallerFp(intptr_t caller_fp) { |
| 181 caller_fp_ = caller_fp; | 181 caller_fp_ = caller_fp; |
| 182 } | 182 } |
| 183 | 183 |
| 184 | 184 |
| 185 static bool IsObjectInstruction(DeoptInstr::Kind kind) { | 185 static bool IsObjectInstruction(DeoptInstr::Kind kind) { |
| 186 switch (kind) { | 186 switch (kind) { |
| 187 case DeoptInstr::kConstant: | 187 case DeoptInstr::kConstant: |
| 188 case DeoptInstr::kStackSlot: | |
| 189 case DeoptInstr::kDoubleStackSlot: | |
| 190 case DeoptInstr::kMintStackSlotPair: | |
| 191 case DeoptInstr::kFloat32x4StackSlot: | |
| 192 case DeoptInstr::kInt32x4StackSlot: | |
| 193 case DeoptInstr::kFloat64x2StackSlot: | |
| 194 case DeoptInstr::kPp: | 188 case DeoptInstr::kPp: |
| 195 case DeoptInstr::kCallerPp: | 189 case DeoptInstr::kCallerPp: |
| 196 case DeoptInstr::kMaterializedObjectRef: | 190 case DeoptInstr::kMaterializedObjectRef: |
| 191 case DeoptInstr::kFloat32x4: |
| 192 case DeoptInstr::kInt32x4: |
| 193 case DeoptInstr::kFloat64x2: |
| 194 case DeoptInstr::kWord: |
| 195 case DeoptInstr::kDouble: |
| 196 case DeoptInstr::kMintPair: |
| 197 return true; | 197 return true; |
| 198 | 198 |
| 199 case DeoptInstr::kRegister: | |
| 200 case DeoptInstr::kFpuRegister: | |
| 201 case DeoptInstr::kMintRegisterPair: | |
| 202 case DeoptInstr::kMintStackSlotRegister: | |
| 203 case DeoptInstr::kFloat32x4FpuRegister: | |
| 204 case DeoptInstr::kInt32x4FpuRegister: | |
| 205 case DeoptInstr::kFloat64x2FpuRegister: | |
| 206 // TODO(turnidge): Sometimes we encounter a deopt instruction | |
| 207 // with a register source while deoptimizing frames during | |
| 208 // debugging but we haven't saved our register set. This | |
| 209 // happens specifically when using the VMService to inspect the | |
| 210 // stack. In that case, the register values will have been | |
| 211 // saved before the StackOverflow runtime call but we do not | |
| 212 // actually keep track of which registers were saved and | |
| 213 // restored. | |
| 214 // | |
| 215 // It is possible to save this information at the point of the | |
| 216 // StackOverflow runtime call but would require a bit of magic | |
| 217 // to either make sure that the registers are pushed on the | |
| 218 // stack in a predictable fashion or that we save enough | |
| 219 // information to recover them after the fact. | |
| 220 // | |
| 221 // For now, we punt on these instructions. | |
| 222 return false; | |
| 223 | |
| 224 case DeoptInstr::kRetAddress: | 199 case DeoptInstr::kRetAddress: |
| 225 case DeoptInstr::kPcMarker: | 200 case DeoptInstr::kPcMarker: |
| 226 case DeoptInstr::kCallerFp: | 201 case DeoptInstr::kCallerFp: |
| 227 case DeoptInstr::kCallerPc: | 202 case DeoptInstr::kCallerPc: |
| 228 return false; | 203 return false; |
| 229 | 204 |
| 230 case DeoptInstr::kSuffix: | 205 case DeoptInstr::kSuffix: |
| 231 case DeoptInstr::kMaterializeObject: | 206 case DeoptInstr::kMaterializeObject: |
| 232 default: | 207 default: |
| 233 // We should not encounter these instructions when filling stack slots. | 208 // We should not encounter these instructions when filling stack slots. |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 Array::Handle(Array::New(dest_frame_size_)); | 338 Array::Handle(Array::New(dest_frame_size_)); |
| 364 Object& obj = Object::Handle(); | 339 Object& obj = Object::Handle(); |
| 365 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 340 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
| 366 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); | 341 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); |
| 367 dest_array.SetAt(i, obj); | 342 dest_array.SetAt(i, obj); |
| 368 } | 343 } |
| 369 return dest_array.raw(); | 344 return dest_array.raw(); |
| 370 } | 345 } |
| 371 | 346 |
| 372 | 347 |
| 373 // Deoptimization instruction moving value from optimized frame at | |
| 374 // 'source_index' to specified slots in the unoptimized frame. | |
| 375 // 'source_index' represents the slot index of the frame (0 being | |
| 376 // first argument) and accounts for saved return address, frame | |
| 377 // pointer, pool pointer and pc marker. | |
| 378 class DeoptStackSlotInstr : public DeoptInstr { | |
| 379 public: | |
| 380 explicit DeoptStackSlotInstr(intptr_t source_index) | |
| 381 : stack_slot_index_(source_index) { | |
| 382 ASSERT(stack_slot_index_ >= 0); | |
| 383 } | |
| 384 | |
| 385 virtual intptr_t source_index() const { return stack_slot_index_; } | |
| 386 virtual DeoptInstr::Kind kind() const { return kStackSlot; } | |
| 387 | |
| 388 virtual const char* ToCString() const { | |
| 389 return Isolate::Current()->current_zone()->PrintToString( | |
| 390 "s%" Pd "", stack_slot_index_); | |
| 391 } | |
| 392 | |
| 393 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 394 intptr_t source_index = | |
| 395 deopt_context->source_frame_size() - stack_slot_index_ - 1; | |
| 396 intptr_t* source_addr = | |
| 397 deopt_context->GetSourceFrameAddressAt(source_index); | |
| 398 *dest_addr = *source_addr; | |
| 399 } | |
| 400 | |
| 401 private: | |
| 402 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | |
| 403 | |
| 404 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); | |
| 405 }; | |
| 406 | |
| 407 | |
| 408 class DeoptDoubleStackSlotInstr : public DeoptInstr { | |
| 409 public: | |
| 410 explicit DeoptDoubleStackSlotInstr(intptr_t source_index) | |
| 411 : stack_slot_index_(source_index) { | |
| 412 ASSERT(stack_slot_index_ >= 0); | |
| 413 } | |
| 414 | |
| 415 virtual intptr_t source_index() const { return stack_slot_index_; } | |
| 416 virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; } | |
| 417 | |
| 418 virtual const char* ToCString() const { | |
| 419 return Isolate::Current()->current_zone()->PrintToString( | |
| 420 "ds%" Pd "", stack_slot_index_); | |
| 421 } | |
| 422 | |
| 423 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 424 intptr_t source_index = | |
| 425 deopt_context->source_frame_size() - stack_slot_index_ - 1; | |
| 426 double* source_addr = reinterpret_cast<double*>( | |
| 427 deopt_context->GetSourceFrameAddressAt(source_index)); | |
| 428 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 429 deopt_context->DeferDoubleMaterialization( | |
| 430 *source_addr, reinterpret_cast<RawDouble**>(dest_addr)); | |
| 431 } | |
| 432 | |
| 433 private: | |
| 434 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | |
| 435 | |
| 436 DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr); | |
| 437 }; | |
| 438 | |
| 439 | |
| 440 class DeoptFloat32x4StackSlotInstr : public DeoptInstr { | |
| 441 public: | |
| 442 explicit DeoptFloat32x4StackSlotInstr(intptr_t source_index) | |
| 443 : stack_slot_index_(source_index) { | |
| 444 ASSERT(stack_slot_index_ >= 0); | |
| 445 } | |
| 446 | |
| 447 virtual intptr_t source_index() const { return stack_slot_index_; } | |
| 448 virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; } | |
| 449 | |
| 450 virtual const char* ToCString() const { | |
| 451 return Isolate::Current()->current_zone()->PrintToString( | |
| 452 "f32x4s%" Pd "", stack_slot_index_); | |
| 453 } | |
| 454 | |
| 455 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 456 intptr_t source_index = | |
| 457 deopt_context->source_frame_size() - stack_slot_index_ - 1; | |
| 458 simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>( | |
| 459 deopt_context->GetSourceFrameAddressAt(source_index)); | |
| 460 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 461 deopt_context->DeferFloat32x4Materialization( | |
| 462 *source_addr, reinterpret_cast<RawFloat32x4**>(dest_addr)); | |
| 463 } | |
| 464 | |
| 465 private: | |
| 466 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | |
| 467 | |
| 468 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr); | |
| 469 }; | |
| 470 | |
| 471 | |
| 472 class DeoptFloat64x2StackSlotInstr : public DeoptInstr { | |
| 473 public: | |
| 474 explicit DeoptFloat64x2StackSlotInstr(intptr_t source_index) | |
| 475 : stack_slot_index_(source_index) { | |
| 476 ASSERT(stack_slot_index_ >= 0); | |
| 477 } | |
| 478 | |
| 479 virtual intptr_t source_index() const { return stack_slot_index_; } | |
| 480 virtual DeoptInstr::Kind kind() const { return kFloat64x2StackSlot; } | |
| 481 | |
| 482 virtual const char* ToCString() const { | |
| 483 return Isolate::Current()->current_zone()->PrintToString( | |
| 484 "f64x2s%" Pd "", stack_slot_index_); | |
| 485 } | |
| 486 | |
| 487 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 488 intptr_t source_index = | |
| 489 deopt_context->source_frame_size() - stack_slot_index_ - 1; | |
| 490 simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>( | |
| 491 deopt_context->GetSourceFrameAddressAt(source_index)); | |
| 492 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 493 deopt_context->DeferFloat64x2Materialization( | |
| 494 *source_addr, reinterpret_cast<RawFloat64x2**>(dest_addr)); | |
| 495 } | |
| 496 | |
| 497 private: | |
| 498 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | |
| 499 | |
| 500 DISALLOW_COPY_AND_ASSIGN(DeoptFloat64x2StackSlotInstr); | |
| 501 }; | |
| 502 | |
| 503 | |
| 504 class DeoptInt32x4StackSlotInstr : public DeoptInstr { | |
| 505 public: | |
| 506 explicit DeoptInt32x4StackSlotInstr(intptr_t source_index) | |
| 507 : stack_slot_index_(source_index) { | |
| 508 ASSERT(stack_slot_index_ >= 0); | |
| 509 } | |
| 510 | |
| 511 virtual intptr_t source_index() const { return stack_slot_index_; } | |
| 512 virtual DeoptInstr::Kind kind() const { return kInt32x4StackSlot; } | |
| 513 | |
| 514 virtual const char* ToCString() const { | |
| 515 return Isolate::Current()->current_zone()->PrintToString( | |
| 516 "ui32x4s%" Pd "", stack_slot_index_); | |
| 517 } | |
| 518 | |
| 519 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 520 intptr_t source_index = | |
| 521 deopt_context->source_frame_size() - stack_slot_index_ - 1; | |
| 522 simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>( | |
| 523 deopt_context->GetSourceFrameAddressAt(source_index)); | |
| 524 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 525 deopt_context->DeferInt32x4Materialization( | |
| 526 *source_addr, reinterpret_cast<RawInt32x4**>(dest_addr)); | |
| 527 } | |
| 528 | |
| 529 private: | |
| 530 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | |
| 531 | |
| 532 DISALLOW_COPY_AND_ASSIGN(DeoptInt32x4StackSlotInstr); | |
| 533 }; | |
| 534 | |
| 535 | |
| 536 // Deoptimization instruction creating return address using function and | 348 // Deoptimization instruction creating return address using function and |
| 537 // deopt-id stored at 'object_table_index'. | 349 // deopt-id stored at 'object_table_index'. |
| 538 class DeoptRetAddressInstr : public DeoptInstr { | 350 class DeoptRetAddressInstr : public DeoptInstr { |
| 539 public: | 351 public: |
| 540 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) | 352 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) |
| 541 : object_table_index_(object_table_index), deopt_id_(deopt_id) { | 353 : object_table_index_(object_table_index), deopt_id_(deopt_id) { |
| 542 ASSERT(object_table_index >= 0); | 354 ASSERT(object_table_index >= 0); |
| 543 ASSERT(deopt_id >= 0); | 355 ASSERT(deopt_id >= 0); |
| 544 } | 356 } |
| 545 | 357 |
| 546 explicit DeoptRetAddressInstr(intptr_t source_index) | 358 explicit DeoptRetAddressInstr(intptr_t source_index) |
| 547 : object_table_index_(ObjectTableIndex::decode(source_index)), | 359 : object_table_index_(ObjectTableIndex::decode(source_index)), |
| 548 deopt_id_(DeoptId::decode(source_index)) { | 360 deopt_id_(DeoptId::decode(source_index)) { |
| 549 } | 361 } |
| 550 | 362 |
| 551 virtual intptr_t source_index() const { | 363 virtual intptr_t source_index() const { |
| 552 return ObjectTableIndex::encode(object_table_index_) | | 364 return ObjectTableIndex::encode(object_table_index_) | |
| 553 DeoptId::encode(deopt_id_); | 365 DeoptId::encode(deopt_id_); |
| 554 } | 366 } |
| 555 | 367 |
| 556 virtual DeoptInstr::Kind kind() const { return kRetAddress; } | 368 virtual DeoptInstr::Kind kind() const { return kRetAddress; } |
| 557 | 369 |
| 558 virtual const char* ToCString() const { | 370 virtual const char* ArgumentsToCString() const { |
| 559 return Isolate::Current()->current_zone()->PrintToString( | 371 return Isolate::Current()->current_zone()->PrintToString( |
| 560 "ret oti:%" Pd "(%" Pd ")", object_table_index_, deopt_id_); | 372 "%" Pd ", %" Pd "", object_table_index_, deopt_id_); |
| 561 } | 373 } |
| 562 | 374 |
| 563 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 375 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 564 Code& code = Code::Handle(deopt_context->isolate()); | 376 Code& code = Code::Handle(deopt_context->isolate()); |
| 565 code ^= deopt_context->ObjectAt(object_table_index_); | 377 code ^= deopt_context->ObjectAt(object_table_index_); |
| 566 ASSERT(!code.IsNull()); | 378 ASSERT(!code.IsNull()); |
| 567 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, | 379 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, |
| 568 RawPcDescriptors::kDeopt); | 380 RawPcDescriptors::kDeopt); |
| 569 ASSERT(continue_at_pc != 0); | 381 ASSERT(continue_at_pc != 0); |
| 570 *dest_addr = continue_at_pc; | 382 *dest_addr = continue_at_pc; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 class DeoptConstantInstr : public DeoptInstr { | 416 class DeoptConstantInstr : public DeoptInstr { |
| 605 public: | 417 public: |
| 606 explicit DeoptConstantInstr(intptr_t object_table_index) | 418 explicit DeoptConstantInstr(intptr_t object_table_index) |
| 607 : object_table_index_(object_table_index) { | 419 : object_table_index_(object_table_index) { |
| 608 ASSERT(object_table_index >= 0); | 420 ASSERT(object_table_index >= 0); |
| 609 } | 421 } |
| 610 | 422 |
| 611 virtual intptr_t source_index() const { return object_table_index_; } | 423 virtual intptr_t source_index() const { return object_table_index_; } |
| 612 virtual DeoptInstr::Kind kind() const { return kConstant; } | 424 virtual DeoptInstr::Kind kind() const { return kConstant; } |
| 613 | 425 |
| 614 virtual const char* ToCString() const { | 426 virtual const char* ArgumentsToCString() const { |
| 615 return Isolate::Current()->current_zone()->PrintToString( | 427 return Isolate::Current()->current_zone()->PrintToString( |
| 616 "const oti:%" Pd "", object_table_index_); | 428 "%" Pd "", object_table_index_); |
| 617 } | 429 } |
| 618 | 430 |
| 619 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 431 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 620 const Object& obj = Object::Handle( | 432 const Object& obj = Object::Handle( |
| 621 deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); | 433 deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); |
| 622 *reinterpret_cast<RawObject**>(dest_addr) = obj.raw(); | 434 *reinterpret_cast<RawObject**>(dest_addr) = obj.raw(); |
| 623 } | 435 } |
| 624 | 436 |
| 625 private: | 437 private: |
| 626 const intptr_t object_table_index_; | 438 const intptr_t object_table_index_; |
| 627 | 439 |
| 628 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | 440 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); |
| 629 }; | 441 }; |
| 630 | 442 |
| 631 | 443 |
| 444 // Deoptimization instruction moving value from optimized frame at |
| 445 // 'source_index' to specified slots in the unoptimized frame. |
| 446 // 'source_index' represents the slot index of the frame (0 being |
| 447 // first argument) and accounts for saved return address, frame |
| 448 // pointer, pool pointer and pc marker. |
| 632 // Deoptimization instruction moving a CPU register. | 449 // Deoptimization instruction moving a CPU register. |
| 633 class DeoptRegisterInstr: public DeoptInstr { | 450 class DeoptWordInstr: public DeoptInstr { |
| 634 public: | 451 public: |
| 635 explicit DeoptRegisterInstr(intptr_t reg_as_int) | 452 explicit DeoptWordInstr(intptr_t source_index) |
| 636 : reg_(static_cast<Register>(reg_as_int)) {} | 453 : source_(source_index) {} |
| 637 | 454 |
| 638 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } | 455 explicit DeoptWordInstr(const CpuRegisterSource& source) |
| 639 virtual DeoptInstr::Kind kind() const { return kRegister; } | 456 : source_(source) {} |
| 640 | 457 |
| 641 virtual const char* ToCString() const { | 458 virtual intptr_t source_index() const { return source_.source_index(); } |
| 642 return Assembler::RegisterName(reg_); | 459 virtual DeoptInstr::Kind kind() const { return kWord; } |
| 460 |
| 461 virtual const char* ArgumentsToCString() const { |
| 462 return source_.ToCString(); |
| 643 } | 463 } |
| 644 | 464 |
| 645 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 465 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 646 *dest_addr = deopt_context->RegisterValue(reg_); | 466 *dest_addr = source_.Value<intptr_t>(deopt_context); |
| 647 } | 467 } |
| 648 | 468 |
| 649 private: | 469 private: |
| 650 const Register reg_; | 470 const CpuRegisterSource source_; |
| 651 | 471 |
| 652 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); | 472 DISALLOW_COPY_AND_ASSIGN(DeoptWordInstr); |
| 653 }; | 473 }; |
| 654 | 474 |
| 655 | 475 |
| 656 // Deoptimization instruction moving an XMM register. | 476 class DeoptIntegerInstrBase: public DeoptInstr { |
| 657 class DeoptFpuRegisterInstr: public DeoptInstr { | |
| 658 public: | 477 public: |
| 659 explicit DeoptFpuRegisterInstr(intptr_t reg_as_int) | 478 DeoptIntegerInstrBase() { } |
| 660 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | |
| 661 | |
| 662 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } | |
| 663 virtual DeoptInstr::Kind kind() const { return kFpuRegister; } | |
| 664 | |
| 665 virtual const char* ToCString() const { | |
| 666 return Assembler::FpuRegisterName(reg_); | |
| 667 } | |
| 668 | 479 |
| 669 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 480 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 670 double value = deopt_context->FpuRegisterValue(reg_); | 481 const int64_t value = GetValue(deopt_context); |
| 671 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 672 deopt_context->DeferDoubleMaterialization( | |
| 673 value, reinterpret_cast<RawDouble**>(dest_addr)); | |
| 674 } | |
| 675 | |
| 676 private: | |
| 677 const FpuRegister reg_; | |
| 678 | |
| 679 DISALLOW_COPY_AND_ASSIGN(DeoptFpuRegisterInstr); | |
| 680 }; | |
| 681 | |
| 682 | |
| 683 class DeoptMintRegisterPairInstr: public DeoptInstr { | |
| 684 public: | |
| 685 DeoptMintRegisterPairInstr(intptr_t lo_reg_as_int, intptr_t hi_reg_as_int) | |
| 686 : lo_reg_(static_cast<Register>(lo_reg_as_int)), | |
| 687 hi_reg_(static_cast<Register>(hi_reg_as_int)) {} | |
| 688 | |
| 689 virtual intptr_t source_index() const { | |
| 690 return EncodeRegisters(static_cast<intptr_t>(lo_reg_), | |
| 691 static_cast<intptr_t>(hi_reg_)); | |
| 692 } | |
| 693 virtual DeoptInstr::Kind kind() const { return kMintRegisterPair; } | |
| 694 | |
| 695 virtual const char* ToCString() const { | |
| 696 return Isolate::Current()->current_zone()->PrintToString( | |
| 697 "int64 register pair: %s,%s", Assembler::RegisterName(hi_reg_), | |
| 698 Assembler::RegisterName(lo_reg_)); | |
| 699 } | |
| 700 | |
| 701 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 702 uint32_t lo_value = deopt_context->RegisterValue(lo_reg_); | |
| 703 int32_t hi_value = deopt_context->RegisterValue(hi_reg_); | |
| 704 int64_t value = Utils::LowHighTo64Bits(lo_value, hi_value); | |
| 705 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 706 if (Smi::IsValid(value)) { | 482 if (Smi::IsValid(value)) { |
| 707 *dest_addr = reinterpret_cast<intptr_t>( | 483 *dest_addr = Smi::RawValue(static_cast<intptr_t>(value)); |
| 708 Smi::New(static_cast<intptr_t>(value))); | |
| 709 } else { | 484 } else { |
| 485 *dest_addr = Smi::RawValue(0); |
| 710 deopt_context->DeferMintMaterialization( | 486 deopt_context->DeferMintMaterialization( |
| 711 value, reinterpret_cast<RawMint**>(dest_addr)); | 487 value, reinterpret_cast<RawMint**>(dest_addr)); |
| 712 } | 488 } |
| 713 } | 489 } |
| 714 | 490 |
| 491 virtual int64_t GetValue(DeoptContext* deopt_context) = 0; |
| 492 |
| 493 private: |
| 494 DISALLOW_COPY_AND_ASSIGN(DeoptIntegerInstrBase); |
| 495 }; |
| 496 |
| 497 |
| 498 class DeoptMintPairInstr: public DeoptIntegerInstrBase { |
| 499 public: |
| 500 explicit DeoptMintPairInstr(intptr_t source_index) |
| 501 : DeoptIntegerInstrBase(), |
| 502 lo_(LoRegister::decode(source_index)), |
| 503 hi_(HiRegister::decode(source_index)) { |
| 504 } |
| 505 |
| 506 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) |
| 507 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} |
| 508 |
| 509 virtual intptr_t source_index() const { |
| 510 return LoRegister::encode(lo_.source_index()) | |
| 511 HiRegister::encode(hi_.source_index()); |
| 512 } |
| 513 virtual DeoptInstr::Kind kind() const { return kMintPair; } |
| 514 |
| 515 virtual const char* ArgumentsToCString() const { |
| 516 return Isolate::Current()->current_zone()->PrintToString( |
| 517 "%s,%s", |
| 518 lo_.ToCString(), |
| 519 hi_.ToCString()); |
| 520 } |
| 521 |
| 522 virtual int64_t GetValue(DeoptContext* deopt_context) { |
| 523 return Utils::LowHighTo64Bits( |
| 524 lo_.Value<uint32_t>(deopt_context), hi_.Value<int32_t>(deopt_context)); |
| 525 } |
| 526 |
| 527 private: |
| 715 static const intptr_t kFieldWidth = kBitsPerWord / 2; | 528 static const intptr_t kFieldWidth = kBitsPerWord / 2; |
| 716 class LoRegister : public BitField<intptr_t, 0, kFieldWidth> { }; | 529 class LoRegister : public BitField<intptr_t, 0, kFieldWidth> { }; |
| 717 class HiRegister : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; | 530 class HiRegister : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; |
| 718 static intptr_t EncodeRegisters(intptr_t lo_reg_as_int, | 531 |
| 719 intptr_t hi_reg_as_int) { | 532 const CpuRegisterSource lo_; |
| 720 return LoRegister::encode(lo_reg_as_int) | | 533 const CpuRegisterSource hi_; |
| 721 HiRegister::encode(hi_reg_as_int); | 534 |
| 535 DISALLOW_COPY_AND_ASSIGN(DeoptMintPairInstr); |
| 536 }; |
| 537 |
| 538 |
| 539 class DeoptUint32Instr : public DeoptIntegerInstrBase { |
| 540 public: |
| 541 explicit DeoptUint32Instr(intptr_t source_index) |
| 542 : DeoptIntegerInstrBase(), source_(source_index) { |
| 722 } | 543 } |
| 723 | 544 |
| 724 static intptr_t DecodeLoRegister(intptr_t v) { | 545 explicit DeoptUint32Instr(const CpuRegisterSource& source) |
| 725 return LoRegister::decode(v); | 546 : DeoptIntegerInstrBase(), source_(source) { |
| 726 } | 547 } |
| 727 | 548 |
| 728 static intptr_t DecodeHiRegister(intptr_t v) { | 549 virtual intptr_t source_index() const { return source_.source_index(); } |
| 729 return HiRegister::decode(v); | 550 virtual DeoptInstr::Kind kind() const { return kUint32; } |
| 551 |
| 552 virtual const char* ArgumentsToCString() const { |
| 553 return source_.ToCString(); |
| 554 } |
| 555 |
| 556 virtual int64_t GetValue(DeoptContext* deopt_context) { |
| 557 return static_cast<int64_t>(source_.Value<uint32_t>(deopt_context)); |
| 730 } | 558 } |
| 731 | 559 |
| 732 private: | 560 private: |
| 733 const Register lo_reg_; | 561 const CpuRegisterSource source_; |
| 734 const Register hi_reg_; | |
| 735 | 562 |
| 736 DISALLOW_COPY_AND_ASSIGN(DeoptMintRegisterPairInstr); | 563 DISALLOW_COPY_AND_ASSIGN(DeoptUint32Instr); |
| 737 }; | 564 }; |
| 738 | 565 |
| 739 | 566 |
| 740 class DeoptMintStackSlotPairInstr: public DeoptInstr { | 567 template<DeoptInstr::Kind K, |
| 568 typename Type, |
| 569 typename RawObjectType> |
| 570 class DeoptFpuInstr: public DeoptInstr { |
| 741 public: | 571 public: |
| 742 DeoptMintStackSlotPairInstr(intptr_t lo_slot, intptr_t hi_slot) | 572 explicit DeoptFpuInstr(intptr_t source_index) |
| 743 : lo_slot_(static_cast<Register>(lo_slot)), | 573 : source_(source_index) {} |
| 744 hi_slot_(static_cast<Register>(hi_slot)) {} | |
| 745 | 574 |
| 746 virtual intptr_t source_index() const { | 575 explicit DeoptFpuInstr(const FpuRegisterSource& source) |
| 747 return EncodeSlots(static_cast<intptr_t>(lo_slot_), | 576 : source_(source) {} |
| 748 static_cast<intptr_t>(hi_slot_)); | |
| 749 } | |
| 750 virtual DeoptInstr::Kind kind() const { return kMintStackSlotPair; } | |
| 751 | 577 |
| 752 virtual const char* ToCString() const { | 578 virtual intptr_t source_index() const { return source_.source_index(); } |
| 753 return Isolate::Current()->current_zone()->PrintToString( | 579 virtual DeoptInstr::Kind kind() const { return K; } |
| 754 "int64 stack slots: %" Pd", %" Pd "", lo_slot_, hi_slot_); | 580 |
| 581 virtual const char* ArgumentsToCString() const { |
| 582 return source_.ToCString(); |
| 755 } | 583 } |
| 756 | 584 |
| 757 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 585 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 758 intptr_t lo_source_index = | 586 *dest_addr = Smi::RawValue(0); |
| 759 deopt_context->source_frame_size() - lo_slot_ - 1; | 587 deopt_context->DeferMaterialization( |
| 760 int32_t* lo_source_addr = reinterpret_cast<int32_t*>( | 588 source_.Value<Type>(deopt_context), |
| 761 deopt_context->GetSourceFrameAddressAt(lo_source_index)); | 589 reinterpret_cast<RawObjectType**>(dest_addr)); |
| 762 intptr_t hi_source_index = | |
| 763 deopt_context->source_frame_size() - hi_slot_ - 1; | |
| 764 int32_t* hi_source_addr = reinterpret_cast<int32_t*>( | |
| 765 deopt_context->GetSourceFrameAddressAt(hi_source_index)); | |
| 766 int64_t value = Utils::LowHighTo64Bits(*lo_source_addr, *hi_source_addr); | |
| 767 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 768 if (Smi::IsValid(value)) { | |
| 769 *dest_addr = reinterpret_cast<intptr_t>( | |
| 770 Smi::New(static_cast<intptr_t>(value))); | |
| 771 } else { | |
| 772 deopt_context->DeferMintMaterialization( | |
| 773 value, reinterpret_cast<RawMint**>(dest_addr)); | |
| 774 } | |
| 775 } | |
| 776 | |
| 777 static const intptr_t kFieldWidth = kBitsPerWord / 2; | |
| 778 class LoSlot : public BitField<intptr_t, 0, kFieldWidth> { }; | |
| 779 class HiSlot : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; | |
| 780 static intptr_t EncodeSlots(intptr_t lo_slot, | |
| 781 intptr_t hi_slot) { | |
| 782 return LoSlot::encode(lo_slot) | | |
| 783 HiSlot::encode(hi_slot); | |
| 784 } | |
| 785 | |
| 786 static intptr_t DecodeLoSlot(intptr_t v) { | |
| 787 return LoSlot::decode(v); | |
| 788 } | |
| 789 | |
| 790 static intptr_t DecodeHiSlot(intptr_t v) { | |
| 791 return HiSlot::decode(v); | |
| 792 } | 590 } |
| 793 | 591 |
| 794 private: | 592 private: |
| 795 const intptr_t lo_slot_; | 593 const FpuRegisterSource source_; |
| 796 const intptr_t hi_slot_; | |
| 797 | 594 |
| 798 DISALLOW_COPY_AND_ASSIGN(DeoptMintStackSlotPairInstr); | 595 DISALLOW_COPY_AND_ASSIGN(DeoptFpuInstr); |
| 799 }; | 596 }; |
| 800 | 597 |
| 598 typedef DeoptFpuInstr<DeoptInstr::kDouble, double, RawDouble> DeoptDoubleInstr; |
| 801 | 599 |
| 802 class DeoptMintStackSlotRegisterInstr : public DeoptInstr { | 600 // Simd128 types. |
| 803 public: | 601 typedef DeoptFpuInstr<DeoptInstr::kFloat32x4, simd128_value_t, RawFloat32x4> |
| 804 DeoptMintStackSlotRegisterInstr(intptr_t source_index, | 602 DeoptFloat32x4Instr; |
| 805 intptr_t reg_as_int, | 603 typedef DeoptFpuInstr<DeoptInstr::kFloat32x4, simd128_value_t, RawFloat32x4> |
| 806 bool flip) | 604 DeoptFloat32x4Instr; |
| 807 : slot_(source_index), | 605 typedef DeoptFpuInstr<DeoptInstr::kFloat64x2, simd128_value_t, RawFloat64x2> |
| 808 reg_(static_cast<Register>(reg_as_int)), | 606 DeoptFloat64x2Instr; |
| 809 flip_(flip) { | 607 typedef DeoptFpuInstr<DeoptInstr::kInt32x4, simd128_value_t, RawInt32x4> |
| 810 // when flip_ is false, stack slot is low bits and reg is high bits. | 608 DeoptInt32x4Instr; |
| 811 // when flip_ is true, stack slot is high bits and reg is low bits. | |
| 812 } | |
| 813 | |
| 814 virtual intptr_t source_index() const { | |
| 815 return Encode(static_cast<intptr_t>(slot_), | |
| 816 static_cast<intptr_t>(reg_), | |
| 817 flip_ ? 1 : 0); | |
| 818 } | |
| 819 virtual DeoptInstr::Kind kind() const { return kMintStackSlotRegister; } | |
| 820 | |
| 821 virtual const char* ToCString() const { | |
| 822 if (flip_) { | |
| 823 return Isolate::Current()->current_zone()->PrintToString( | |
| 824 "int64 reg: %s, stack slot: %" Pd "", Assembler::RegisterName(reg_), | |
| 825 slot_); | |
| 826 } else { | |
| 827 return Isolate::Current()->current_zone()->PrintToString( | |
| 828 "int64 stack slot: %" Pd", reg: %s", slot_, | |
| 829 Assembler::RegisterName(reg_)); | |
| 830 } | |
| 831 } | |
| 832 | |
| 833 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 834 intptr_t slot_source_index = | |
| 835 deopt_context->source_frame_size() - slot_ - 1; | |
| 836 int32_t* slot_source_addr = reinterpret_cast<int32_t*>( | |
| 837 deopt_context->GetSourceFrameAddressAt(slot_source_index)); | |
| 838 int32_t slot_value = *slot_source_addr; | |
| 839 int32_t reg_value = deopt_context->RegisterValue(reg_); | |
| 840 int64_t value; | |
| 841 if (flip_) { | |
| 842 value = Utils::LowHighTo64Bits(reg_value, slot_value); | |
| 843 } else { | |
| 844 value = Utils::LowHighTo64Bits(slot_value, reg_value); | |
| 845 } | |
| 846 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 847 if (Smi::IsValid(value)) { | |
| 848 *dest_addr = reinterpret_cast<intptr_t>( | |
| 849 Smi::New(static_cast<intptr_t>(value))); | |
| 850 } else { | |
| 851 deopt_context->DeferMintMaterialization( | |
| 852 value, reinterpret_cast<RawMint**>(dest_addr)); | |
| 853 } | |
| 854 } | |
| 855 | |
| 856 static const intptr_t kFieldWidth = kBitsPerWord / 2; | |
| 857 class Slot : public BitField<intptr_t, 0, kFieldWidth> { }; | |
| 858 class Reg : public BitField<intptr_t, kFieldWidth, kFieldWidth - 1> { }; | |
| 859 // 1 bit for the flip. | |
| 860 class Flip : public BitField<intptr_t, kFieldWidth * 2 - 1, 1> { }; | |
| 861 | |
| 862 static intptr_t Encode(intptr_t slot, | |
| 863 intptr_t reg_as_int, | |
| 864 bool flip) { | |
| 865 return Slot::encode(slot) | | |
| 866 Reg::encode(reg_as_int) | | |
| 867 Flip::encode(flip ? 1 : 0); | |
| 868 } | |
| 869 | |
| 870 static intptr_t DecodeSlot(intptr_t v) { | |
| 871 return Slot::decode(v); | |
| 872 } | |
| 873 | |
| 874 static intptr_t DecodeReg(intptr_t v) { | |
| 875 return Reg::decode(v); | |
| 876 } | |
| 877 | |
| 878 static bool DecodeFlip(intptr_t v) { | |
| 879 return Flip::decode(v); | |
| 880 } | |
| 881 | |
| 882 private: | |
| 883 const intptr_t slot_; | |
| 884 const Register reg_; | |
| 885 const bool flip_; | |
| 886 DISALLOW_COPY_AND_ASSIGN(DeoptMintStackSlotRegisterInstr); | |
| 887 }; | |
| 888 | |
| 889 | |
| 890 class DeoptUint32RegisterInstr: public DeoptInstr { | |
| 891 public: | |
| 892 explicit DeoptUint32RegisterInstr(intptr_t reg_as_int) | |
| 893 : reg_(static_cast<Register>(reg_as_int)) {} | |
| 894 | |
| 895 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } | |
| 896 virtual DeoptInstr::Kind kind() const { return kUint32Register; } | |
| 897 | |
| 898 virtual const char* ToCString() const { | |
| 899 return Isolate::Current()->current_zone()->PrintToString( | |
| 900 "uint32 %s", Assembler::RegisterName(reg_)); | |
| 901 } | |
| 902 | |
| 903 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 904 uint32_t low = static_cast<uint32_t>(deopt_context->RegisterValue(reg_)); | |
| 905 int64_t value = Utils::LowHighTo64Bits(low, 0); | |
| 906 if (Smi::IsValid(value)) { | |
| 907 *dest_addr = reinterpret_cast<intptr_t>( | |
| 908 Smi::New(static_cast<intptr_t>(value))); | |
| 909 } else { | |
| 910 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 911 deopt_context->DeferMintMaterialization( | |
| 912 value, reinterpret_cast<RawMint**>(dest_addr)); | |
| 913 } | |
| 914 } | |
| 915 | |
| 916 private: | |
| 917 const Register reg_; | |
| 918 | |
| 919 DISALLOW_COPY_AND_ASSIGN(DeoptUint32RegisterInstr); | |
| 920 }; | |
| 921 | |
| 922 | |
| 923 class DeoptUint32StackSlotInstr : public DeoptInstr { | |
| 924 public: | |
| 925 explicit DeoptUint32StackSlotInstr(intptr_t source_index) | |
| 926 : stack_slot_index_(source_index) { | |
| 927 ASSERT(stack_slot_index_ >= 0); | |
| 928 } | |
| 929 | |
| 930 virtual intptr_t source_index() const { return stack_slot_index_; } | |
| 931 virtual DeoptInstr::Kind kind() const { return kUint32StackSlot; } | |
| 932 | |
| 933 virtual const char* ToCString() const { | |
| 934 return Isolate::Current()->current_zone()->PrintToString( | |
| 935 "uint32 s%" Pd "", stack_slot_index_); | |
| 936 } | |
| 937 | |
| 938 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 939 intptr_t source_index = | |
| 940 deopt_context->source_frame_size() - stack_slot_index_ - 1; | |
| 941 uint32_t* source_addr = reinterpret_cast<uint32_t*>( | |
| 942 deopt_context->GetSourceFrameAddressAt(source_index)); | |
| 943 int64_t value = Utils::LowHighTo64Bits(*source_addr, 0); | |
| 944 if (Smi::IsValid(value)) { | |
| 945 *dest_addr = reinterpret_cast<intptr_t>( | |
| 946 Smi::New(static_cast<intptr_t>(value))); | |
| 947 } else { | |
| 948 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 949 deopt_context->DeferMintMaterialization( | |
| 950 value, reinterpret_cast<RawMint**>(dest_addr)); | |
| 951 } | |
| 952 } | |
| 953 | |
| 954 private: | |
| 955 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | |
| 956 | |
| 957 DISALLOW_COPY_AND_ASSIGN(DeoptUint32StackSlotInstr); | |
| 958 }; | |
| 959 | |
| 960 | |
| 961 // Deoptimization instruction moving an XMM register. | |
| 962 class DeoptFloat32x4FpuRegisterInstr: public DeoptInstr { | |
| 963 public: | |
| 964 explicit DeoptFloat32x4FpuRegisterInstr(intptr_t reg_as_int) | |
| 965 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | |
| 966 | |
| 967 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } | |
| 968 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } | |
| 969 | |
| 970 virtual const char* ToCString() const { | |
| 971 return Isolate::Current()->current_zone()->PrintToString( | |
| 972 "%s(f32x4)", Assembler::FpuRegisterName(reg_)); | |
| 973 } | |
| 974 | |
| 975 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 976 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); | |
| 977 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 978 deopt_context->DeferFloat32x4Materialization( | |
| 979 value, reinterpret_cast<RawFloat32x4**>(dest_addr)); | |
| 980 } | |
| 981 | |
| 982 private: | |
| 983 const FpuRegister reg_; | |
| 984 | |
| 985 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr); | |
| 986 }; | |
| 987 | |
| 988 | |
| 989 class DeoptFloat64x2FpuRegisterInstr: public DeoptInstr { | |
| 990 public: | |
| 991 explicit DeoptFloat64x2FpuRegisterInstr(intptr_t reg_as_int) | |
| 992 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | |
| 993 | |
| 994 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } | |
| 995 virtual DeoptInstr::Kind kind() const { return kFloat64x2FpuRegister; } | |
| 996 | |
| 997 virtual const char* ToCString() const { | |
| 998 return Isolate::Current()->current_zone()->PrintToString( | |
| 999 "%s(f64x2)", Assembler::FpuRegisterName(reg_)); | |
| 1000 } | |
| 1001 | |
| 1002 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 1003 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); | |
| 1004 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 1005 deopt_context->DeferFloat64x2Materialization( | |
| 1006 value, reinterpret_cast<RawFloat64x2**>(dest_addr)); | |
| 1007 } | |
| 1008 | |
| 1009 private: | |
| 1010 const FpuRegister reg_; | |
| 1011 | |
| 1012 DISALLOW_COPY_AND_ASSIGN(DeoptFloat64x2FpuRegisterInstr); | |
| 1013 }; | |
| 1014 | |
| 1015 | |
| 1016 // Deoptimization instruction moving an XMM register. | |
| 1017 class DeoptInt32x4FpuRegisterInstr: public DeoptInstr { | |
| 1018 public: | |
| 1019 explicit DeoptInt32x4FpuRegisterInstr(intptr_t reg_as_int) | |
| 1020 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | |
| 1021 | |
| 1022 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } | |
| 1023 virtual DeoptInstr::Kind kind() const { return kInt32x4FpuRegister; } | |
| 1024 | |
| 1025 virtual const char* ToCString() const { | |
| 1026 return Isolate::Current()->current_zone()->PrintToString( | |
| 1027 "%s(f32x4)", Assembler::FpuRegisterName(reg_)); | |
| 1028 } | |
| 1029 | |
| 1030 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 1031 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); | |
| 1032 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | |
| 1033 deopt_context->DeferInt32x4Materialization( | |
| 1034 value, reinterpret_cast<RawInt32x4**>(dest_addr)); | |
| 1035 } | |
| 1036 | |
| 1037 private: | |
| 1038 const FpuRegister reg_; | |
| 1039 | |
| 1040 DISALLOW_COPY_AND_ASSIGN(DeoptInt32x4FpuRegisterInstr); | |
| 1041 }; | |
| 1042 | |
| 1043 | 609 |
| 1044 // Deoptimization instruction creating a PC marker for the code of | 610 // Deoptimization instruction creating a PC marker for the code of |
| 1045 // function at 'object_table_index'. | 611 // function at 'object_table_index'. |
| 1046 class DeoptPcMarkerInstr : public DeoptInstr { | 612 class DeoptPcMarkerInstr : public DeoptInstr { |
| 1047 public: | 613 public: |
| 1048 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | 614 explicit DeoptPcMarkerInstr(intptr_t object_table_index) |
| 1049 : object_table_index_(object_table_index) { | 615 : object_table_index_(object_table_index) { |
| 1050 ASSERT(object_table_index >= 0); | 616 ASSERT(object_table_index >= 0); |
| 1051 } | 617 } |
| 1052 | 618 |
| 1053 virtual intptr_t source_index() const { return object_table_index_; } | 619 virtual intptr_t source_index() const { return object_table_index_; } |
| 1054 virtual DeoptInstr::Kind kind() const { return kPcMarker; } | 620 virtual DeoptInstr::Kind kind() const { return kPcMarker; } |
| 1055 | 621 |
| 1056 virtual const char* ToCString() const { | 622 virtual const char* ArgumentsToCString() const { |
| 1057 return Isolate::Current()->current_zone()->PrintToString( | 623 return Isolate::Current()->current_zone()->PrintToString( |
| 1058 "pcmark oti:%" Pd "", object_table_index_); | 624 "%" Pd "", object_table_index_); |
| 1059 } | 625 } |
| 1060 | 626 |
| 1061 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 627 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 1062 Code& code = Code::Handle(deopt_context->isolate()); | 628 Code& code = Code::Handle(deopt_context->isolate()); |
| 1063 code ^= deopt_context->ObjectAt(object_table_index_); | 629 code ^= deopt_context->ObjectAt(object_table_index_); |
| 1064 if (code.IsNull()) { | 630 if (code.IsNull()) { |
| 1065 // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0. | 631 // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0. |
| 1066 *dest_addr = 0; | 632 *dest_addr = 0; |
| 1067 return; | 633 return; |
| 1068 } | 634 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 class DeoptPpInstr : public DeoptInstr { | 666 class DeoptPpInstr : public DeoptInstr { |
| 1101 public: | 667 public: |
| 1102 explicit DeoptPpInstr(intptr_t object_table_index) | 668 explicit DeoptPpInstr(intptr_t object_table_index) |
| 1103 : object_table_index_(object_table_index) { | 669 : object_table_index_(object_table_index) { |
| 1104 ASSERT(object_table_index >= 0); | 670 ASSERT(object_table_index >= 0); |
| 1105 } | 671 } |
| 1106 | 672 |
| 1107 virtual intptr_t source_index() const { return object_table_index_; } | 673 virtual intptr_t source_index() const { return object_table_index_; } |
| 1108 virtual DeoptInstr::Kind kind() const { return kPp; } | 674 virtual DeoptInstr::Kind kind() const { return kPp; } |
| 1109 | 675 |
| 1110 virtual const char* ToCString() const { | 676 virtual const char* ArgumentsToCString() const { |
| 1111 return Isolate::Current()->current_zone()->PrintToString( | 677 return Isolate::Current()->current_zone()->PrintToString( |
| 1112 "pp oti:%" Pd "", object_table_index_); | 678 "%" Pd "", object_table_index_); |
| 1113 } | 679 } |
| 1114 | 680 |
| 1115 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 681 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 1116 Code& code = Code::Handle(deopt_context->isolate()); | 682 Code& code = Code::Handle(deopt_context->isolate()); |
| 1117 code ^= deopt_context->ObjectAt(object_table_index_); | 683 code ^= deopt_context->ObjectAt(object_table_index_); |
| 1118 ASSERT(!code.IsNull()); | 684 ASSERT(!code.IsNull()); |
| 1119 const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool()); | 685 const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool()); |
| 1120 *dest_addr = pp; | 686 *dest_addr = pp; |
| 1121 } | 687 } |
| 1122 | 688 |
| 1123 private: | 689 private: |
| 1124 intptr_t object_table_index_; | 690 intptr_t object_table_index_; |
| 1125 | 691 |
| 1126 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); | 692 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); |
| 1127 }; | 693 }; |
| 1128 | 694 |
| 1129 | 695 |
| 1130 // Deoptimization instruction copying the caller saved FP from optimized frame. | 696 // Deoptimization instruction copying the caller saved FP from optimized frame. |
| 1131 class DeoptCallerFpInstr : public DeoptInstr { | 697 class DeoptCallerFpInstr : public DeoptInstr { |
| 1132 public: | 698 public: |
| 1133 DeoptCallerFpInstr() {} | 699 DeoptCallerFpInstr() {} |
| 1134 | 700 |
| 1135 virtual intptr_t source_index() const { return 0; } | 701 virtual intptr_t source_index() const { return 0; } |
| 1136 virtual DeoptInstr::Kind kind() const { return kCallerFp; } | 702 virtual DeoptInstr::Kind kind() const { return kCallerFp; } |
| 1137 | 703 |
| 1138 virtual const char* ToCString() const { | |
| 1139 return "callerfp"; | |
| 1140 } | |
| 1141 | |
| 1142 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 704 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 1143 *dest_addr = deopt_context->GetCallerFp(); | 705 *dest_addr = deopt_context->GetCallerFp(); |
| 1144 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>( | 706 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>( |
| 1145 dest_addr - (kSavedCallerFpSlotFromFp * kWordSize))); | 707 dest_addr - (kSavedCallerFpSlotFromFp * kWordSize))); |
| 1146 } | 708 } |
| 1147 | 709 |
| 1148 private: | 710 private: |
| 1149 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | 711 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); |
| 1150 }; | 712 }; |
| 1151 | 713 |
| 1152 | 714 |
| 1153 // Deoptimization instruction copying the caller saved PP from optimized frame. | 715 // Deoptimization instruction copying the caller saved PP from optimized frame. |
| 1154 class DeoptCallerPpInstr : public DeoptInstr { | 716 class DeoptCallerPpInstr : public DeoptInstr { |
| 1155 public: | 717 public: |
| 1156 DeoptCallerPpInstr() {} | 718 DeoptCallerPpInstr() {} |
| 1157 | 719 |
| 1158 virtual intptr_t source_index() const { return 0; } | 720 virtual intptr_t source_index() const { return 0; } |
| 1159 virtual DeoptInstr::Kind kind() const { return kCallerPp; } | 721 virtual DeoptInstr::Kind kind() const { return kCallerPp; } |
| 1160 | 722 |
| 1161 virtual const char* ToCString() const { | |
| 1162 return "callerpp"; | |
| 1163 } | |
| 1164 | |
| 1165 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 723 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 1166 *dest_addr = deopt_context->GetSourcePp(); | 724 *dest_addr = deopt_context->GetSourcePp(); |
| 1167 } | 725 } |
| 1168 | 726 |
| 1169 private: | 727 private: |
| 1170 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPpInstr); | 728 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPpInstr); |
| 1171 }; | 729 }; |
| 1172 | 730 |
| 1173 | 731 |
| 1174 // Deoptimization instruction copying the caller return address from optimized | 732 // Deoptimization instruction copying the caller return address from optimized |
| 1175 // frame. | 733 // frame. |
| 1176 class DeoptCallerPcInstr : public DeoptInstr { | 734 class DeoptCallerPcInstr : public DeoptInstr { |
| 1177 public: | 735 public: |
| 1178 DeoptCallerPcInstr() {} | 736 DeoptCallerPcInstr() {} |
| 1179 | 737 |
| 1180 virtual intptr_t source_index() const { return 0; } | 738 virtual intptr_t source_index() const { return 0; } |
| 1181 virtual DeoptInstr::Kind kind() const { return kCallerPc; } | 739 virtual DeoptInstr::Kind kind() const { return kCallerPc; } |
| 1182 | 740 |
| 1183 virtual const char* ToCString() const { | |
| 1184 return "callerpc"; | |
| 1185 } | |
| 1186 | |
| 1187 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 741 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 1188 *dest_addr = deopt_context->GetSourcePc(); | 742 *dest_addr = deopt_context->GetSourcePc(); |
| 1189 } | 743 } |
| 1190 | 744 |
| 1191 private: | 745 private: |
| 1192 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 746 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
| 1193 }; | 747 }; |
| 1194 | 748 |
| 1195 | 749 |
| 1196 // Deoptimization instruction that indicates the rest of this DeoptInfo is a | 750 // Deoptimization instruction that indicates the rest of this DeoptInfo is a |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1209 : info_number_(InfoNumber::decode(source_index)), | 763 : info_number_(InfoNumber::decode(source_index)), |
| 1210 suffix_length_(SuffixLength::decode(source_index)) { | 764 suffix_length_(SuffixLength::decode(source_index)) { |
| 1211 } | 765 } |
| 1212 | 766 |
| 1213 virtual intptr_t source_index() const { | 767 virtual intptr_t source_index() const { |
| 1214 return InfoNumber::encode(info_number_) | | 768 return InfoNumber::encode(info_number_) | |
| 1215 SuffixLength::encode(suffix_length_); | 769 SuffixLength::encode(suffix_length_); |
| 1216 } | 770 } |
| 1217 virtual DeoptInstr::Kind kind() const { return kSuffix; } | 771 virtual DeoptInstr::Kind kind() const { return kSuffix; } |
| 1218 | 772 |
| 1219 virtual const char* ToCString() const { | 773 virtual const char* ArgumentsToCString() const { |
| 1220 return Isolate::Current()->current_zone()->PrintToString( | 774 return Isolate::Current()->current_zone()->PrintToString( |
| 1221 "suffix %" Pd ":%" Pd, info_number_, suffix_length_); | 775 "%" Pd ":%" Pd, info_number_, suffix_length_); |
| 1222 } | 776 } |
| 1223 | 777 |
| 1224 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 778 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 1225 // The deoptimization info is uncompressed by translating away suffixes | 779 // The deoptimization info is uncompressed by translating away suffixes |
| 1226 // before executing the instructions. | 780 // before executing the instructions. |
| 1227 UNREACHABLE(); | 781 UNREACHABLE(); |
| 1228 } | 782 } |
| 1229 | 783 |
| 1230 private: | 784 private: |
| 1231 // Static decoder functions in DeoptInstr have access to the bitfield | 785 // Static decoder functions in DeoptInstr have access to the bitfield |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1248 class DeoptMaterializedObjectRefInstr : public DeoptInstr { | 802 class DeoptMaterializedObjectRefInstr : public DeoptInstr { |
| 1249 public: | 803 public: |
| 1250 explicit DeoptMaterializedObjectRefInstr(intptr_t index) | 804 explicit DeoptMaterializedObjectRefInstr(intptr_t index) |
| 1251 : index_(index) { | 805 : index_(index) { |
| 1252 ASSERT(index >= 0); | 806 ASSERT(index >= 0); |
| 1253 } | 807 } |
| 1254 | 808 |
| 1255 virtual intptr_t source_index() const { return index_; } | 809 virtual intptr_t source_index() const { return index_; } |
| 1256 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } | 810 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } |
| 1257 | 811 |
| 1258 virtual const char* ToCString() const { | 812 virtual const char* ArgumentsToCString() const { |
| 1259 return Isolate::Current()->current_zone()->PrintToString( | 813 return Isolate::Current()->current_zone()->PrintToString( |
| 1260 "mat ref #%" Pd "", index_); | 814 "#%" Pd "", index_); |
| 1261 } | 815 } |
| 1262 | 816 |
| 1263 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 817 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 1264 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | 818 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 1265 deopt_context->DeferMaterializedObjectRef( | 819 deopt_context->DeferMaterializedObjectRef( |
| 1266 index_, dest_addr); | 820 index_, dest_addr); |
| 1267 } | 821 } |
| 1268 | 822 |
| 1269 private: | 823 private: |
| 1270 intptr_t index_; | 824 intptr_t index_; |
| 1271 | 825 |
| 1272 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); | 826 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); |
| 1273 }; | 827 }; |
| 1274 | 828 |
| 1275 | 829 |
| 1276 // Materialize object with the given number of fields. | 830 // Materialize object with the given number of fields. |
| 1277 // Arguments for materialization (class and field-value pairs) are pushed | 831 // Arguments for materialization (class and field-value pairs) are pushed |
| 1278 // to the expression stack of the bottom-most frame. | 832 // to the expression stack of the bottom-most frame. |
| 1279 class DeoptMaterializeObjectInstr : public DeoptInstr { | 833 class DeoptMaterializeObjectInstr : public DeoptInstr { |
| 1280 public: | 834 public: |
| 1281 explicit DeoptMaterializeObjectInstr(intptr_t field_count) | 835 explicit DeoptMaterializeObjectInstr(intptr_t field_count) |
| 1282 : field_count_(field_count) { | 836 : field_count_(field_count) { |
| 1283 ASSERT(field_count >= 0); | 837 ASSERT(field_count >= 0); |
| 1284 } | 838 } |
| 1285 | 839 |
| 1286 virtual intptr_t source_index() const { return field_count_; } | 840 virtual intptr_t source_index() const { return field_count_; } |
| 1287 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } | 841 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } |
| 1288 | 842 |
| 1289 virtual const char* ToCString() const { | 843 virtual const char* ArgumentsToCString() const { |
| 1290 return Isolate::Current()->current_zone()->PrintToString( | 844 return Isolate::Current()->current_zone()->PrintToString( |
| 1291 "mat obj len:%" Pd "", field_count_); | 845 "%" Pd "", field_count_); |
| 1292 } | 846 } |
| 1293 | 847 |
| 1294 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 848 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 1295 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. | 849 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. |
| 1296 UNREACHABLE(); | 850 UNREACHABLE(); |
| 1297 } | 851 } |
| 1298 | 852 |
| 1299 private: | 853 private: |
| 1300 intptr_t field_count_; | 854 intptr_t field_count_; |
| 1301 | 855 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1326 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), | 880 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), |
| 1327 RawPcDescriptors::kDeopt); | 881 RawPcDescriptors::kDeopt); |
| 1328 ASSERT(res != 0); | 882 ASSERT(res != 0); |
| 1329 return res; | 883 return res; |
| 1330 } | 884 } |
| 1331 | 885 |
| 1332 | 886 |
| 1333 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { | 887 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { |
| 1334 Kind kind = static_cast<Kind>(kind_as_int); | 888 Kind kind = static_cast<Kind>(kind_as_int); |
| 1335 switch (kind) { | 889 switch (kind) { |
| 1336 case kStackSlot: return new DeoptStackSlotInstr(source_index); | 890 case kWord: |
| 1337 case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(source_index); | 891 return new DeoptWordInstr(source_index); |
| 1338 case kFloat32x4StackSlot: | 892 case kDouble: |
| 1339 return new DeoptFloat32x4StackSlotInstr(source_index); | 893 return new DeoptDoubleInstr(source_index); |
| 1340 case kFloat64x2StackSlot: | 894 case kMintPair: |
| 1341 return new DeoptFloat64x2StackSlotInstr(source_index); | 895 return new DeoptMintPairInstr(source_index); |
| 1342 case kInt32x4StackSlot: | 896 case kUint32: |
| 1343 return new DeoptInt32x4StackSlotInstr(source_index); | 897 return new DeoptUint32Instr(source_index); |
| 1344 case kRetAddress: return new DeoptRetAddressInstr(source_index); | 898 case kFloat32x4: |
| 1345 case kConstant: return new DeoptConstantInstr(source_index); | 899 return new DeoptFloat32x4Instr(source_index); |
| 1346 case kRegister: return new DeoptRegisterInstr(source_index); | 900 case kFloat64x2: |
| 1347 case kFpuRegister: return new DeoptFpuRegisterInstr(source_index); | 901 return new DeoptFloat64x2Instr(source_index); |
| 1348 case kMintRegisterPair: { | 902 case kInt32x4: |
| 1349 intptr_t lo_reg_as_int = | 903 return new DeoptInt32x4Instr(source_index); |
| 1350 DeoptMintRegisterPairInstr::LoRegister::decode(source_index); | 904 case kRetAddress: |
| 1351 intptr_t hi_reg_as_int = | 905 return new DeoptRetAddressInstr(source_index); |
| 1352 DeoptMintRegisterPairInstr::HiRegister::decode(source_index); | 906 case kConstant: |
| 1353 return new DeoptMintRegisterPairInstr(lo_reg_as_int, hi_reg_as_int); | 907 return new DeoptConstantInstr(source_index); |
| 1354 } | 908 case kPcMarker: |
| 1355 case kMintStackSlotPair: { | 909 return new DeoptPcMarkerInstr(source_index); |
| 1356 intptr_t lo_slot = | 910 case kPp: |
| 1357 DeoptMintStackSlotPairInstr::LoSlot::decode(source_index); | 911 return new DeoptPpInstr(source_index); |
| 1358 intptr_t hi_slot = | 912 case kCallerFp: |
| 1359 DeoptMintStackSlotPairInstr::HiSlot::decode(source_index); | 913 return new DeoptCallerFpInstr(); |
| 1360 return new DeoptMintStackSlotPairInstr(lo_slot, hi_slot); | 914 case kCallerPp: |
| 1361 } | 915 return new DeoptCallerPpInstr(); |
| 1362 case kMintStackSlotRegister: { | 916 case kCallerPc: |
| 1363 intptr_t slot = | 917 return new DeoptCallerPcInstr(); |
| 1364 DeoptMintStackSlotRegisterInstr::Slot::decode(source_index); | 918 case kSuffix: |
| 1365 intptr_t reg_as_int = | 919 return new DeoptSuffixInstr(source_index); |
| 1366 DeoptMintStackSlotRegisterInstr::Reg::decode(source_index); | |
| 1367 bool flip = DeoptMintStackSlotRegisterInstr::Flip::decode(source_index); | |
| 1368 return new DeoptMintStackSlotRegisterInstr(slot, reg_as_int, flip); | |
| 1369 } | |
| 1370 case kUint32Register: | |
| 1371 return new DeoptUint32RegisterInstr(source_index); | |
| 1372 case kUint32StackSlot: | |
| 1373 return new DeoptUint32StackSlotInstr(source_index); | |
| 1374 case kFloat32x4FpuRegister: | |
| 1375 return new DeoptFloat32x4FpuRegisterInstr(source_index); | |
| 1376 case kFloat64x2FpuRegister: | |
| 1377 return new DeoptFloat64x2FpuRegisterInstr(source_index); | |
| 1378 case kInt32x4FpuRegister: | |
| 1379 return new DeoptInt32x4FpuRegisterInstr(source_index); | |
| 1380 case kPcMarker: return new DeoptPcMarkerInstr(source_index); | |
| 1381 case kPp: return new DeoptPpInstr(source_index); | |
| 1382 case kCallerFp: return new DeoptCallerFpInstr(); | |
| 1383 case kCallerPp: return new DeoptCallerPpInstr(); | |
| 1384 case kCallerPc: return new DeoptCallerPcInstr(); | |
| 1385 case kSuffix: return new DeoptSuffixInstr(source_index); | |
| 1386 case kMaterializedObjectRef: | 920 case kMaterializedObjectRef: |
| 1387 return new DeoptMaterializedObjectRefInstr(source_index); | 921 return new DeoptMaterializedObjectRefInstr(source_index); |
| 1388 case kMaterializeObject: | 922 case kMaterializeObject: |
| 1389 return new DeoptMaterializeObjectInstr(source_index); | 923 return new DeoptMaterializeObjectInstr(source_index); |
| 1390 } | 924 } |
| 1391 UNREACHABLE(); | 925 UNREACHABLE(); |
| 1392 return NULL; | 926 return NULL; |
| 1393 } | 927 } |
| 1394 | 928 |
| 1395 | 929 |
| 930 const char* DeoptInstr::KindToCString(Kind kind) { |
| 931 switch (kind) { |
| 932 case kWord: |
| 933 return "word"; |
| 934 case kDouble: |
| 935 return "double"; |
| 936 case kMintPair: |
| 937 return "mint"; |
| 938 case kUint32: |
| 939 return "uint32"; |
| 940 case kFloat32x4: |
| 941 return "float32x4"; |
| 942 case kFloat64x2: |
| 943 return "float64x2"; |
| 944 case kInt32x4: |
| 945 return "int32x4"; |
| 946 case kRetAddress: |
| 947 return "retaddr"; |
| 948 case kConstant: |
| 949 return "const"; |
| 950 case kPcMarker: |
| 951 return "pc"; |
| 952 case kPp: |
| 953 return "pp"; |
| 954 case kCallerFp: |
| 955 return "callerfp"; |
| 956 case kCallerPp: |
| 957 return "callerpp"; |
| 958 case kCallerPc: |
| 959 return "callerpc"; |
| 960 case kSuffix: |
| 961 return "suffix"; |
| 962 case kMaterializedObjectRef: |
| 963 return "ref"; |
| 964 case kMaterializeObject: |
| 965 return "mat"; |
| 966 } |
| 967 UNREACHABLE(); |
| 968 return NULL; |
| 969 } |
| 970 |
| 971 |
| 1396 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { | 972 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { |
| 1397 public: | 973 public: |
| 1398 // Construct the root node representing the implicit "shared" terminator | 974 // Construct the root node representing the implicit "shared" terminator |
| 1399 // at the end of each deopt info. | 975 // at the end of each deopt info. |
| 1400 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) { } | 976 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) { } |
| 1401 | 977 |
| 1402 // Construct a node representing a written instruction. | 978 // Construct a node representing a written instruction. |
| 1403 TrieNode(DeoptInstr* instruction, intptr_t info_number) | 979 TrieNode(DeoptInstr* instruction, intptr_t info_number) |
| 1404 : instruction_(instruction), info_number_(info_number), children_(4) { } | 980 : instruction_(instruction), info_number_(info_number), children_(4) { } |
| 1405 | 981 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1452 | 1028 |
| 1453 | 1029 |
| 1454 intptr_t DeoptInfoBuilder::CalculateStackIndex( | 1030 intptr_t DeoptInfoBuilder::CalculateStackIndex( |
| 1455 const Location& source_loc) const { | 1031 const Location& source_loc) const { |
| 1456 return source_loc.stack_index() < 0 ? | 1032 return source_loc.stack_index() < 0 ? |
| 1457 source_loc.stack_index() + num_args_ : | 1033 source_loc.stack_index() + num_args_ : |
| 1458 source_loc.stack_index() + num_args_ + kDartFrameFixedSize; | 1034 source_loc.stack_index() + num_args_ + kDartFrameFixedSize; |
| 1459 } | 1035 } |
| 1460 | 1036 |
| 1461 | 1037 |
| 1038 CpuRegisterSource DeoptInfoBuilder::ToCpuRegisterSource(const Location& loc) { |
| 1039 if (loc.IsRegister()) { |
| 1040 return CpuRegisterSource(CpuRegisterSource::kRegister, loc.reg()); |
| 1041 } else { |
| 1042 ASSERT(loc.IsStackSlot()); |
| 1043 return CpuRegisterSource( |
| 1044 CpuRegisterSource::kStackSlot, CalculateStackIndex(loc)); |
| 1045 } |
| 1046 } |
| 1047 |
| 1048 |
| 1049 FpuRegisterSource DeoptInfoBuilder::ToFpuRegisterSource( |
| 1050 const Location& loc, |
| 1051 Location::Kind stack_slot_kind) { |
| 1052 if (loc.IsFpuRegister()) { |
| 1053 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); |
| 1054 } else { |
| 1055 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || |
| 1056 (stack_slot_kind == Location::kDoubleStackSlot)); |
| 1057 ASSERT(loc.kind() == stack_slot_kind); |
| 1058 return FpuRegisterSource( |
| 1059 FpuRegisterSource::kStackSlot, CalculateStackIndex(loc)); |
| 1060 } |
| 1061 } |
| 1062 |
| 1462 void DeoptInfoBuilder::AddReturnAddress(const Code& code, | 1063 void DeoptInfoBuilder::AddReturnAddress(const Code& code, |
| 1463 intptr_t deopt_id, | 1064 intptr_t deopt_id, |
| 1464 intptr_t dest_index) { | 1065 intptr_t dest_index) { |
| 1465 // Check that deopt_id exists. | 1066 // Check that deopt_id exists. |
| 1466 // TODO(vegorov): verify after deoptimization targets as well. | 1067 // TODO(vegorov): verify after deoptimization targets as well. |
| 1467 #ifdef DEBUG | 1068 #ifdef DEBUG |
| 1468 ASSERT(Isolate::IsDeoptAfter(deopt_id) || | 1069 ASSERT(Isolate::IsDeoptAfter(deopt_id) || |
| 1469 (code.GetPcForDeoptId(deopt_id, RawPcDescriptors::kDeopt) != 0)); | 1070 (code.GetPcForDeoptId(deopt_id, RawPcDescriptors::kDeopt) != 0)); |
| 1470 #endif | 1071 #endif |
| 1471 const intptr_t object_table_index = FindOrAddObjectInTable(code); | 1072 const intptr_t object_table_index = FindOrAddObjectInTable(code); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1491 } | 1092 } |
| 1492 | 1093 |
| 1493 | 1094 |
| 1494 void DeoptInfoBuilder::AddCopy(Value* value, | 1095 void DeoptInfoBuilder::AddCopy(Value* value, |
| 1495 const Location& source_loc, | 1096 const Location& source_loc, |
| 1496 const intptr_t dest_index) { | 1097 const intptr_t dest_index) { |
| 1497 DeoptInstr* deopt_instr = NULL; | 1098 DeoptInstr* deopt_instr = NULL; |
| 1498 if (source_loc.IsConstant()) { | 1099 if (source_loc.IsConstant()) { |
| 1499 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); | 1100 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); |
| 1500 deopt_instr = new(isolate()) DeoptConstantInstr(object_table_index); | 1101 deopt_instr = new(isolate()) DeoptConstantInstr(object_table_index); |
| 1501 } else if (source_loc.IsRegister()) { | |
| 1502 if (value->definition()->representation() == kUnboxedUint32) { | |
| 1503 deopt_instr = new(isolate()) DeoptUint32RegisterInstr(source_loc.reg()); | |
| 1504 } else { | |
| 1505 ASSERT(value->definition()->representation() == kTagged); | |
| 1506 deopt_instr = new(isolate()) DeoptRegisterInstr(source_loc.reg()); | |
| 1507 } | |
| 1508 } else if (source_loc.IsFpuRegister()) { | |
| 1509 if (value->definition()->representation() == kUnboxedDouble) { | |
| 1510 deopt_instr = new(isolate()) DeoptFpuRegisterInstr(source_loc.fpu_reg()); | |
| 1511 } else if (value->definition()->representation() == kUnboxedFloat32x4) { | |
| 1512 deopt_instr = | |
| 1513 new(isolate()) DeoptFloat32x4FpuRegisterInstr(source_loc.fpu_reg()); | |
| 1514 } else if (value->definition()->representation() == kUnboxedInt32x4) { | |
| 1515 deopt_instr = | |
| 1516 new(isolate()) DeoptInt32x4FpuRegisterInstr(source_loc.fpu_reg()); | |
| 1517 } else { | |
| 1518 ASSERT(value->definition()->representation() == kUnboxedFloat64x2); | |
| 1519 deopt_instr = | |
| 1520 new(isolate()) DeoptFloat64x2FpuRegisterInstr(source_loc.fpu_reg()); | |
| 1521 } | |
| 1522 } else if (source_loc.IsStackSlot()) { | |
| 1523 if (value->definition()->representation() == kUnboxedUint32) { | |
| 1524 intptr_t source_index = CalculateStackIndex(source_loc); | |
| 1525 deopt_instr = new(isolate()) DeoptUint32StackSlotInstr(source_index); | |
| 1526 } else { | |
| 1527 ASSERT(value->definition()->representation() == kTagged); | |
| 1528 intptr_t source_index = CalculateStackIndex(source_loc); | |
| 1529 deopt_instr = new(isolate()) DeoptStackSlotInstr(source_index); | |
| 1530 } | |
| 1531 } else if (source_loc.IsDoubleStackSlot()) { | |
| 1532 ASSERT(value->definition()->representation() == kUnboxedDouble); | |
| 1533 intptr_t source_index = CalculateStackIndex(source_loc); | |
| 1534 deopt_instr = new(isolate()) DeoptDoubleStackSlotInstr(source_index); | |
| 1535 } else if (source_loc.IsQuadStackSlot()) { | |
| 1536 intptr_t source_index = CalculateStackIndex(source_loc); | |
| 1537 if (value->definition()->representation() == kUnboxedFloat32x4) { | |
| 1538 deopt_instr = new(isolate()) DeoptFloat32x4StackSlotInstr(source_index); | |
| 1539 } else if (value->definition()->representation() == kUnboxedInt32x4) { | |
| 1540 deopt_instr = new(isolate()) DeoptInt32x4StackSlotInstr(source_index); | |
| 1541 } else { | |
| 1542 ASSERT(value->definition()->representation() == kUnboxedFloat64x2); | |
| 1543 deopt_instr = new(isolate()) DeoptFloat64x2StackSlotInstr(source_index); | |
| 1544 } | |
| 1545 } else if (source_loc.IsPairLocation()) { | |
| 1546 ASSERT(value->definition()->representation() == kUnboxedMint); | |
| 1547 // There are four cases to consider here: | |
| 1548 // (R = Register, S = Stack slot). | |
| 1549 // 1) R, R. | |
| 1550 // 2) S, S. | |
| 1551 // 3) R, S. | |
| 1552 // 4) S, R. | |
| 1553 PairLocation* pair = source_loc.AsPairLocation(); | |
| 1554 if (pair->At(0).IsRegister() && pair->At(1).IsRegister()) { | |
| 1555 deopt_instr = | |
| 1556 new(isolate()) DeoptMintRegisterPairInstr(pair->At(0).reg(), | |
| 1557 pair->At(1).reg()); | |
| 1558 } else if (pair->At(0).IsStackSlot() && pair->At(1).IsStackSlot()) { | |
| 1559 deopt_instr = new(isolate()) DeoptMintStackSlotPairInstr( | |
| 1560 CalculateStackIndex(pair->At(0)), | |
| 1561 CalculateStackIndex(pair->At(1))); | |
| 1562 } else if (pair->At(0).IsRegister() && pair->At(1).IsStackSlot()) { | |
| 1563 deopt_instr = new(isolate()) DeoptMintStackSlotRegisterInstr( | |
| 1564 CalculateStackIndex(pair->At(1)), | |
| 1565 pair->At(0).reg(), | |
| 1566 true); | |
| 1567 } else { | |
| 1568 ASSERT(pair->At(0).IsStackSlot() && pair->At(1).IsRegister()); | |
| 1569 deopt_instr = new(isolate()) DeoptMintStackSlotRegisterInstr( | |
| 1570 CalculateStackIndex(pair->At(0)), | |
| 1571 pair->At(1).reg(), | |
| 1572 false); | |
| 1573 } | |
| 1574 } else if (source_loc.IsInvalid() && | 1102 } else if (source_loc.IsInvalid() && |
| 1575 value->definition()->IsMaterializeObject()) { | 1103 value->definition()->IsMaterializeObject()) { |
| 1576 const intptr_t index = FindMaterialization( | 1104 const intptr_t index = FindMaterialization( |
| 1577 value->definition()->AsMaterializeObject()); | 1105 value->definition()->AsMaterializeObject()); |
| 1578 ASSERT(index >= 0); | 1106 ASSERT(index >= 0); |
| 1579 deopt_instr = new(isolate()) DeoptMaterializedObjectRefInstr(index); | 1107 deopt_instr = new(isolate()) DeoptMaterializedObjectRefInstr(index); |
| 1580 } else { | 1108 } else { |
| 1581 UNREACHABLE(); | 1109 ASSERT(!source_loc.IsInvalid()); |
| 1110 switch (value->definition()->representation()) { |
| 1111 case kTagged: |
| 1112 deopt_instr = new(isolate()) DeoptWordInstr( |
| 1113 ToCpuRegisterSource(source_loc)); |
| 1114 break; |
| 1115 case kUnboxedMint: { |
| 1116 ASSERT(source_loc.IsPairLocation()); |
| 1117 PairLocation* pair = source_loc.AsPairLocation(); |
| 1118 deopt_instr = new(isolate()) DeoptMintPairInstr( |
| 1119 ToCpuRegisterSource(pair->At(0)), |
| 1120 ToCpuRegisterSource(pair->At(1))); |
| 1121 break; |
| 1122 } |
| 1123 case kUnboxedUint32: |
| 1124 deopt_instr = new(isolate()) DeoptUint32Instr( |
| 1125 ToCpuRegisterSource(source_loc)); |
| 1126 break; |
| 1127 case kUnboxedDouble: |
| 1128 deopt_instr = new(isolate()) DeoptDoubleInstr( |
| 1129 ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot)); |
| 1130 break; |
| 1131 case kUnboxedFloat32x4: |
| 1132 deopt_instr = new(isolate()) DeoptFloat32x4Instr( |
| 1133 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
| 1134 break; |
| 1135 case kUnboxedFloat64x2: |
| 1136 deopt_instr = new(isolate()) DeoptFloat64x2Instr( |
| 1137 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
| 1138 break; |
| 1139 case kUnboxedInt32x4: |
| 1140 deopt_instr = new(isolate()) DeoptInt32x4Instr( |
| 1141 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
| 1142 break; |
| 1143 default: |
| 1144 UNREACHABLE(); |
| 1145 break; |
| 1146 } |
| 1582 } | 1147 } |
| 1583 ASSERT(dest_index == FrameSize()); | 1148 ASSERT(dest_index == FrameSize()); |
| 1584 ASSERT(deopt_instr != NULL); | 1149 ASSERT(deopt_instr != NULL); |
| 1585 instructions_.Add(deopt_instr); | 1150 instructions_.Add(deopt_instr); |
| 1586 } | 1151 } |
| 1587 | 1152 |
| 1588 | 1153 |
| 1589 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { | 1154 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { |
| 1590 ASSERT(dest_index == FrameSize()); | 1155 ASSERT(dest_index == FrameSize()); |
| 1591 instructions_.Add(new(isolate()) DeoptCallerFpInstr()); | 1156 instructions_.Add(new(isolate()) DeoptCallerFpInstr()); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1756 Smi* offset, | 1321 Smi* offset, |
| 1757 DeoptInfo* info, | 1322 DeoptInfo* info, |
| 1758 Smi* reason) { | 1323 Smi* reason) { |
| 1759 intptr_t i = index * kEntrySize; | 1324 intptr_t i = index * kEntrySize; |
| 1760 *offset ^= table.At(i); | 1325 *offset ^= table.At(i); |
| 1761 *info ^= table.At(i + 1); | 1326 *info ^= table.At(i + 1); |
| 1762 *reason ^= table.At(i + 2); | 1327 *reason ^= table.At(i + 2); |
| 1763 } | 1328 } |
| 1764 | 1329 |
| 1765 } // namespace dart | 1330 } // namespace dart |
| OLD | NEW |