Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: runtime/vm/deopt_instructions.cc

Issue 1054393003: Compress deopt instructions in memory using variable length encoding. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fix other architectures Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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.
Ivan Posva 2015/04/08 07:12:12 Is this saving unnecessary given the compression?
Vyacheslav Egorov (Google) 2015/04/08 13:07:39 Suffix compression gives us 30-40% saving on top -
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
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
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
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
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,
1159 intptr_t old_size,
1160 intptr_t new_size) {
1161 return Isolate::Current()->current_zone()->Realloc<uint8_t>(
1162 ptr, old_size, new_size);
1163 }
1164
1165
1166 RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) {
1220 // TODO(vegorov): enable compression of deoptimization info containing object 1167 // TODO(vegorov): enable compression of deoptimization info containing object
1221 // materialization instructions. 1168 // materialization instructions.
1222 const bool disable_compression = 1169 const bool disable_compression =
1223 (instructions_[0]->kind() == DeoptInstr::kMaterializeObject); 1170 (instructions_[0]->kind() == DeoptInstr::kMaterializeObject);
1224 1171
1225 intptr_t length = instructions_.length(); 1172 intptr_t length = instructions_.length();
1226 1173
1227 // Count the number of instructions that are a shared suffix of some deopt 1174 // Count the number of instructions that are a shared suffix of some deopt
1228 // info already written. 1175 // info already written.
1229 TrieNode* suffix = trie_root_; 1176 TrieNode* suffix = trie_root_;
1230 intptr_t suffix_length = 0; 1177 intptr_t suffix_length = 0;
1231 if (FLAG_compress_deopt_info && !disable_compression) { 1178 if (FLAG_compress_deopt_info && !disable_compression) {
1232 for (intptr_t i = length - 1; i >= 0; --i) { 1179 for (intptr_t i = length - 1; i >= 0; --i) {
1233 TrieNode* node = suffix->FindChild(*instructions_[i]); 1180 TrieNode* node = suffix->FindChild(*instructions_[i]);
1234 if (node == NULL) break; 1181 if (node == NULL) break;
1235 suffix = node; 1182 suffix = node;
1236 ++suffix_length; 1183 ++suffix_length;
1237 } 1184 }
1238 } 1185 }
1239 1186
1240 // Allocate space for the translation. If the shared suffix is longer 1187 // Allocate space for the translation. If the shared suffix is longer
1241 // than one instruction, we replace it with a single suffix instruction. 1188 // than one instruction, we replace it with a single suffix instruction.
1242 if (suffix_length > 1) length -= (suffix_length - 1); 1189 if (suffix_length > 1) length -= (suffix_length - 1);
1243 const DeoptInfo& deopt_info = 1190
1244 DeoptInfo::Handle(zone(), DeoptInfo::New(length)); 1191 uint8_t* buffer;
1192 typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer;
1193 WriteStream stream(&buffer, ZoneReAlloc, 2 * length * kWordSize);
1194
1195 Writer::Write(&stream, FrameSize());
1196
1197 if (suffix_length > 1) {
Ivan Posva 2015/04/08 07:12:12 bool use_suffix = suffix_length > 1; and use this
Vyacheslav Egorov (Google) 2015/04/08 13:07:39 Done.
1198 Writer::Write(&stream, suffix_length);
1199 Writer::Write(&stream, suffix->info_number());
1200 } else {
1201 Writer::Write(&stream, 0);
1202 }
1245 1203
1246 // Write the unshared instructions and build their sub-tree. 1204 // Write the unshared instructions and build their sub-tree.
1247 TrieNode* node = NULL; 1205 TrieNode* node = (suffix_length > 1) ? suffix : trie_root_;
1248 intptr_t write_count = (suffix_length > 1) ? length - 1 : length; 1206 intptr_t write_count = (suffix_length > 1) ? length - 1 : length;
1249 for (intptr_t i = 0; i < write_count; ++i) { 1207 for (intptr_t i = write_count - 1; i >= 0; --i) {
1250 DeoptInstr* instr = instructions_[i]; 1208 DeoptInstr* instr = instructions_[i];
1251 deopt_info.SetAt(i, instr->kind(), instr->source_index()); 1209 Writer::Write(&stream, instr->kind());
1252 TrieNode* child = node; 1210 Writer::Write(&stream, instr->source_index());
1253 node = new(zone()) TrieNode(instr, current_info_number_); 1211
1212 TrieNode* child = new(zone()) TrieNode(instr, current_info_number_);
1254 node->AddChild(child); 1213 node->AddChild(child);
1214 node = child;
1255 } 1215 }
1256 1216
1257 if (suffix_length > 1) { 1217 const TypedData& deopt_info = TypedData::Handle(zone(), TypedData::New(
1258 suffix->AddChild(node); 1218 kTypedDataUint8ArrayCid, stream.bytes_written(), Heap::kOld));
1259 DeoptInstr* instr = 1219 {
1260 new(zone()) DeoptSuffixInstr(suffix->info_number(), suffix_length); 1220 NoSafepointScope no_safepoint;
1261 deopt_info.SetAt(length - 1, instr->kind(), instr->source_index()); 1221 memmove(deopt_info.DataAddr(0),
1262 } else { 1222 stream.buffer(),
1263 trie_root_->AddChild(node); 1223 stream.bytes_written());
1264 } 1224 }
1265 1225
1266 ASSERT(deopt_info.VerifyDecompression(instructions_, deopt_table)); 1226 ASSERT(DeoptInfo::VerifyDecompression(
1227 instructions_, deopt_table, deopt_info));
1267 instructions_.Clear(); 1228 instructions_.Clear();
1268 materializations_.Clear(); 1229 materializations_.Clear();
1269 frame_start_ = -1; 1230 frame_start_ = -1;
1270 1231
1271 ++current_info_number_; 1232 ++current_info_number_;
1272 return deopt_info.raw(); 1233 return deopt_info.raw();
1273 } 1234 }
1274 1235
1275 1236
1276 intptr_t DeoptTable::SizeFor(intptr_t length) { 1237 intptr_t DeoptTable::SizeFor(intptr_t length) {
1277 return length * kEntrySize; 1238 return length * kEntrySize;
1278 } 1239 }
1279 1240
1280 void DeoptTable::SetEntry(const Array& table, 1241 void DeoptTable::SetEntry(const Array& table,
1281 intptr_t index, 1242 intptr_t index,
1282 const Smi& offset, 1243 const Smi& offset,
1283 const DeoptInfo& info, 1244 const TypedData& info,
1284 const Smi& reason) { 1245 const Smi& reason) {
1285 ASSERT((table.Length() % kEntrySize) == 0); 1246 ASSERT((table.Length() % kEntrySize) == 0);
1286 intptr_t i = index * kEntrySize; 1247 intptr_t i = index * kEntrySize;
1287 table.SetAt(i, offset); 1248 table.SetAt(i, offset);
1288 table.SetAt(i + 1, info); 1249 table.SetAt(i + 1, info);
1289 table.SetAt(i + 2, reason); 1250 table.SetAt(i + 2, reason);
1290 } 1251 }
1291 1252
1292 1253
1293 intptr_t DeoptTable::GetLength(const Array& table) { 1254 intptr_t DeoptTable::GetLength(const Array& table) {
1294 ASSERT((table.Length() % kEntrySize) == 0); 1255 ASSERT((table.Length() % kEntrySize) == 0);
1295 return table.Length() / kEntrySize; 1256 return table.Length() / kEntrySize;
1296 } 1257 }
1297 1258
1298 1259
1299 void DeoptTable::GetEntry(const Array& table, 1260 void DeoptTable::GetEntry(const Array& table,
1300 intptr_t index, 1261 intptr_t index,
1301 Smi* offset, 1262 Smi* offset,
1302 DeoptInfo* info, 1263 TypedData* info,
1303 Smi* reason) { 1264 Smi* reason) {
1304 intptr_t i = index * kEntrySize; 1265 intptr_t i = index * kEntrySize;
1305 *offset ^= table.At(i); 1266 *offset ^= table.At(i);
1306 *info ^= table.At(i + 1); 1267 *info ^= table.At(i + 1);
1307 *reason ^= table.At(i + 2); 1268 *reason ^= table.At(i + 2);
1308 } 1269 }
1309 1270
1310 } // namespace dart 1271 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698