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 |