| 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" |
| 11 #include "vm/parser.h" | 11 #include "vm/parser.h" |
| 12 #include "vm/stack_frame.h" | 12 #include "vm/stack_frame.h" |
| 13 #include "vm/thread.h" |
| 13 | 14 |
| 14 namespace dart { | 15 namespace dart { |
| 15 | 16 |
| 16 DEFINE_FLAG(bool, compress_deopt_info, true, | 17 DEFINE_FLAG(bool, compress_deopt_info, true, |
| 17 "Compress the size of the deoptimization info for optimized code."); | 18 "Compress the size of the deoptimization info for optimized code."); |
| 18 DECLARE_FLAG(bool, trace_deoptimization); | 19 DECLARE_FLAG(bool, trace_deoptimization); |
| 19 DECLARE_FLAG(bool, trace_deoptimization_verbose); | 20 DECLARE_FLAG(bool, trace_deoptimization_verbose); |
| 20 | 21 |
| 21 | 22 |
| 22 DeoptContext::DeoptContext(const StackFrame* frame, | 23 DeoptContext::DeoptContext(const StackFrame* frame, |
| 23 const Code& code, | 24 const Code& code, |
| 24 DestFrameOptions dest_options, | 25 DestFrameOptions dest_options, |
| 25 fpu_register_t* fpu_registers, | 26 fpu_register_t* fpu_registers, |
| 26 intptr_t* cpu_registers) | 27 intptr_t* cpu_registers) |
| 27 : code_(code.raw()), | 28 : code_(code.raw()), |
| 28 object_table_(code.object_table()), | 29 object_table_(code.object_table()), |
| 29 deopt_info_(DeoptInfo::null()), | 30 deopt_info_(DeoptInfo::null()), |
| 30 dest_frame_is_allocated_(false), | 31 dest_frame_is_allocated_(false), |
| 31 dest_frame_(NULL), | 32 dest_frame_(NULL), |
| 32 dest_frame_size_(0), | 33 dest_frame_size_(0), |
| 33 source_frame_is_allocated_(false), | 34 source_frame_is_allocated_(false), |
| 34 source_frame_(NULL), | 35 source_frame_(NULL), |
| 35 source_frame_size_(0), | 36 source_frame_size_(0), |
| 36 cpu_registers_(cpu_registers), | 37 cpu_registers_(cpu_registers), |
| 37 fpu_registers_(fpu_registers), | 38 fpu_registers_(fpu_registers), |
| 38 num_args_(0), | 39 num_args_(0), |
| 39 deopt_reason_(ICData::kDeoptUnknown), | 40 deopt_reason_(ICData::kDeoptUnknown), |
| 40 deopt_flags_(0), | 41 deopt_flags_(0), |
| 41 isolate_(Isolate::Current()), | 42 thread_(Thread::Current()), |
| 42 deferred_slots_(NULL), | 43 deferred_slots_(NULL), |
| 43 deferred_objects_count_(0), | 44 deferred_objects_count_(0), |
| 44 deferred_objects_(NULL) { | 45 deferred_objects_(NULL) { |
| 45 const DeoptInfo& deopt_info = DeoptInfo::Handle( | 46 const DeoptInfo& deopt_info = DeoptInfo::Handle( |
| 46 code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason_, &deopt_flags_)); | 47 code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason_, &deopt_flags_)); |
| 47 ASSERT(!deopt_info.IsNull()); | 48 ASSERT(!deopt_info.IsNull()); |
| 48 deopt_info_ = deopt_info.raw(); | 49 deopt_info_ = deopt_info.raw(); |
| 49 | 50 |
| 50 const Function& function = Function::Handle(code.function()); | 51 const Function& function = Function::Handle(code.function()); |
| 51 | 52 |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 OS::PrintErr(" Deopt args: %" Pd "\n", deopt_arg_count); | 332 OS::PrintErr(" Deopt args: %" Pd "\n", deopt_arg_count); |
| 332 } | 333 } |
| 333 | 334 |
| 334 return deopt_arg_count; | 335 return deopt_arg_count; |
| 335 } | 336 } |
| 336 | 337 |
| 337 | 338 |
| 338 RawArray* DeoptContext::DestFrameAsArray() { | 339 RawArray* DeoptContext::DestFrameAsArray() { |
| 339 ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_); | 340 ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_); |
| 340 const Array& dest_array = | 341 const Array& dest_array = |
| 341 Array::Handle(isolate(), Array::New(dest_frame_size_)); | 342 Array::Handle(zone(), Array::New(dest_frame_size_)); |
| 342 PassiveObject& obj = PassiveObject::Handle(isolate()); | 343 PassiveObject& obj = PassiveObject::Handle(zone()); |
| 343 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 344 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
| 344 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); | 345 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); |
| 345 dest_array.SetAt(i, obj); | 346 dest_array.SetAt(i, obj); |
| 346 } | 347 } |
| 347 return dest_array.raw(); | 348 return dest_array.raw(); |
| 348 } | 349 } |
| 349 | 350 |
| 350 | 351 |
| 351 // Deoptimization instruction creating return address using function and | 352 // Deoptimization instruction creating return address using function and |
| 352 // deopt-id stored at 'object_table_index'. | 353 // deopt-id stored at 'object_table_index'. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 364 } | 365 } |
| 365 | 366 |
| 366 virtual intptr_t source_index() const { | 367 virtual intptr_t source_index() const { |
| 367 return ObjectTableIndex::encode(object_table_index_) | | 368 return ObjectTableIndex::encode(object_table_index_) | |
| 368 DeoptId::encode(deopt_id_); | 369 DeoptId::encode(deopt_id_); |
| 369 } | 370 } |
| 370 | 371 |
| 371 virtual DeoptInstr::Kind kind() const { return kRetAddress; } | 372 virtual DeoptInstr::Kind kind() const { return kRetAddress; } |
| 372 | 373 |
| 373 virtual const char* ArgumentsToCString() const { | 374 virtual const char* ArgumentsToCString() const { |
| 374 return Isolate::Current()->current_zone()->PrintToString( | 375 return Thread::Current()->zone()->PrintToString( |
| 375 "%" Pd ", %" Pd "", object_table_index_, deopt_id_); | 376 "%" Pd ", %" Pd "", object_table_index_, deopt_id_); |
| 376 } | 377 } |
| 377 | 378 |
| 378 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 379 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 379 Code& code = Code::Handle(deopt_context->isolate()); | 380 Code& code = Code::Handle(deopt_context->zone()); |
| 380 code ^= deopt_context->ObjectAt(object_table_index_); | 381 code ^= deopt_context->ObjectAt(object_table_index_); |
| 381 ASSERT(!code.IsNull()); | 382 ASSERT(!code.IsNull()); |
| 382 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, | 383 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, |
| 383 RawPcDescriptors::kDeopt); | 384 RawPcDescriptors::kDeopt); |
| 384 ASSERT(continue_at_pc != 0); | 385 ASSERT(continue_at_pc != 0); |
| 385 *dest_addr = continue_at_pc; | 386 *dest_addr = continue_at_pc; |
| 386 | 387 |
| 387 uword pc = code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kIcCall); | 388 uword pc = code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kIcCall); |
| 388 if (pc != 0) { | 389 if (pc != 0) { |
| 389 // If the deoptimization happened at an IC call, update the IC data | 390 // If the deoptimization happened at an IC call, update the IC data |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 public: | 427 public: |
| 427 explicit DeoptConstantInstr(intptr_t object_table_index) | 428 explicit DeoptConstantInstr(intptr_t object_table_index) |
| 428 : object_table_index_(object_table_index) { | 429 : object_table_index_(object_table_index) { |
| 429 ASSERT(object_table_index >= 0); | 430 ASSERT(object_table_index >= 0); |
| 430 } | 431 } |
| 431 | 432 |
| 432 virtual intptr_t source_index() const { return object_table_index_; } | 433 virtual intptr_t source_index() const { return object_table_index_; } |
| 433 virtual DeoptInstr::Kind kind() const { return kConstant; } | 434 virtual DeoptInstr::Kind kind() const { return kConstant; } |
| 434 | 435 |
| 435 virtual const char* ArgumentsToCString() const { | 436 virtual const char* ArgumentsToCString() const { |
| 436 return Isolate::Current()->current_zone()->PrintToString( | 437 return Thread::Current()->zone()->PrintToString( |
| 437 "%" Pd "", object_table_index_); | 438 "%" Pd "", object_table_index_); |
| 438 } | 439 } |
| 439 | 440 |
| 440 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 441 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 441 const PassiveObject& obj = PassiveObject::Handle( | 442 const PassiveObject& obj = PassiveObject::Handle( |
| 442 deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); | 443 deopt_context->zone(), deopt_context->ObjectAt(object_table_index_)); |
| 443 *reinterpret_cast<RawObject**>(dest_addr) = obj.raw(); | 444 *reinterpret_cast<RawObject**>(dest_addr) = obj.raw(); |
| 444 } | 445 } |
| 445 | 446 |
| 446 private: | 447 private: |
| 447 const intptr_t object_table_index_; | 448 const intptr_t object_table_index_; |
| 448 | 449 |
| 449 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | 450 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); |
| 450 }; | 451 }; |
| 451 | 452 |
| 452 | 453 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) | 516 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) |
| 516 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} | 517 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} |
| 517 | 518 |
| 518 virtual intptr_t source_index() const { | 519 virtual intptr_t source_index() const { |
| 519 return LoRegister::encode(lo_.source_index()) | | 520 return LoRegister::encode(lo_.source_index()) | |
| 520 HiRegister::encode(hi_.source_index()); | 521 HiRegister::encode(hi_.source_index()); |
| 521 } | 522 } |
| 522 virtual DeoptInstr::Kind kind() const { return kMintPair; } | 523 virtual DeoptInstr::Kind kind() const { return kMintPair; } |
| 523 | 524 |
| 524 virtual const char* ArgumentsToCString() const { | 525 virtual const char* ArgumentsToCString() const { |
| 525 return Isolate::Current()->current_zone()->PrintToString( | 526 return Thread::Current()->zone()->PrintToString( |
| 526 "%s,%s", | 527 "%s,%s", |
| 527 lo_.ToCString(), | 528 lo_.ToCString(), |
| 528 hi_.ToCString()); | 529 hi_.ToCString()); |
| 529 } | 530 } |
| 530 | 531 |
| 531 virtual int64_t GetValue(DeoptContext* deopt_context) { | 532 virtual int64_t GetValue(DeoptContext* deopt_context) { |
| 532 return Utils::LowHighTo64Bits( | 533 return Utils::LowHighTo64Bits( |
| 533 lo_.Value<uint32_t>(deopt_context), hi_.Value<int32_t>(deopt_context)); | 534 lo_.Value<uint32_t>(deopt_context), hi_.Value<int32_t>(deopt_context)); |
| 534 } | 535 } |
| 535 | 536 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 public: | 629 public: |
| 629 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | 630 explicit DeoptPcMarkerInstr(intptr_t object_table_index) |
| 630 : object_table_index_(object_table_index) { | 631 : object_table_index_(object_table_index) { |
| 631 ASSERT(object_table_index >= 0); | 632 ASSERT(object_table_index >= 0); |
| 632 } | 633 } |
| 633 | 634 |
| 634 virtual intptr_t source_index() const { return object_table_index_; } | 635 virtual intptr_t source_index() const { return object_table_index_; } |
| 635 virtual DeoptInstr::Kind kind() const { return kPcMarker; } | 636 virtual DeoptInstr::Kind kind() const { return kPcMarker; } |
| 636 | 637 |
| 637 virtual const char* ArgumentsToCString() const { | 638 virtual const char* ArgumentsToCString() const { |
| 638 return Isolate::Current()->current_zone()->PrintToString( | 639 return Thread::Current()->zone()->PrintToString( |
| 639 "%" Pd "", object_table_index_); | 640 "%" Pd "", object_table_index_); |
| 640 } | 641 } |
| 641 | 642 |
| 642 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 643 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 643 Code& code = Code::Handle(deopt_context->isolate()); | 644 Code& code = Code::Handle(deopt_context->zone()); |
| 644 code ^= deopt_context->ObjectAt(object_table_index_); | 645 code ^= deopt_context->ObjectAt(object_table_index_); |
| 645 if (code.IsNull()) { | 646 if (code.IsNull()) { |
| 646 // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0. | 647 // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0. |
| 647 *dest_addr = 0; | 648 *dest_addr = 0; |
| 648 return; | 649 return; |
| 649 } | 650 } |
| 650 const Function& function = | 651 const Function& function = |
| 651 Function::Handle(deopt_context->isolate(), code.function()); | 652 Function::Handle(deopt_context->zone(), code.function()); |
| 652 ASSERT(function.HasCode()); | 653 ASSERT(function.HasCode()); |
| 653 const intptr_t pc_marker = | 654 const intptr_t pc_marker = |
| 654 code.EntryPoint() + Assembler::EntryPointToPcMarkerOffset(); | 655 code.EntryPoint() + Assembler::EntryPointToPcMarkerOffset(); |
| 655 *dest_addr = pc_marker; | 656 *dest_addr = pc_marker; |
| 656 // Increment the deoptimization counter. This effectively increments each | 657 // Increment the deoptimization counter. This effectively increments each |
| 657 // function occurring in the optimized frame. | 658 // function occurring in the optimized frame. |
| 658 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 659 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
| 659 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | 660 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| 660 OS::PrintErr("Deoptimizing %s (count %d)\n", | 661 OS::PrintErr("Deoptimizing %s (count %d)\n", |
| 661 function.ToFullyQualifiedCString(), | 662 function.ToFullyQualifiedCString(), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 682 public: | 683 public: |
| 683 explicit DeoptPpInstr(intptr_t object_table_index) | 684 explicit DeoptPpInstr(intptr_t object_table_index) |
| 684 : object_table_index_(object_table_index) { | 685 : object_table_index_(object_table_index) { |
| 685 ASSERT(object_table_index >= 0); | 686 ASSERT(object_table_index >= 0); |
| 686 } | 687 } |
| 687 | 688 |
| 688 virtual intptr_t source_index() const { return object_table_index_; } | 689 virtual intptr_t source_index() const { return object_table_index_; } |
| 689 virtual DeoptInstr::Kind kind() const { return kPp; } | 690 virtual DeoptInstr::Kind kind() const { return kPp; } |
| 690 | 691 |
| 691 virtual const char* ArgumentsToCString() const { | 692 virtual const char* ArgumentsToCString() const { |
| 692 return Isolate::Current()->current_zone()->PrintToString( | 693 return Thread::Current()->zone()->PrintToString( |
| 693 "%" Pd "", object_table_index_); | 694 "%" Pd "", object_table_index_); |
| 694 } | 695 } |
| 695 | 696 |
| 696 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 697 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 697 Code& code = Code::Handle(deopt_context->isolate()); | 698 Code& code = Code::Handle(deopt_context->zone()); |
| 698 code ^= deopt_context->ObjectAt(object_table_index_); | 699 code ^= deopt_context->ObjectAt(object_table_index_); |
| 699 ASSERT(!code.IsNull()); | 700 ASSERT(!code.IsNull()); |
| 700 const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool()); | 701 const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool()); |
| 701 *dest_addr = pp; | 702 *dest_addr = pp; |
| 702 } | 703 } |
| 703 | 704 |
| 704 private: | 705 private: |
| 705 intptr_t object_table_index_; | 706 intptr_t object_table_index_; |
| 706 | 707 |
| 707 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); | 708 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 779 suffix_length_(SuffixLength::decode(source_index)) { | 780 suffix_length_(SuffixLength::decode(source_index)) { |
| 780 } | 781 } |
| 781 | 782 |
| 782 virtual intptr_t source_index() const { | 783 virtual intptr_t source_index() const { |
| 783 return InfoNumber::encode(info_number_) | | 784 return InfoNumber::encode(info_number_) | |
| 784 SuffixLength::encode(suffix_length_); | 785 SuffixLength::encode(suffix_length_); |
| 785 } | 786 } |
| 786 virtual DeoptInstr::Kind kind() const { return kSuffix; } | 787 virtual DeoptInstr::Kind kind() const { return kSuffix; } |
| 787 | 788 |
| 788 virtual const char* ArgumentsToCString() const { | 789 virtual const char* ArgumentsToCString() const { |
| 789 return Isolate::Current()->current_zone()->PrintToString( | 790 return Thread::Current()->zone()->PrintToString( |
| 790 "%" Pd ":%" Pd, info_number_, suffix_length_); | 791 "%" Pd ":%" Pd, info_number_, suffix_length_); |
| 791 } | 792 } |
| 792 | 793 |
| 793 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 794 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 794 // The deoptimization info is uncompressed by translating away suffixes | 795 // The deoptimization info is uncompressed by translating away suffixes |
| 795 // before executing the instructions. | 796 // before executing the instructions. |
| 796 UNREACHABLE(); | 797 UNREACHABLE(); |
| 797 } | 798 } |
| 798 | 799 |
| 799 private: | 800 private: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 818 public: | 819 public: |
| 819 explicit DeoptMaterializedObjectRefInstr(intptr_t index) | 820 explicit DeoptMaterializedObjectRefInstr(intptr_t index) |
| 820 : index_(index) { | 821 : index_(index) { |
| 821 ASSERT(index >= 0); | 822 ASSERT(index >= 0); |
| 822 } | 823 } |
| 823 | 824 |
| 824 virtual intptr_t source_index() const { return index_; } | 825 virtual intptr_t source_index() const { return index_; } |
| 825 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } | 826 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } |
| 826 | 827 |
| 827 virtual const char* ArgumentsToCString() const { | 828 virtual const char* ArgumentsToCString() const { |
| 828 return Isolate::Current()->current_zone()->PrintToString( | 829 return Thread::Current()->zone()->PrintToString( |
| 829 "#%" Pd "", index_); | 830 "#%" Pd "", index_); |
| 830 } | 831 } |
| 831 | 832 |
| 832 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 833 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 833 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | 834 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 834 deopt_context->DeferMaterializedObjectRef( | 835 deopt_context->DeferMaterializedObjectRef( |
| 835 index_, dest_addr); | 836 index_, dest_addr); |
| 836 } | 837 } |
| 837 | 838 |
| 838 private: | 839 private: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 849 public: | 850 public: |
| 850 explicit DeoptMaterializeObjectInstr(intptr_t field_count) | 851 explicit DeoptMaterializeObjectInstr(intptr_t field_count) |
| 851 : field_count_(field_count) { | 852 : field_count_(field_count) { |
| 852 ASSERT(field_count >= 0); | 853 ASSERT(field_count >= 0); |
| 853 } | 854 } |
| 854 | 855 |
| 855 virtual intptr_t source_index() const { return field_count_; } | 856 virtual intptr_t source_index() const { return field_count_; } |
| 856 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } | 857 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } |
| 857 | 858 |
| 858 virtual const char* ArgumentsToCString() const { | 859 virtual const char* ArgumentsToCString() const { |
| 859 return Isolate::Current()->current_zone()->PrintToString( | 860 return Thread::Current()->zone()->PrintToString( |
| 860 "%" Pd "", field_count_); | 861 "%" Pd "", field_count_); |
| 861 } | 862 } |
| 862 | 863 |
| 863 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 864 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 864 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. | 865 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. |
| 865 UNREACHABLE(); | 866 UNREACHABLE(); |
| 866 } | 867 } |
| 867 | 868 |
| 868 private: | 869 private: |
| 869 intptr_t field_count_; | 870 intptr_t field_count_; |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 } | 1017 } |
| 1017 | 1018 |
| 1018 private: | 1019 private: |
| 1019 const DeoptInstr* instruction_; // Instruction that was written. | 1020 const DeoptInstr* instruction_; // Instruction that was written. |
| 1020 const intptr_t info_number_; // Index of the deopt info it was written to. | 1021 const intptr_t info_number_; // Index of the deopt info it was written to. |
| 1021 | 1022 |
| 1022 GrowableArray<TrieNode*> children_; | 1023 GrowableArray<TrieNode*> children_; |
| 1023 }; | 1024 }; |
| 1024 | 1025 |
| 1025 | 1026 |
| 1026 DeoptInfoBuilder::DeoptInfoBuilder(Isolate* isolate, const intptr_t num_args) | 1027 DeoptInfoBuilder::DeoptInfoBuilder(Zone* zone, const intptr_t num_args) |
| 1027 : isolate_(isolate), | 1028 : zone_(zone), |
| 1028 instructions_(), | 1029 instructions_(), |
| 1029 object_table_(GrowableObjectArray::Handle( | 1030 object_table_(GrowableObjectArray::Handle( |
| 1030 GrowableObjectArray::New(Heap::kOld))), | 1031 GrowableObjectArray::New(Heap::kOld))), |
| 1031 num_args_(num_args), | 1032 num_args_(num_args), |
| 1032 trie_root_(new(isolate) TrieNode()), | 1033 trie_root_(new(zone) TrieNode()), |
| 1033 current_info_number_(0), | 1034 current_info_number_(0), |
| 1034 frame_start_(-1), | 1035 frame_start_(-1), |
| 1035 materializations_() { | 1036 materializations_() { |
| 1036 } | 1037 } |
| 1037 | 1038 |
| 1038 | 1039 |
| 1039 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { | 1040 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { |
| 1040 for (intptr_t i = 0; i < object_table_.Length(); i++) { | 1041 for (intptr_t i = 0; i < object_table_.Length(); i++) { |
| 1041 if (object_table_.At(i) == obj.raw()) { | 1042 if (object_table_.At(i) == obj.raw()) { |
| 1042 return i; | 1043 return i; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1087 intptr_t dest_index) { | 1088 intptr_t dest_index) { |
| 1088 // Check that deopt_id exists. | 1089 // Check that deopt_id exists. |
| 1089 // TODO(vegorov): verify after deoptimization targets as well. | 1090 // TODO(vegorov): verify after deoptimization targets as well. |
| 1090 #ifdef DEBUG | 1091 #ifdef DEBUG |
| 1091 ASSERT(Isolate::IsDeoptAfter(deopt_id) || | 1092 ASSERT(Isolate::IsDeoptAfter(deopt_id) || |
| 1092 (code.GetPcForDeoptId(deopt_id, RawPcDescriptors::kDeopt) != 0)); | 1093 (code.GetPcForDeoptId(deopt_id, RawPcDescriptors::kDeopt) != 0)); |
| 1093 #endif | 1094 #endif |
| 1094 const intptr_t object_table_index = FindOrAddObjectInTable(code); | 1095 const intptr_t object_table_index = FindOrAddObjectInTable(code); |
| 1095 ASSERT(dest_index == FrameSize()); | 1096 ASSERT(dest_index == FrameSize()); |
| 1096 instructions_.Add( | 1097 instructions_.Add( |
| 1097 new(isolate()) DeoptRetAddressInstr(object_table_index, deopt_id)); | 1098 new(zone()) DeoptRetAddressInstr(object_table_index, deopt_id)); |
| 1098 } | 1099 } |
| 1099 | 1100 |
| 1100 | 1101 |
| 1101 void DeoptInfoBuilder::AddPcMarker(const Code& code, | 1102 void DeoptInfoBuilder::AddPcMarker(const Code& code, |
| 1102 intptr_t dest_index) { | 1103 intptr_t dest_index) { |
| 1103 intptr_t object_table_index = FindOrAddObjectInTable(code); | 1104 intptr_t object_table_index = FindOrAddObjectInTable(code); |
| 1104 ASSERT(dest_index == FrameSize()); | 1105 ASSERT(dest_index == FrameSize()); |
| 1105 instructions_.Add(new(isolate()) DeoptPcMarkerInstr(object_table_index)); | 1106 instructions_.Add(new(zone()) DeoptPcMarkerInstr(object_table_index)); |
| 1106 } | 1107 } |
| 1107 | 1108 |
| 1108 | 1109 |
| 1109 void DeoptInfoBuilder::AddPp(const Code& code, | 1110 void DeoptInfoBuilder::AddPp(const Code& code, |
| 1110 intptr_t dest_index) { | 1111 intptr_t dest_index) { |
| 1111 intptr_t object_table_index = FindOrAddObjectInTable(code); | 1112 intptr_t object_table_index = FindOrAddObjectInTable(code); |
| 1112 ASSERT(dest_index == FrameSize()); | 1113 ASSERT(dest_index == FrameSize()); |
| 1113 instructions_.Add(new(isolate()) DeoptPpInstr(object_table_index)); | 1114 instructions_.Add(new(zone()) DeoptPpInstr(object_table_index)); |
| 1114 } | 1115 } |
| 1115 | 1116 |
| 1116 | 1117 |
| 1117 void DeoptInfoBuilder::AddCopy(Value* value, | 1118 void DeoptInfoBuilder::AddCopy(Value* value, |
| 1118 const Location& source_loc, | 1119 const Location& source_loc, |
| 1119 const intptr_t dest_index) { | 1120 const intptr_t dest_index) { |
| 1120 DeoptInstr* deopt_instr = NULL; | 1121 DeoptInstr* deopt_instr = NULL; |
| 1121 if (source_loc.IsConstant()) { | 1122 if (source_loc.IsConstant()) { |
| 1122 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); | 1123 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); |
| 1123 deopt_instr = new(isolate()) DeoptConstantInstr(object_table_index); | 1124 deopt_instr = new(zone()) DeoptConstantInstr(object_table_index); |
| 1124 } else if (source_loc.IsInvalid() && | 1125 } else if (source_loc.IsInvalid() && |
| 1125 value->definition()->IsMaterializeObject()) { | 1126 value->definition()->IsMaterializeObject()) { |
| 1126 const intptr_t index = FindMaterialization( | 1127 const intptr_t index = FindMaterialization( |
| 1127 value->definition()->AsMaterializeObject()); | 1128 value->definition()->AsMaterializeObject()); |
| 1128 ASSERT(index >= 0); | 1129 ASSERT(index >= 0); |
| 1129 deopt_instr = new(isolate()) DeoptMaterializedObjectRefInstr(index); | 1130 deopt_instr = new(zone()) DeoptMaterializedObjectRefInstr(index); |
| 1130 } else { | 1131 } else { |
| 1131 ASSERT(!source_loc.IsInvalid()); | 1132 ASSERT(!source_loc.IsInvalid()); |
| 1132 switch (value->definition()->representation()) { | 1133 switch (value->definition()->representation()) { |
| 1133 case kTagged: | 1134 case kTagged: |
| 1134 deopt_instr = new(isolate()) DeoptWordInstr( | 1135 deopt_instr = new(zone()) DeoptWordInstr( |
| 1135 ToCpuRegisterSource(source_loc)); | 1136 ToCpuRegisterSource(source_loc)); |
| 1136 break; | 1137 break; |
| 1137 case kUnboxedMint: { | 1138 case kUnboxedMint: { |
| 1138 if (source_loc.IsPairLocation()) { | 1139 if (source_loc.IsPairLocation()) { |
| 1139 PairLocation* pair = source_loc.AsPairLocation(); | 1140 PairLocation* pair = source_loc.AsPairLocation(); |
| 1140 deopt_instr = new(isolate()) DeoptMintPairInstr( | 1141 deopt_instr = new(zone()) DeoptMintPairInstr( |
| 1141 ToCpuRegisterSource(pair->At(0)), | 1142 ToCpuRegisterSource(pair->At(0)), |
| 1142 ToCpuRegisterSource(pair->At(1))); | 1143 ToCpuRegisterSource(pair->At(1))); |
| 1143 } else { | 1144 } else { |
| 1144 ASSERT(!source_loc.IsPairLocation()); | 1145 ASSERT(!source_loc.IsPairLocation()); |
| 1145 deopt_instr = new(isolate()) DeoptMintInstr( | 1146 deopt_instr = new(zone()) DeoptMintInstr( |
| 1146 ToCpuRegisterSource(source_loc)); | 1147 ToCpuRegisterSource(source_loc)); |
| 1147 } | 1148 } |
| 1148 break; | 1149 break; |
| 1149 } | 1150 } |
| 1150 case kUnboxedInt32: | 1151 case kUnboxedInt32: |
| 1151 deopt_instr = new(isolate()) DeoptInt32Instr( | 1152 deopt_instr = new(zone()) DeoptInt32Instr( |
| 1152 ToCpuRegisterSource(source_loc)); | 1153 ToCpuRegisterSource(source_loc)); |
| 1153 break; | 1154 break; |
| 1154 case kUnboxedUint32: | 1155 case kUnboxedUint32: |
| 1155 deopt_instr = new(isolate()) DeoptUint32Instr( | 1156 deopt_instr = new(zone()) DeoptUint32Instr( |
| 1156 ToCpuRegisterSource(source_loc)); | 1157 ToCpuRegisterSource(source_loc)); |
| 1157 break; | 1158 break; |
| 1158 case kUnboxedDouble: | 1159 case kUnboxedDouble: |
| 1159 deopt_instr = new(isolate()) DeoptDoubleInstr( | 1160 deopt_instr = new(zone()) DeoptDoubleInstr( |
| 1160 ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot)); | 1161 ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot)); |
| 1161 break; | 1162 break; |
| 1162 case kUnboxedFloat32x4: | 1163 case kUnboxedFloat32x4: |
| 1163 deopt_instr = new(isolate()) DeoptFloat32x4Instr( | 1164 deopt_instr = new(zone()) DeoptFloat32x4Instr( |
| 1164 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); | 1165 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
| 1165 break; | 1166 break; |
| 1166 case kUnboxedFloat64x2: | 1167 case kUnboxedFloat64x2: |
| 1167 deopt_instr = new(isolate()) DeoptFloat64x2Instr( | 1168 deopt_instr = new(zone()) DeoptFloat64x2Instr( |
| 1168 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); | 1169 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
| 1169 break; | 1170 break; |
| 1170 case kUnboxedInt32x4: | 1171 case kUnboxedInt32x4: |
| 1171 deopt_instr = new(isolate()) DeoptInt32x4Instr( | 1172 deopt_instr = new(zone()) DeoptInt32x4Instr( |
| 1172 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); | 1173 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
| 1173 break; | 1174 break; |
| 1174 default: | 1175 default: |
| 1175 UNREACHABLE(); | 1176 UNREACHABLE(); |
| 1176 break; | 1177 break; |
| 1177 } | 1178 } |
| 1178 } | 1179 } |
| 1179 ASSERT(dest_index == FrameSize()); | 1180 ASSERT(dest_index == FrameSize()); |
| 1180 ASSERT(deopt_instr != NULL); | 1181 ASSERT(deopt_instr != NULL); |
| 1181 instructions_.Add(deopt_instr); | 1182 instructions_.Add(deopt_instr); |
| 1182 } | 1183 } |
| 1183 | 1184 |
| 1184 | 1185 |
| 1185 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { | 1186 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { |
| 1186 ASSERT(dest_index == FrameSize()); | 1187 ASSERT(dest_index == FrameSize()); |
| 1187 instructions_.Add(new(isolate()) DeoptCallerFpInstr()); | 1188 instructions_.Add(new(zone()) DeoptCallerFpInstr()); |
| 1188 } | 1189 } |
| 1189 | 1190 |
| 1190 | 1191 |
| 1191 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { | 1192 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { |
| 1192 ASSERT(dest_index == FrameSize()); | 1193 ASSERT(dest_index == FrameSize()); |
| 1193 instructions_.Add(new(isolate()) DeoptCallerPpInstr()); | 1194 instructions_.Add(new(zone()) DeoptCallerPpInstr()); |
| 1194 } | 1195 } |
| 1195 | 1196 |
| 1196 | 1197 |
| 1197 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { | 1198 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { |
| 1198 ASSERT(dest_index == FrameSize()); | 1199 ASSERT(dest_index == FrameSize()); |
| 1199 instructions_.Add(new(isolate()) DeoptCallerPcInstr()); | 1200 instructions_.Add(new(zone()) DeoptCallerPcInstr()); |
| 1200 } | 1201 } |
| 1201 | 1202 |
| 1202 | 1203 |
| 1203 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { | 1204 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { |
| 1204 ASSERT(dest_index == FrameSize()); | 1205 ASSERT(dest_index == FrameSize()); |
| 1205 intptr_t object_table_index = FindOrAddObjectInTable(obj); | 1206 intptr_t object_table_index = FindOrAddObjectInTable(obj); |
| 1206 instructions_.Add(new(isolate()) DeoptConstantInstr(object_table_index)); | 1207 instructions_.Add(new(zone()) DeoptConstantInstr(object_table_index)); |
| 1207 } | 1208 } |
| 1208 | 1209 |
| 1209 | 1210 |
| 1210 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { | 1211 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { |
| 1211 const intptr_t index = FindMaterialization(mat); | 1212 const intptr_t index = FindMaterialization(mat); |
| 1212 if (index >= 0) { | 1213 if (index >= 0) { |
| 1213 return; // Already added. | 1214 return; // Already added. |
| 1214 } | 1215 } |
| 1215 materializations_.Add(mat); | 1216 materializations_.Add(mat); |
| 1216 | 1217 |
| 1217 // Count initialized fields and emit kMaterializeObject instruction. | 1218 // Count initialized fields and emit kMaterializeObject instruction. |
| 1218 // There is no need to write nulls into fields because object is null | 1219 // There is no need to write nulls into fields because object is null |
| 1219 // initialized by default. | 1220 // initialized by default. |
| 1220 intptr_t non_null_fields = 0; | 1221 intptr_t non_null_fields = 0; |
| 1221 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1222 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 1222 if (!mat->InputAt(i)->BindsToConstantNull()) { | 1223 if (!mat->InputAt(i)->BindsToConstantNull()) { |
| 1223 non_null_fields++; | 1224 non_null_fields++; |
| 1224 } | 1225 } |
| 1225 } | 1226 } |
| 1226 | 1227 |
| 1227 instructions_.Add( | 1228 instructions_.Add( |
| 1228 new(isolate()) DeoptMaterializeObjectInstr(non_null_fields)); | 1229 new(zone()) DeoptMaterializeObjectInstr(non_null_fields)); |
| 1229 | 1230 |
| 1230 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1231 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 1231 MaterializeObjectInstr* nested_mat = mat->InputAt(i)->definition()-> | 1232 MaterializeObjectInstr* nested_mat = mat->InputAt(i)->definition()-> |
| 1232 AsMaterializeObject(); | 1233 AsMaterializeObject(); |
| 1233 if (nested_mat != NULL) { | 1234 if (nested_mat != NULL) { |
| 1234 AddMaterialization(nested_mat); | 1235 AddMaterialization(nested_mat); |
| 1235 } | 1236 } |
| 1236 } | 1237 } |
| 1237 } | 1238 } |
| 1238 | 1239 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1286 if (node == NULL) break; | 1287 if (node == NULL) break; |
| 1287 suffix = node; | 1288 suffix = node; |
| 1288 ++suffix_length; | 1289 ++suffix_length; |
| 1289 } | 1290 } |
| 1290 } | 1291 } |
| 1291 | 1292 |
| 1292 // Allocate space for the translation. If the shared suffix is longer | 1293 // Allocate space for the translation. If the shared suffix is longer |
| 1293 // than one instruction, we replace it with a single suffix instruction. | 1294 // than one instruction, we replace it with a single suffix instruction. |
| 1294 if (suffix_length > 1) length -= (suffix_length - 1); | 1295 if (suffix_length > 1) length -= (suffix_length - 1); |
| 1295 const DeoptInfo& deopt_info = | 1296 const DeoptInfo& deopt_info = |
| 1296 DeoptInfo::Handle(isolate(), DeoptInfo::New(length)); | 1297 DeoptInfo::Handle(zone(), DeoptInfo::New(length)); |
| 1297 | 1298 |
| 1298 // Write the unshared instructions and build their sub-tree. | 1299 // Write the unshared instructions and build their sub-tree. |
| 1299 TrieNode* node = NULL; | 1300 TrieNode* node = NULL; |
| 1300 intptr_t write_count = (suffix_length > 1) ? length - 1 : length; | 1301 intptr_t write_count = (suffix_length > 1) ? length - 1 : length; |
| 1301 for (intptr_t i = 0; i < write_count; ++i) { | 1302 for (intptr_t i = 0; i < write_count; ++i) { |
| 1302 DeoptInstr* instr = instructions_[i]; | 1303 DeoptInstr* instr = instructions_[i]; |
| 1303 deopt_info.SetAt(i, instr->kind(), instr->source_index()); | 1304 deopt_info.SetAt(i, instr->kind(), instr->source_index()); |
| 1304 TrieNode* child = node; | 1305 TrieNode* child = node; |
| 1305 node = new(isolate()) TrieNode(instr, current_info_number_); | 1306 node = new(zone()) TrieNode(instr, current_info_number_); |
| 1306 node->AddChild(child); | 1307 node->AddChild(child); |
| 1307 } | 1308 } |
| 1308 | 1309 |
| 1309 if (suffix_length > 1) { | 1310 if (suffix_length > 1) { |
| 1310 suffix->AddChild(node); | 1311 suffix->AddChild(node); |
| 1311 DeoptInstr* instr = | 1312 DeoptInstr* instr = |
| 1312 new(isolate()) DeoptSuffixInstr(suffix->info_number(), suffix_length); | 1313 new(zone()) DeoptSuffixInstr(suffix->info_number(), suffix_length); |
| 1313 deopt_info.SetAt(length - 1, instr->kind(), instr->source_index()); | 1314 deopt_info.SetAt(length - 1, instr->kind(), instr->source_index()); |
| 1314 } else { | 1315 } else { |
| 1315 trie_root_->AddChild(node); | 1316 trie_root_->AddChild(node); |
| 1316 } | 1317 } |
| 1317 | 1318 |
| 1318 ASSERT(deopt_info.VerifyDecompression(instructions_, deopt_table)); | 1319 ASSERT(deopt_info.VerifyDecompression(instructions_, deopt_table)); |
| 1319 instructions_.Clear(); | 1320 instructions_.Clear(); |
| 1320 materializations_.Clear(); | 1321 materializations_.Clear(); |
| 1321 frame_start_ = -1; | 1322 frame_start_ = -1; |
| 1322 | 1323 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1353 Smi* offset, | 1354 Smi* offset, |
| 1354 DeoptInfo* info, | 1355 DeoptInfo* info, |
| 1355 Smi* reason) { | 1356 Smi* reason) { |
| 1356 intptr_t i = index * kEntrySize; | 1357 intptr_t i = index * kEntrySize; |
| 1357 *offset ^= table.At(i); | 1358 *offset ^= table.At(i); |
| 1358 *info ^= table.At(i + 1); | 1359 *info ^= table.At(i + 1); |
| 1359 *reason ^= table.At(i + 2); | 1360 *reason ^= table.At(i + 2); |
| 1360 } | 1361 } |
| 1361 | 1362 |
| 1362 } // namespace dart | 1363 } // namespace dart |
| OLD | NEW |