| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/deopt_instructions.h" | 5 #include "vm/deopt_instructions.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/intermediate_language.h" | 10 #include "vm/intermediate_language.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 DECLARE_FLAG(bool, trace_deoptimization_verbose); | 21 DECLARE_FLAG(bool, trace_deoptimization_verbose); |
| 22 | 22 |
| 23 | 23 |
| 24 DeoptContext::DeoptContext(const StackFrame* frame, | 24 DeoptContext::DeoptContext(const StackFrame* frame, |
| 25 const Code& code, | 25 const Code& code, |
| 26 DestFrameOptions dest_options, | 26 DestFrameOptions dest_options, |
| 27 fpu_register_t* fpu_registers, | 27 fpu_register_t* fpu_registers, |
| 28 intptr_t* cpu_registers) | 28 intptr_t* cpu_registers) |
| 29 : code_(code.raw()), | 29 : code_(code.raw()), |
| 30 object_table_(code.object_table()), | 30 object_table_(code.object_table()), |
| 31 deopt_info_(DeoptInfo::null()), | 31 deopt_info_(TypedData::null()), |
| 32 dest_frame_is_allocated_(false), | 32 dest_frame_is_allocated_(false), |
| 33 dest_frame_(NULL), | 33 dest_frame_(NULL), |
| 34 dest_frame_size_(0), | 34 dest_frame_size_(0), |
| 35 source_frame_is_allocated_(false), | 35 source_frame_is_allocated_(false), |
| 36 source_frame_(NULL), | 36 source_frame_(NULL), |
| 37 source_frame_size_(0), | 37 source_frame_size_(0), |
| 38 cpu_registers_(cpu_registers), | 38 cpu_registers_(cpu_registers), |
| 39 fpu_registers_(fpu_registers), | 39 fpu_registers_(fpu_registers), |
| 40 num_args_(0), | 40 num_args_(0), |
| 41 deopt_reason_(ICData::kDeoptUnknown), | 41 deopt_reason_(ICData::kDeoptUnknown), |
| 42 deopt_flags_(0), | 42 deopt_flags_(0), |
| 43 thread_(Thread::Current()), | 43 thread_(Thread::Current()), |
| 44 deferred_slots_(NULL), | 44 deferred_slots_(NULL), |
| 45 deferred_objects_count_(0), | 45 deferred_objects_count_(0), |
| 46 deferred_objects_(NULL) { | 46 deferred_objects_(NULL) { |
| 47 const DeoptInfo& deopt_info = DeoptInfo::Handle( | 47 const TypedData& deopt_info = TypedData::Handle( |
| 48 code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason_, &deopt_flags_)); | 48 code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason_, &deopt_flags_)); |
| 49 ASSERT(!deopt_info.IsNull()); | 49 ASSERT(!deopt_info.IsNull()); |
| 50 deopt_info_ = deopt_info.raw(); | 50 deopt_info_ = deopt_info.raw(); |
| 51 | 51 |
| 52 const Function& function = Function::Handle(code.function()); | 52 const Function& function = Function::Handle(code.function()); |
| 53 | 53 |
| 54 // Do not include incoming arguments if there are optional arguments | 54 // Do not include incoming arguments if there are optional arguments |
| 55 // (they are copied into local space at method entry). | 55 // (they are copied into local space at method entry). |
| 56 num_args_ = | 56 num_args_ = |
| 57 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 57 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 74 intptr_t* original_frame = source_frame_; | 74 intptr_t* original_frame = source_frame_; |
| 75 source_frame_ = new intptr_t[source_frame_size_]; | 75 source_frame_ = new intptr_t[source_frame_size_]; |
| 76 ASSERT(source_frame_ != NULL); | 76 ASSERT(source_frame_ != NULL); |
| 77 for (intptr_t i = 0; i < source_frame_size_; i++) { | 77 for (intptr_t i = 0; i < source_frame_size_; i++) { |
| 78 source_frame_[i] = original_frame[i]; | 78 source_frame_[i] = original_frame[i]; |
| 79 } | 79 } |
| 80 source_frame_is_allocated_ = true; | 80 source_frame_is_allocated_ = true; |
| 81 } | 81 } |
| 82 caller_fp_ = GetSourceFp(); | 82 caller_fp_ = GetSourceFp(); |
| 83 | 83 |
| 84 dest_frame_size_ = deopt_info.FrameSize(); | 84 dest_frame_size_ = DeoptInfo::FrameSize(deopt_info); |
| 85 | 85 |
| 86 if (dest_options == kDestIsAllocated) { | 86 if (dest_options == kDestIsAllocated) { |
| 87 dest_frame_ = new intptr_t[dest_frame_size_]; | 87 dest_frame_ = new intptr_t[dest_frame_size_]; |
| 88 ASSERT(source_frame_ != NULL); | 88 ASSERT(source_frame_ != NULL); |
| 89 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 89 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
| 90 dest_frame_[i] = 0; | 90 dest_frame_[i] = 0; |
| 91 } | 91 } |
| 92 dest_frame_is_allocated_ = true; | 92 dest_frame_is_allocated_ = true; |
| 93 } | 93 } |
| 94 | 94 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 case DeoptInstr::kInt32: | 197 case DeoptInstr::kInt32: |
| 198 case DeoptInstr::kUint32: | 198 case DeoptInstr::kUint32: |
| 199 return true; | 199 return true; |
| 200 | 200 |
| 201 case DeoptInstr::kRetAddress: | 201 case DeoptInstr::kRetAddress: |
| 202 case DeoptInstr::kPcMarker: | 202 case DeoptInstr::kPcMarker: |
| 203 case DeoptInstr::kCallerFp: | 203 case DeoptInstr::kCallerFp: |
| 204 case DeoptInstr::kCallerPc: | 204 case DeoptInstr::kCallerPc: |
| 205 return false; | 205 return false; |
| 206 | 206 |
| 207 case DeoptInstr::kSuffix: | |
| 208 case DeoptInstr::kMaterializeObject: | 207 case DeoptInstr::kMaterializeObject: |
| 209 default: | 208 default: |
| 210 // We should not encounter these instructions when filling stack slots. | 209 // We should not encounter these instructions when filling stack slots. |
| 211 UNREACHABLE(); | 210 UNREACHABLE(); |
| 212 return false; | 211 return false; |
| 213 } | 212 } |
| 214 UNREACHABLE(); | 213 UNREACHABLE(); |
| 215 return false; | 214 return false; |
| 216 } | 215 } |
| 217 | 216 |
| 218 | 217 |
| 219 void DeoptContext::FillDestFrame() { | 218 void DeoptContext::FillDestFrame() { |
| 220 const Code& code = Code::Handle(code_); | 219 const Code& code = Code::Handle(code_); |
| 221 const DeoptInfo& deopt_info = DeoptInfo::Handle(deopt_info_); | 220 const TypedData& deopt_info = TypedData::Handle(deopt_info_); |
| 222 | 221 |
| 223 const intptr_t len = deopt_info.TranslationLength(); | 222 GrowableArray<DeoptInstr*> deopt_instructions; |
| 224 GrowableArray<DeoptInstr*> deopt_instructions(len); | |
| 225 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 223 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
| 226 ASSERT(!deopt_table.IsNull()); | 224 ASSERT(!deopt_table.IsNull()); |
| 227 deopt_info.ToInstructions(deopt_table, &deopt_instructions); | 225 DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions); |
| 228 | 226 |
| 229 const intptr_t frame_size = deopt_info.FrameSize(); | 227 const intptr_t len = deopt_instructions.length(); |
| 228 const intptr_t frame_size = dest_frame_size_; |
| 230 | 229 |
| 231 // For now, we never place non-objects in the deoptimized frame if | 230 // For now, we never place non-objects in the deoptimized frame if |
| 232 // the destination frame is a copy. This allows us to copy the | 231 // the destination frame is a copy. This allows us to copy the |
| 233 // deoptimized frame into an Array. | 232 // deoptimized frame into an Array. |
| 234 const bool objects_only = dest_frame_is_allocated_; | 233 const bool objects_only = dest_frame_is_allocated_; |
| 235 | 234 |
| 236 // All kMaterializeObject instructions are emitted before the instructions | 235 // All kMaterializeObject instructions are emitted before the instructions |
| 237 // that describe stack frames. Skip them and defer materialization of | 236 // that describe stack frames. Skip them and defer materialization of |
| 238 // objects until the frame is fully reconstructed and it is safe to perform | 237 // objects until the frame is fully reconstructed and it is safe to perform |
| 239 // GC. | 238 // GC. |
| 240 // Arguments (class of the instance to allocate and field-value pairs) are | 239 // Arguments (class of the instance to allocate and field-value pairs) are |
| 241 // described as part of the expression stack for the bottom-most deoptimized | 240 // described as part of the expression stack for the bottom-most deoptimized |
| 242 // frame. They will be used during materialization and removed from the stack | 241 // frame. They will be used during materialization and removed from the stack |
| 243 // right before control switches to the unoptimized code. | 242 // right before control switches to the unoptimized code. |
| 244 const intptr_t num_materializations = deopt_info.NumMaterializations(); | 243 const intptr_t num_materializations = |
| 244 DeoptInfo::NumMaterializations(deopt_instructions); |
| 245 PrepareForDeferredMaterialization(num_materializations); | 245 PrepareForDeferredMaterialization(num_materializations); |
| 246 for (intptr_t from_index = 0, to_index = kDartFrameFixedSize; | 246 for (intptr_t from_index = 0, to_index = kDartFrameFixedSize; |
| 247 from_index < num_materializations; | 247 from_index < num_materializations; |
| 248 from_index++) { | 248 from_index++) { |
| 249 const intptr_t field_count = | 249 const intptr_t field_count = |
| 250 DeoptInstr::GetFieldCount(deopt_instructions[from_index]); | 250 DeoptInstr::GetFieldCount(deopt_instructions[from_index]); |
| 251 intptr_t* args = GetDestFrameAddressAt(to_index); | 251 intptr_t* args = GetDestFrameAddressAt(to_index); |
| 252 DeferredObject* obj = new DeferredObject(field_count, args); | 252 DeferredObject* obj = new DeferredObject(field_count, args); |
| 253 SetDeferredObjectAt(from_index, obj); | 253 SetDeferredObjectAt(from_index, obj); |
| 254 to_index += obj->ArgumentCount(); | 254 to_index += obj->ArgumentCount(); |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 | 706 |
| 707 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 707 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 708 *dest_addr = deopt_context->GetSourcePc(); | 708 *dest_addr = deopt_context->GetSourcePc(); |
| 709 } | 709 } |
| 710 | 710 |
| 711 private: | 711 private: |
| 712 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 712 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
| 713 }; | 713 }; |
| 714 | 714 |
| 715 | 715 |
| 716 // Deoptimization instruction that indicates the rest of this DeoptInfo is a | |
| 717 // suffix of another one. The suffix contains the info number (0 based | |
| 718 // index in the deopt table of the DeoptInfo to share) and the length of the | |
| 719 // suffix. | |
| 720 class DeoptSuffixInstr : public DeoptInstr { | |
| 721 public: | |
| 722 DeoptSuffixInstr(intptr_t info_number, intptr_t suffix_length) | |
| 723 : info_number_(info_number), suffix_length_(suffix_length) { | |
| 724 ASSERT(info_number >= 0); | |
| 725 ASSERT(suffix_length >= 0); | |
| 726 } | |
| 727 | |
| 728 explicit DeoptSuffixInstr(intptr_t source_index) | |
| 729 : info_number_(InfoNumber::decode(source_index)), | |
| 730 suffix_length_(SuffixLength::decode(source_index)) { | |
| 731 } | |
| 732 | |
| 733 virtual intptr_t source_index() const { | |
| 734 return InfoNumber::encode(info_number_) | | |
| 735 SuffixLength::encode(suffix_length_); | |
| 736 } | |
| 737 virtual DeoptInstr::Kind kind() const { return kSuffix; } | |
| 738 | |
| 739 virtual const char* ArgumentsToCString() const { | |
| 740 return Thread::Current()->zone()->PrintToString( | |
| 741 "%" Pd ":%" Pd, info_number_, suffix_length_); | |
| 742 } | |
| 743 | |
| 744 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | |
| 745 // The deoptimization info is uncompressed by translating away suffixes | |
| 746 // before executing the instructions. | |
| 747 UNREACHABLE(); | |
| 748 } | |
| 749 | |
| 750 private: | |
| 751 // Static decoder functions in DeoptInstr have access to the bitfield | |
| 752 // definitions. | |
| 753 friend class DeoptInstr; | |
| 754 | |
| 755 static const intptr_t kFieldWidth = kBitsPerWord / 2; | |
| 756 class InfoNumber : public BitField<intptr_t, 0, kFieldWidth> { }; | |
| 757 class SuffixLength : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; | |
| 758 | |
| 759 const intptr_t info_number_; | |
| 760 const intptr_t suffix_length_; | |
| 761 | |
| 762 DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr); | |
| 763 }; | |
| 764 | |
| 765 | |
| 766 // Write reference to a materialized object with the given index into the | 716 // Write reference to a materialized object with the given index into the |
| 767 // stack slot. | 717 // stack slot. |
| 768 class DeoptMaterializedObjectRefInstr : public DeoptInstr { | 718 class DeoptMaterializedObjectRefInstr : public DeoptInstr { |
| 769 public: | 719 public: |
| 770 explicit DeoptMaterializedObjectRefInstr(intptr_t index) | 720 explicit DeoptMaterializedObjectRefInstr(intptr_t index) |
| 771 : index_(index) { | 721 : index_(index) { |
| 772 ASSERT(index >= 0); | 722 ASSERT(index >= 0); |
| 773 } | 723 } |
| 774 | 724 |
| 775 virtual intptr_t source_index() const { return index_; } | 725 virtual intptr_t source_index() const { return index_; } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 UNREACHABLE(); | 766 UNREACHABLE(); |
| 817 } | 767 } |
| 818 | 768 |
| 819 private: | 769 private: |
| 820 intptr_t field_count_; | 770 intptr_t field_count_; |
| 821 | 771 |
| 822 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); | 772 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); |
| 823 }; | 773 }; |
| 824 | 774 |
| 825 | 775 |
| 826 intptr_t DeoptInstr::DecodeSuffix(intptr_t source_index, | |
| 827 intptr_t* info_number) { | |
| 828 *info_number = DeoptSuffixInstr::InfoNumber::decode(source_index); | |
| 829 return DeoptSuffixInstr::SuffixLength::decode(source_index); | |
| 830 } | |
| 831 | |
| 832 | |
| 833 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, | 776 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, |
| 834 const Array& object_table, | 777 const Array& object_table, |
| 835 Code* code) { | 778 Code* code) { |
| 836 ASSERT(instr->kind() == kRetAddress); | 779 ASSERT(instr->kind() == kRetAddress); |
| 837 DeoptRetAddressInstr* ret_address_instr = | 780 DeoptRetAddressInstr* ret_address_instr = |
| 838 static_cast<DeoptRetAddressInstr*>(instr); | 781 static_cast<DeoptRetAddressInstr*>(instr); |
| 839 // The following assert may trigger when displaying a backtrace | 782 // The following assert may trigger when displaying a backtrace |
| 840 // from the simulator. | 783 // from the simulator. |
| 841 ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id())); | 784 ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id())); |
| 842 ASSERT(!object_table.IsNull()); | 785 ASSERT(!object_table.IsNull()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 case kPcMarker: | 824 case kPcMarker: |
| 882 return new DeoptPcMarkerInstr(source_index); | 825 return new DeoptPcMarkerInstr(source_index); |
| 883 case kPp: | 826 case kPp: |
| 884 return new DeoptPpInstr(source_index); | 827 return new DeoptPpInstr(source_index); |
| 885 case kCallerFp: | 828 case kCallerFp: |
| 886 return new DeoptCallerFpInstr(); | 829 return new DeoptCallerFpInstr(); |
| 887 case kCallerPp: | 830 case kCallerPp: |
| 888 return new DeoptCallerPpInstr(); | 831 return new DeoptCallerPpInstr(); |
| 889 case kCallerPc: | 832 case kCallerPc: |
| 890 return new DeoptCallerPcInstr(); | 833 return new DeoptCallerPcInstr(); |
| 891 case kSuffix: | |
| 892 return new DeoptSuffixInstr(source_index); | |
| 893 case kMaterializedObjectRef: | 834 case kMaterializedObjectRef: |
| 894 return new DeoptMaterializedObjectRefInstr(source_index); | 835 return new DeoptMaterializedObjectRefInstr(source_index); |
| 895 case kMaterializeObject: | 836 case kMaterializeObject: |
| 896 return new DeoptMaterializeObjectInstr(source_index); | 837 return new DeoptMaterializeObjectInstr(source_index); |
| 897 } | 838 } |
| 898 UNREACHABLE(); | 839 UNREACHABLE(); |
| 899 return NULL; | 840 return NULL; |
| 900 } | 841 } |
| 901 | 842 |
| 902 | 843 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 926 case kPcMarker: | 867 case kPcMarker: |
| 927 return "pc"; | 868 return "pc"; |
| 928 case kPp: | 869 case kPp: |
| 929 return "pp"; | 870 return "pp"; |
| 930 case kCallerFp: | 871 case kCallerFp: |
| 931 return "callerfp"; | 872 return "callerfp"; |
| 932 case kCallerPp: | 873 case kCallerPp: |
| 933 return "callerpp"; | 874 return "callerpp"; |
| 934 case kCallerPc: | 875 case kCallerPc: |
| 935 return "callerpc"; | 876 return "callerpc"; |
| 936 case kSuffix: | |
| 937 return "suffix"; | |
| 938 case kMaterializedObjectRef: | 877 case kMaterializedObjectRef: |
| 939 return "ref"; | 878 return "ref"; |
| 940 case kMaterializeObject: | 879 case kMaterializeObject: |
| 941 return "mat"; | 880 return "mat"; |
| 942 } | 881 } |
| 943 UNREACHABLE(); | 882 UNREACHABLE(); |
| 944 return NULL; | 883 return NULL; |
| 945 } | 884 } |
| 946 | 885 |
| 947 | 886 |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 MaterializeObjectInstr* mat) const { | 1148 MaterializeObjectInstr* mat) const { |
| 1210 for (intptr_t i = 0; i < materializations_.length(); i++) { | 1149 for (intptr_t i = 0; i < materializations_.length(); i++) { |
| 1211 if (materializations_[i] == mat) { | 1150 if (materializations_[i] == mat) { |
| 1212 return i; | 1151 return i; |
| 1213 } | 1152 } |
| 1214 } | 1153 } |
| 1215 return -1; | 1154 return -1; |
| 1216 } | 1155 } |
| 1217 | 1156 |
| 1218 | 1157 |
| 1219 RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) { | 1158 static uint8_t* ZoneReAlloc(uint8_t* ptr, |
| 1220 // TODO(vegorov): enable compression of deoptimization info containing object | 1159 intptr_t old_size, |
| 1221 // materialization instructions. | 1160 intptr_t new_size) { |
| 1222 const bool disable_compression = | 1161 return Isolate::Current()->current_zone()->Realloc<uint8_t>( |
| 1223 (instructions_[0]->kind() == DeoptInstr::kMaterializeObject); | 1162 ptr, old_size, new_size); |
| 1163 } |
| 1224 | 1164 |
| 1165 |
| 1166 RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) { |
| 1225 intptr_t length = instructions_.length(); | 1167 intptr_t length = instructions_.length(); |
| 1226 | 1168 |
| 1227 // Count the number of instructions that are a shared suffix of some deopt | 1169 // Count the number of instructions that are a shared suffix of some deopt |
| 1228 // info already written. | 1170 // info already written. |
| 1229 TrieNode* suffix = trie_root_; | 1171 TrieNode* suffix = trie_root_; |
| 1230 intptr_t suffix_length = 0; | 1172 intptr_t suffix_length = 0; |
| 1231 if (FLAG_compress_deopt_info && !disable_compression) { | 1173 if (FLAG_compress_deopt_info) { |
| 1232 for (intptr_t i = length - 1; i >= 0; --i) { | 1174 for (intptr_t i = length - 1; i >= 0; --i) { |
| 1233 TrieNode* node = suffix->FindChild(*instructions_[i]); | 1175 TrieNode* node = suffix->FindChild(*instructions_[i]); |
| 1234 if (node == NULL) break; | 1176 if (node == NULL) break; |
| 1235 suffix = node; | 1177 suffix = node; |
| 1236 ++suffix_length; | 1178 ++suffix_length; |
| 1237 } | 1179 } |
| 1238 } | 1180 } |
| 1239 | 1181 |
| 1182 |
| 1240 // Allocate space for the translation. If the shared suffix is longer | 1183 // Allocate space for the translation. If the shared suffix is longer |
| 1241 // than one instruction, we replace it with a single suffix instruction. | 1184 // than one instruction, we replace it with a single suffix instruction. |
| 1242 if (suffix_length > 1) length -= (suffix_length - 1); | 1185 const bool use_suffix = suffix_length > 1; |
| 1243 const DeoptInfo& deopt_info = | 1186 if (use_suffix) { |
| 1244 DeoptInfo::Handle(zone(), DeoptInfo::New(length)); | 1187 length -= (suffix_length - 1); |
| 1188 } |
| 1189 |
| 1190 uint8_t* buffer; |
| 1191 typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer; |
| 1192 WriteStream stream(&buffer, ZoneReAlloc, 2 * length * kWordSize); |
| 1193 |
| 1194 Writer::Write(&stream, FrameSize()); |
| 1195 |
| 1196 if (use_suffix) { |
| 1197 Writer::Write(&stream, suffix_length); |
| 1198 Writer::Write(&stream, suffix->info_number()); |
| 1199 } else { |
| 1200 Writer::Write(&stream, 0); |
| 1201 } |
| 1245 | 1202 |
| 1246 // Write the unshared instructions and build their sub-tree. | 1203 // Write the unshared instructions and build their sub-tree. |
| 1247 TrieNode* node = NULL; | 1204 TrieNode* node = use_suffix ? suffix : trie_root_; |
| 1248 intptr_t write_count = (suffix_length > 1) ? length - 1 : length; | 1205 const intptr_t write_count = use_suffix ? length - 1 : length; |
| 1249 for (intptr_t i = 0; i < write_count; ++i) { | 1206 for (intptr_t i = write_count - 1; i >= 0; --i) { |
| 1250 DeoptInstr* instr = instructions_[i]; | 1207 DeoptInstr* instr = instructions_[i]; |
| 1251 deopt_info.SetAt(i, instr->kind(), instr->source_index()); | 1208 Writer::Write(&stream, instr->kind()); |
| 1252 TrieNode* child = node; | 1209 Writer::Write(&stream, instr->source_index()); |
| 1253 node = new(zone()) TrieNode(instr, current_info_number_); | 1210 |
| 1211 TrieNode* child = new(zone()) TrieNode(instr, current_info_number_); |
| 1254 node->AddChild(child); | 1212 node->AddChild(child); |
| 1213 node = child; |
| 1255 } | 1214 } |
| 1256 | 1215 |
| 1257 if (suffix_length > 1) { | 1216 const TypedData& deopt_info = TypedData::Handle(zone(), TypedData::New( |
| 1258 suffix->AddChild(node); | 1217 kTypedDataUint8ArrayCid, stream.bytes_written(), Heap::kOld)); |
| 1259 DeoptInstr* instr = | 1218 { |
| 1260 new(zone()) DeoptSuffixInstr(suffix->info_number(), suffix_length); | 1219 NoSafepointScope no_safepoint; |
| 1261 deopt_info.SetAt(length - 1, instr->kind(), instr->source_index()); | 1220 memmove(deopt_info.DataAddr(0), |
| 1262 } else { | 1221 stream.buffer(), |
| 1263 trie_root_->AddChild(node); | 1222 stream.bytes_written()); |
| 1264 } | 1223 } |
| 1265 | 1224 |
| 1266 ASSERT(deopt_info.VerifyDecompression(instructions_, deopt_table)); | 1225 ASSERT(DeoptInfo::VerifyDecompression( |
| 1226 instructions_, deopt_table, deopt_info)); |
| 1267 instructions_.Clear(); | 1227 instructions_.Clear(); |
| 1268 materializations_.Clear(); | 1228 materializations_.Clear(); |
| 1269 frame_start_ = -1; | 1229 frame_start_ = -1; |
| 1270 | 1230 |
| 1271 ++current_info_number_; | 1231 ++current_info_number_; |
| 1272 return deopt_info.raw(); | 1232 return deopt_info.raw(); |
| 1273 } | 1233 } |
| 1274 | 1234 |
| 1275 | 1235 |
| 1276 intptr_t DeoptTable::SizeFor(intptr_t length) { | 1236 intptr_t DeoptTable::SizeFor(intptr_t length) { |
| 1277 return length * kEntrySize; | 1237 return length * kEntrySize; |
| 1278 } | 1238 } |
| 1279 | 1239 |
| 1280 void DeoptTable::SetEntry(const Array& table, | 1240 void DeoptTable::SetEntry(const Array& table, |
| 1281 intptr_t index, | 1241 intptr_t index, |
| 1282 const Smi& offset, | 1242 const Smi& offset, |
| 1283 const DeoptInfo& info, | 1243 const TypedData& info, |
| 1284 const Smi& reason) { | 1244 const Smi& reason) { |
| 1285 ASSERT((table.Length() % kEntrySize) == 0); | 1245 ASSERT((table.Length() % kEntrySize) == 0); |
| 1286 intptr_t i = index * kEntrySize; | 1246 intptr_t i = index * kEntrySize; |
| 1287 table.SetAt(i, offset); | 1247 table.SetAt(i, offset); |
| 1288 table.SetAt(i + 1, info); | 1248 table.SetAt(i + 1, info); |
| 1289 table.SetAt(i + 2, reason); | 1249 table.SetAt(i + 2, reason); |
| 1290 } | 1250 } |
| 1291 | 1251 |
| 1292 | 1252 |
| 1293 intptr_t DeoptTable::GetLength(const Array& table) { | 1253 intptr_t DeoptTable::GetLength(const Array& table) { |
| 1294 ASSERT((table.Length() % kEntrySize) == 0); | 1254 ASSERT((table.Length() % kEntrySize) == 0); |
| 1295 return table.Length() / kEntrySize; | 1255 return table.Length() / kEntrySize; |
| 1296 } | 1256 } |
| 1297 | 1257 |
| 1298 | 1258 |
| 1299 void DeoptTable::GetEntry(const Array& table, | 1259 void DeoptTable::GetEntry(const Array& table, |
| 1300 intptr_t index, | 1260 intptr_t index, |
| 1301 Smi* offset, | 1261 Smi* offset, |
| 1302 DeoptInfo* info, | 1262 TypedData* info, |
| 1303 Smi* reason) { | 1263 Smi* reason) { |
| 1304 intptr_t i = index * kEntrySize; | 1264 intptr_t i = index * kEntrySize; |
| 1305 *offset ^= table.At(i); | 1265 *offset ^= table.At(i); |
| 1306 *info ^= table.At(i + 1); | 1266 *info ^= table.At(i + 1); |
| 1307 *reason ^= table.At(i + 2); | 1267 *reason ^= table.At(i + 2); |
| 1308 } | 1268 } |
| 1309 | 1269 |
| 1310 } // namespace dart | 1270 } // namespace dart |
| OLD | NEW |