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/disassembler.h" | 10 #include "vm/disassembler.h" |
11 #include "vm/intermediate_language.h" | 11 #include "vm/intermediate_language.h" |
12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
13 #include "vm/parser.h" | 13 #include "vm/parser.h" |
14 #include "vm/stack_frame.h" | 14 #include "vm/stack_frame.h" |
15 #include "vm/thread.h" | 15 #include "vm/thread.h" |
16 #include "vm/timeline.h" | 16 #include "vm/timeline.h" |
17 | 17 |
18 namespace dart { | 18 namespace dart { |
19 | 19 |
20 DEFINE_FLAG(bool, | 20 DEFINE_FLAG(bool, |
21 compress_deopt_info, | 21 compress_deopt_info, |
22 true, | 22 true, |
23 "Compress the size of the deoptimization info for optimized code."); | 23 "Compress the size of the deoptimization info for optimized code."); |
24 DECLARE_FLAG(bool, trace_deoptimization); | 24 DECLARE_FLAG(bool, trace_deoptimization); |
25 DECLARE_FLAG(bool, trace_deoptimization_verbose); | 25 DECLARE_FLAG(bool, trace_deoptimization_verbose); |
26 | 26 |
27 | |
28 DeoptContext::DeoptContext(const StackFrame* frame, | 27 DeoptContext::DeoptContext(const StackFrame* frame, |
29 const Code& code, | 28 const Code& code, |
30 DestFrameOptions dest_options, | 29 DestFrameOptions dest_options, |
31 fpu_register_t* fpu_registers, | 30 fpu_register_t* fpu_registers, |
32 intptr_t* cpu_registers, | 31 intptr_t* cpu_registers, |
33 bool is_lazy_deopt, | 32 bool is_lazy_deopt, |
34 bool deoptimizing_code) | 33 bool deoptimizing_code) |
35 : code_(code.raw()), | 34 : code_(code.raw()), |
36 object_pool_(code.GetObjectPool()), | 35 object_pool_(code.GetObjectPool()), |
37 deopt_info_(TypedData::null()), | 36 deopt_info_(TypedData::null()), |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | 124 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
126 THR_Print( | 125 THR_Print( |
127 "Deoptimizing (reason %d '%s') at " | 126 "Deoptimizing (reason %d '%s') at " |
128 "pc=%" Pp " fp=%" Pp " '%s' (count %d)\n", | 127 "pc=%" Pp " fp=%" Pp " '%s' (count %d)\n", |
129 deopt_reason(), DeoptReasonToCString(deopt_reason()), frame->pc(), | 128 deopt_reason(), DeoptReasonToCString(deopt_reason()), frame->pc(), |
130 frame->fp(), function.ToFullyQualifiedCString(), | 129 frame->fp(), function.ToFullyQualifiedCString(), |
131 function.deoptimization_counter()); | 130 function.deoptimization_counter()); |
132 } | 131 } |
133 } | 132 } |
134 | 133 |
135 | |
136 DeoptContext::~DeoptContext() { | 134 DeoptContext::~DeoptContext() { |
137 // Delete memory for source frame and registers. | 135 // Delete memory for source frame and registers. |
138 if (source_frame_is_allocated_) { | 136 if (source_frame_is_allocated_) { |
139 delete[] source_frame_; | 137 delete[] source_frame_; |
140 } | 138 } |
141 source_frame_ = NULL; | 139 source_frame_ = NULL; |
142 delete[] fpu_registers_; | 140 delete[] fpu_registers_; |
143 delete[] cpu_registers_; | 141 delete[] cpu_registers_; |
144 fpu_registers_ = NULL; | 142 fpu_registers_ = NULL; |
145 cpu_registers_ = NULL; | 143 cpu_registers_ = NULL; |
(...skipping 30 matching lines...) Expand all Loading... |
176 timeline_event->CopyArgument(0, "function", function_name.ToCString()); | 174 timeline_event->CopyArgument(0, "function", function_name.ToCString()); |
177 timeline_event->CopyArgument(1, "reason", reason); | 175 timeline_event->CopyArgument(1, "reason", reason); |
178 timeline_event->FormatArgument(2, "deoptimizationCount", "%d", counter); | 176 timeline_event->FormatArgument(2, "deoptimizationCount", "%d", counter); |
179 timeline_event->Complete(); | 177 timeline_event->Complete(); |
180 } | 178 } |
181 } | 179 } |
182 } | 180 } |
183 #endif // !PRODUCT | 181 #endif // !PRODUCT |
184 } | 182 } |
185 | 183 |
186 | |
187 void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 184 void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
188 visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_pool_)); | 185 visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_pool_)); |
189 visitor->VisitPointer(reinterpret_cast<RawObject**>(&deopt_info_)); | 186 visitor->VisitPointer(reinterpret_cast<RawObject**>(&deopt_info_)); |
190 | 187 |
191 // Visit any object pointers on the destination stack. | 188 // Visit any object pointers on the destination stack. |
192 if (dest_frame_is_allocated_) { | 189 if (dest_frame_is_allocated_) { |
193 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 190 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
194 if (dest_frame_[i] != 0) { | 191 if (dest_frame_[i] != 0) { |
195 visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i])); | 192 visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i])); |
196 } | 193 } |
197 } | 194 } |
198 } | 195 } |
199 } | 196 } |
200 | 197 |
201 | |
202 intptr_t DeoptContext::DestStackAdjustment() const { | 198 intptr_t DeoptContext::DestStackAdjustment() const { |
203 return dest_frame_size_ - kDartFrameFixedSize - num_args_ | 199 return dest_frame_size_ - kDartFrameFixedSize - num_args_ |
204 #if !defined(TARGET_ARCH_DBC) | 200 #if !defined(TARGET_ARCH_DBC) |
205 - 1 // For fp. | 201 - 1 // For fp. |
206 #endif | 202 #endif |
207 - kParamEndSlotFromFp; | 203 - kParamEndSlotFromFp; |
208 } | 204 } |
209 | 205 |
210 | |
211 intptr_t DeoptContext::GetSourceFp() const { | 206 intptr_t DeoptContext::GetSourceFp() const { |
212 #if !defined(TARGET_ARCH_DBC) | 207 #if !defined(TARGET_ARCH_DBC) |
213 return source_frame_[source_frame_size_ - 1 - num_args_ - | 208 return source_frame_[source_frame_size_ - 1 - num_args_ - |
214 kParamEndSlotFromFp]; | 209 kParamEndSlotFromFp]; |
215 #else | 210 #else |
216 return source_frame_[num_args_ + kDartFrameFixedSize + | 211 return source_frame_[num_args_ + kDartFrameFixedSize + |
217 kSavedCallerFpSlotFromFp]; | 212 kSavedCallerFpSlotFromFp]; |
218 #endif | 213 #endif |
219 } | 214 } |
220 | 215 |
221 | |
222 intptr_t DeoptContext::GetSourcePp() const { | 216 intptr_t DeoptContext::GetSourcePp() const { |
223 #if !defined(TARGET_ARCH_DBC) | 217 #if !defined(TARGET_ARCH_DBC) |
224 return source_frame_[source_frame_size_ - 1 - num_args_ - | 218 return source_frame_[source_frame_size_ - 1 - num_args_ - |
225 kParamEndSlotFromFp + | 219 kParamEndSlotFromFp + |
226 StackFrame::SavedCallerPpSlotFromFp()]; | 220 StackFrame::SavedCallerPpSlotFromFp()]; |
227 #else | 221 #else |
228 UNREACHABLE(); | 222 UNREACHABLE(); |
229 return 0; | 223 return 0; |
230 #endif | 224 #endif |
231 } | 225 } |
232 | 226 |
233 | |
234 intptr_t DeoptContext::GetSourcePc() const { | 227 intptr_t DeoptContext::GetSourcePc() const { |
235 #if !defined(TARGET_ARCH_DBC) | 228 #if !defined(TARGET_ARCH_DBC) |
236 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; | 229 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; |
237 #else | 230 #else |
238 return source_frame_[num_args_ + kDartFrameFixedSize + | 231 return source_frame_[num_args_ + kDartFrameFixedSize + |
239 kSavedCallerPcSlotFromFp]; | 232 kSavedCallerPcSlotFromFp]; |
240 #endif | 233 #endif |
241 } | 234 } |
242 | 235 |
243 | |
244 intptr_t DeoptContext::GetCallerFp() const { | 236 intptr_t DeoptContext::GetCallerFp() const { |
245 return caller_fp_; | 237 return caller_fp_; |
246 } | 238 } |
247 | 239 |
248 | |
249 void DeoptContext::SetCallerFp(intptr_t caller_fp) { | 240 void DeoptContext::SetCallerFp(intptr_t caller_fp) { |
250 caller_fp_ = caller_fp; | 241 caller_fp_ = caller_fp; |
251 } | 242 } |
252 | 243 |
253 | |
254 static bool IsObjectInstruction(DeoptInstr::Kind kind) { | 244 static bool IsObjectInstruction(DeoptInstr::Kind kind) { |
255 switch (kind) { | 245 switch (kind) { |
256 case DeoptInstr::kConstant: | 246 case DeoptInstr::kConstant: |
257 case DeoptInstr::kPp: | 247 case DeoptInstr::kPp: |
258 case DeoptInstr::kCallerPp: | 248 case DeoptInstr::kCallerPp: |
259 case DeoptInstr::kMaterializedObjectRef: | 249 case DeoptInstr::kMaterializedObjectRef: |
260 case DeoptInstr::kFloat32x4: | 250 case DeoptInstr::kFloat32x4: |
261 case DeoptInstr::kInt32x4: | 251 case DeoptInstr::kInt32x4: |
262 case DeoptInstr::kFloat64x2: | 252 case DeoptInstr::kFloat64x2: |
263 case DeoptInstr::kWord: | 253 case DeoptInstr::kWord: |
(...skipping 13 matching lines...) Expand all Loading... |
277 case DeoptInstr::kMaterializeObject: | 267 case DeoptInstr::kMaterializeObject: |
278 default: | 268 default: |
279 // We should not encounter these instructions when filling stack slots. | 269 // We should not encounter these instructions when filling stack slots. |
280 UNREACHABLE(); | 270 UNREACHABLE(); |
281 return false; | 271 return false; |
282 } | 272 } |
283 UNREACHABLE(); | 273 UNREACHABLE(); |
284 return false; | 274 return false; |
285 } | 275 } |
286 | 276 |
287 | |
288 void DeoptContext::FillDestFrame() { | 277 void DeoptContext::FillDestFrame() { |
289 const Code& code = Code::Handle(code_); | 278 const Code& code = Code::Handle(code_); |
290 const TypedData& deopt_info = TypedData::Handle(deopt_info_); | 279 const TypedData& deopt_info = TypedData::Handle(deopt_info_); |
291 | 280 |
292 GrowableArray<DeoptInstr*> deopt_instructions; | 281 GrowableArray<DeoptInstr*> deopt_instructions; |
293 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 282 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
294 ASSERT(!deopt_table.IsNull()); | 283 ASSERT(!deopt_table.IsNull()); |
295 DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions); | 284 DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions); |
296 | 285 |
297 const intptr_t len = deopt_instructions.length(); | 286 const intptr_t len = deopt_instructions.length(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 | 326 |
338 if (FLAG_trace_deoptimization_verbose) { | 327 if (FLAG_trace_deoptimization_verbose) { |
339 for (intptr_t i = 0; i < frame_size; i++) { | 328 for (intptr_t i = 0; i < frame_size; i++) { |
340 intptr_t* to_addr = GetDestFrameAddressAt(i); | 329 intptr_t* to_addr = GetDestFrameAddressAt(i); |
341 THR_Print("*%" Pd ". [%p] 0x%" Px " [%s]\n", i, to_addr, *to_addr, | 330 THR_Print("*%" Pd ". [%p] 0x%" Px " [%s]\n", i, to_addr, *to_addr, |
342 deopt_instructions[i + (len - frame_size)]->ToCString()); | 331 deopt_instructions[i + (len - frame_size)]->ToCString()); |
343 } | 332 } |
344 } | 333 } |
345 } | 334 } |
346 | 335 |
347 | |
348 intptr_t* DeoptContext::CatchEntryState(intptr_t num_vars) { | 336 intptr_t* DeoptContext::CatchEntryState(intptr_t num_vars) { |
349 const Code& code = Code::Handle(code_); | 337 const Code& code = Code::Handle(code_); |
350 const TypedData& deopt_info = TypedData::Handle(deopt_info_); | 338 const TypedData& deopt_info = TypedData::Handle(deopt_info_); |
351 GrowableArray<DeoptInstr*> deopt_instructions; | 339 GrowableArray<DeoptInstr*> deopt_instructions; |
352 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 340 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
353 ASSERT(!deopt_table.IsNull()); | 341 ASSERT(!deopt_table.IsNull()); |
354 DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions); | 342 DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions); |
355 | 343 |
356 intptr_t* state = new intptr_t[2 * num_vars + 1]; | 344 intptr_t* state = new intptr_t[2 * num_vars + 1]; |
357 state[0] = num_vars; | 345 state[0] = num_vars; |
(...skipping 15 matching lines...) Expand all Loading... |
373 intptr_t dest_index = i - params; | 361 intptr_t dest_index = i - params; |
374 #endif | 362 #endif |
375 CatchEntryStatePair p = instr->ToCatchEntryStatePair(this, dest_index); | 363 CatchEntryStatePair p = instr->ToCatchEntryStatePair(this, dest_index); |
376 state[1 + 2 * i] = p.src; | 364 state[1 + 2 * i] = p.src; |
377 state[2 + 2 * i] = p.dest; | 365 state[2 + 2 * i] = p.dest; |
378 } | 366 } |
379 | 367 |
380 return state; | 368 return state; |
381 } | 369 } |
382 | 370 |
383 | |
384 static void FillDeferredSlots(DeoptContext* deopt_context, | 371 static void FillDeferredSlots(DeoptContext* deopt_context, |
385 DeferredSlot** slot_list) { | 372 DeferredSlot** slot_list) { |
386 DeferredSlot* slot = *slot_list; | 373 DeferredSlot* slot = *slot_list; |
387 *slot_list = NULL; | 374 *slot_list = NULL; |
388 | 375 |
389 while (slot != NULL) { | 376 while (slot != NULL) { |
390 DeferredSlot* current = slot; | 377 DeferredSlot* current = slot; |
391 slot = slot->next(); | 378 slot = slot->next(); |
392 | 379 |
393 current->Materialize(deopt_context); | 380 current->Materialize(deopt_context); |
394 | 381 |
395 delete current; | 382 delete current; |
396 } | 383 } |
397 } | 384 } |
398 | 385 |
399 | |
400 // Materializes all deferred objects. Returns the total number of | 386 // Materializes all deferred objects. Returns the total number of |
401 // artificial arguments used during deoptimization. | 387 // artificial arguments used during deoptimization. |
402 intptr_t DeoptContext::MaterializeDeferredObjects() { | 388 intptr_t DeoptContext::MaterializeDeferredObjects() { |
403 // Populate slots with references to all unboxed "primitive" values (doubles, | 389 // Populate slots with references to all unboxed "primitive" values (doubles, |
404 // mints, simd) and deferred objects. Deferred objects are only allocated | 390 // mints, simd) and deferred objects. Deferred objects are only allocated |
405 // but not filled with data. This is done later because deferred objects | 391 // but not filled with data. This is done later because deferred objects |
406 // can references each other. | 392 // can references each other. |
407 FillDeferredSlots(this, &deferred_slots_); | 393 FillDeferredSlots(this, &deferred_slots_); |
408 | 394 |
409 // Compute total number of artificial arguments used during deoptimization. | 395 // Compute total number of artificial arguments used during deoptimization. |
(...skipping 21 matching lines...) Expand all Loading... |
431 char line_buffer[80]; | 417 char line_buffer[80]; |
432 OS::SNPrint(line_buffer, sizeof(line_buffer), " Line %" Pd ": '%s'", line, | 418 OS::SNPrint(line_buffer, sizeof(line_buffer), " Line %" Pd ": '%s'", line, |
433 line_string.ToCString()); | 419 line_string.ToCString()); |
434 THR_Print("%s\n", line_buffer); | 420 THR_Print("%s\n", line_buffer); |
435 THR_Print(" Deopt args: %" Pd "\n", deopt_arg_count); | 421 THR_Print(" Deopt args: %" Pd "\n", deopt_arg_count); |
436 } | 422 } |
437 | 423 |
438 return deopt_arg_count; | 424 return deopt_arg_count; |
439 } | 425 } |
440 | 426 |
441 | |
442 RawArray* DeoptContext::DestFrameAsArray() { | 427 RawArray* DeoptContext::DestFrameAsArray() { |
443 ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_); | 428 ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_); |
444 const Array& dest_array = Array::Handle(zone(), Array::New(dest_frame_size_)); | 429 const Array& dest_array = Array::Handle(zone(), Array::New(dest_frame_size_)); |
445 PassiveObject& obj = PassiveObject::Handle(zone()); | 430 PassiveObject& obj = PassiveObject::Handle(zone()); |
446 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 431 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
447 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); | 432 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); |
448 dest_array.SetAt(i, obj); | 433 dest_array.SetAt(i, obj); |
449 } | 434 } |
450 return dest_array.raw(); | 435 return dest_array.raw(); |
451 } | 436 } |
452 | 437 |
453 | |
454 // Deoptimization instruction creating return address using function and | 438 // Deoptimization instruction creating return address using function and |
455 // deopt-id stored at 'object_table_index'. | 439 // deopt-id stored at 'object_table_index'. |
456 class DeoptRetAddressInstr : public DeoptInstr { | 440 class DeoptRetAddressInstr : public DeoptInstr { |
457 public: | 441 public: |
458 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) | 442 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) |
459 : object_table_index_(object_table_index), deopt_id_(deopt_id) { | 443 : object_table_index_(object_table_index), deopt_id_(deopt_id) { |
460 ASSERT(object_table_index >= 0); | 444 ASSERT(object_table_index >= 0); |
461 ASSERT(deopt_id >= 0); | 445 ASSERT(deopt_id >= 0); |
462 } | 446 } |
463 | 447 |
(...skipping 28 matching lines...) Expand all Loading... |
492 }; | 476 }; |
493 class DeoptId | 477 class DeoptId |
494 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; | 478 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; |
495 | 479 |
496 const intptr_t object_table_index_; | 480 const intptr_t object_table_index_; |
497 const intptr_t deopt_id_; | 481 const intptr_t deopt_id_; |
498 | 482 |
499 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddressInstr); | 483 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddressInstr); |
500 }; | 484 }; |
501 | 485 |
502 | |
503 // Deoptimization instruction moving a constant stored at 'object_table_index'. | 486 // Deoptimization instruction moving a constant stored at 'object_table_index'. |
504 class DeoptConstantInstr : public DeoptInstr { | 487 class DeoptConstantInstr : public DeoptInstr { |
505 public: | 488 public: |
506 explicit DeoptConstantInstr(intptr_t object_table_index) | 489 explicit DeoptConstantInstr(intptr_t object_table_index) |
507 : object_table_index_(object_table_index) { | 490 : object_table_index_(object_table_index) { |
508 ASSERT(object_table_index >= 0); | 491 ASSERT(object_table_index >= 0); |
509 } | 492 } |
510 | 493 |
511 virtual intptr_t source_index() const { return object_table_index_; } | 494 virtual intptr_t source_index() const { return object_table_index_; } |
512 virtual DeoptInstr::Kind kind() const { return kConstant; } | 495 virtual DeoptInstr::Kind kind() const { return kConstant; } |
(...skipping 13 matching lines...) Expand all Loading... |
526 intptr_t dest_slot) { | 509 intptr_t dest_slot) { |
527 return CatchEntryStatePair::FromConstant(object_table_index_, dest_slot); | 510 return CatchEntryStatePair::FromConstant(object_table_index_, dest_slot); |
528 } | 511 } |
529 | 512 |
530 private: | 513 private: |
531 const intptr_t object_table_index_; | 514 const intptr_t object_table_index_; |
532 | 515 |
533 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | 516 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); |
534 }; | 517 }; |
535 | 518 |
536 | |
537 // Deoptimization instruction moving value from optimized frame at | 519 // Deoptimization instruction moving value from optimized frame at |
538 // 'source_index' to specified slots in the unoptimized frame. | 520 // 'source_index' to specified slots in the unoptimized frame. |
539 // 'source_index' represents the slot index of the frame (0 being | 521 // 'source_index' represents the slot index of the frame (0 being |
540 // first argument) and accounts for saved return address, frame | 522 // first argument) and accounts for saved return address, frame |
541 // pointer, pool pointer and pc marker. | 523 // pointer, pool pointer and pc marker. |
542 // Deoptimization instruction moving a CPU register. | 524 // Deoptimization instruction moving a CPU register. |
543 class DeoptWordInstr : public DeoptInstr { | 525 class DeoptWordInstr : public DeoptInstr { |
544 public: | 526 public: |
545 explicit DeoptWordInstr(intptr_t source_index) : source_(source_index) {} | 527 explicit DeoptWordInstr(intptr_t source_index) : source_(source_index) {} |
546 | 528 |
(...skipping 13 matching lines...) Expand all Loading... |
560 return CatchEntryStatePair::FromMove(source_.StackSlot(deopt_context), | 542 return CatchEntryStatePair::FromMove(source_.StackSlot(deopt_context), |
561 dest_slot); | 543 dest_slot); |
562 } | 544 } |
563 | 545 |
564 private: | 546 private: |
565 const CpuRegisterSource source_; | 547 const CpuRegisterSource source_; |
566 | 548 |
567 DISALLOW_COPY_AND_ASSIGN(DeoptWordInstr); | 549 DISALLOW_COPY_AND_ASSIGN(DeoptWordInstr); |
568 }; | 550 }; |
569 | 551 |
570 | |
571 class DeoptIntegerInstrBase : public DeoptInstr { | 552 class DeoptIntegerInstrBase : public DeoptInstr { |
572 public: | 553 public: |
573 DeoptIntegerInstrBase() {} | 554 DeoptIntegerInstrBase() {} |
574 | 555 |
575 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 556 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
576 const int64_t value = GetValue(deopt_context); | 557 const int64_t value = GetValue(deopt_context); |
577 if (Smi::IsValid(value)) { | 558 if (Smi::IsValid(value)) { |
578 *dest_addr = Smi::RawValue(static_cast<intptr_t>(value)); | 559 *dest_addr = Smi::RawValue(static_cast<intptr_t>(value)); |
579 } else { | 560 } else { |
580 *dest_addr = Smi::RawValue(0); | 561 *dest_addr = Smi::RawValue(0); |
581 deopt_context->DeferMintMaterialization( | 562 deopt_context->DeferMintMaterialization( |
582 value, reinterpret_cast<RawMint**>(dest_addr)); | 563 value, reinterpret_cast<RawMint**>(dest_addr)); |
583 } | 564 } |
584 } | 565 } |
585 | 566 |
586 virtual int64_t GetValue(DeoptContext* deopt_context) = 0; | 567 virtual int64_t GetValue(DeoptContext* deopt_context) = 0; |
587 | 568 |
588 private: | 569 private: |
589 DISALLOW_COPY_AND_ASSIGN(DeoptIntegerInstrBase); | 570 DISALLOW_COPY_AND_ASSIGN(DeoptIntegerInstrBase); |
590 }; | 571 }; |
591 | 572 |
592 | |
593 class DeoptMintPairInstr : public DeoptIntegerInstrBase { | 573 class DeoptMintPairInstr : public DeoptIntegerInstrBase { |
594 public: | 574 public: |
595 explicit DeoptMintPairInstr(intptr_t source_index) | 575 explicit DeoptMintPairInstr(intptr_t source_index) |
596 : DeoptIntegerInstrBase(), | 576 : DeoptIntegerInstrBase(), |
597 lo_(LoRegister::decode(source_index)), | 577 lo_(LoRegister::decode(source_index)), |
598 hi_(HiRegister::decode(source_index)) {} | 578 hi_(HiRegister::decode(source_index)) {} |
599 | 579 |
600 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) | 580 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) |
601 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} | 581 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} |
602 | 582 |
(...skipping 18 matching lines...) Expand all Loading... |
621 class LoRegister : public BitField<intptr_t, intptr_t, 0, kFieldWidth> {}; | 601 class LoRegister : public BitField<intptr_t, intptr_t, 0, kFieldWidth> {}; |
622 class HiRegister | 602 class HiRegister |
623 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; | 603 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; |
624 | 604 |
625 const CpuRegisterSource lo_; | 605 const CpuRegisterSource lo_; |
626 const CpuRegisterSource hi_; | 606 const CpuRegisterSource hi_; |
627 | 607 |
628 DISALLOW_COPY_AND_ASSIGN(DeoptMintPairInstr); | 608 DISALLOW_COPY_AND_ASSIGN(DeoptMintPairInstr); |
629 }; | 609 }; |
630 | 610 |
631 | |
632 template <DeoptInstr::Kind K, typename T> | 611 template <DeoptInstr::Kind K, typename T> |
633 class DeoptIntInstr : public DeoptIntegerInstrBase { | 612 class DeoptIntInstr : public DeoptIntegerInstrBase { |
634 public: | 613 public: |
635 explicit DeoptIntInstr(intptr_t source_index) | 614 explicit DeoptIntInstr(intptr_t source_index) |
636 : DeoptIntegerInstrBase(), source_(source_index) {} | 615 : DeoptIntegerInstrBase(), source_(source_index) {} |
637 | 616 |
638 explicit DeoptIntInstr(const CpuRegisterSource& source) | 617 explicit DeoptIntInstr(const CpuRegisterSource& source) |
639 : DeoptIntegerInstrBase(), source_(source) {} | 618 : DeoptIntegerInstrBase(), source_(source) {} |
640 | 619 |
641 virtual intptr_t source_index() const { return source_.source_index(); } | 620 virtual intptr_t source_index() const { return source_.source_index(); } |
642 virtual DeoptInstr::Kind kind() const { return K; } | 621 virtual DeoptInstr::Kind kind() const { return K; } |
643 | 622 |
644 virtual const char* ArgumentsToCString() const { return source_.ToCString(); } | 623 virtual const char* ArgumentsToCString() const { return source_.ToCString(); } |
645 | 624 |
646 virtual int64_t GetValue(DeoptContext* deopt_context) { | 625 virtual int64_t GetValue(DeoptContext* deopt_context) { |
647 return static_cast<int64_t>(source_.Value<T>(deopt_context)); | 626 return static_cast<int64_t>(source_.Value<T>(deopt_context)); |
648 } | 627 } |
649 | 628 |
650 private: | 629 private: |
651 const CpuRegisterSource source_; | 630 const CpuRegisterSource source_; |
652 | 631 |
653 DISALLOW_COPY_AND_ASSIGN(DeoptIntInstr); | 632 DISALLOW_COPY_AND_ASSIGN(DeoptIntInstr); |
654 }; | 633 }; |
655 | 634 |
656 | |
657 typedef DeoptIntInstr<DeoptInstr::kUint32, uint32_t> DeoptUint32Instr; | 635 typedef DeoptIntInstr<DeoptInstr::kUint32, uint32_t> DeoptUint32Instr; |
658 typedef DeoptIntInstr<DeoptInstr::kInt32, int32_t> DeoptInt32Instr; | 636 typedef DeoptIntInstr<DeoptInstr::kInt32, int32_t> DeoptInt32Instr; |
659 typedef DeoptIntInstr<DeoptInstr::kMint, int64_t> DeoptMintInstr; | 637 typedef DeoptIntInstr<DeoptInstr::kMint, int64_t> DeoptMintInstr; |
660 | 638 |
661 | |
662 template <DeoptInstr::Kind K, typename Type, typename RawObjectType> | 639 template <DeoptInstr::Kind K, typename Type, typename RawObjectType> |
663 class DeoptFpuInstr : public DeoptInstr { | 640 class DeoptFpuInstr : public DeoptInstr { |
664 public: | 641 public: |
665 explicit DeoptFpuInstr(intptr_t source_index) : source_(source_index) {} | 642 explicit DeoptFpuInstr(intptr_t source_index) : source_(source_index) {} |
666 | 643 |
667 explicit DeoptFpuInstr(const FpuRegisterSource& source) : source_(source) {} | 644 explicit DeoptFpuInstr(const FpuRegisterSource& source) : source_(source) {} |
668 | 645 |
669 virtual intptr_t source_index() const { return source_.source_index(); } | 646 virtual intptr_t source_index() const { return source_.source_index(); } |
670 virtual DeoptInstr::Kind kind() const { return K; } | 647 virtual DeoptInstr::Kind kind() const { return K; } |
671 | 648 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
733 StubCode::FrameAwaitingMaterialization_entry()->code(); | 710 StubCode::FrameAwaitingMaterialization_entry()->code(); |
734 deopt_context->DeferPcMarkerMaterialization(object_table_index_, dest_addr); | 711 deopt_context->DeferPcMarkerMaterialization(object_table_index_, dest_addr); |
735 } | 712 } |
736 | 713 |
737 private: | 714 private: |
738 intptr_t object_table_index_; | 715 intptr_t object_table_index_; |
739 | 716 |
740 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); | 717 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); |
741 }; | 718 }; |
742 | 719 |
743 | |
744 // Deoptimization instruction creating a pool pointer for the code of | 720 // Deoptimization instruction creating a pool pointer for the code of |
745 // function at 'object_table_index'. | 721 // function at 'object_table_index'. |
746 class DeoptPpInstr : public DeoptInstr { | 722 class DeoptPpInstr : public DeoptInstr { |
747 public: | 723 public: |
748 explicit DeoptPpInstr(intptr_t object_table_index) | 724 explicit DeoptPpInstr(intptr_t object_table_index) |
749 : object_table_index_(object_table_index) { | 725 : object_table_index_(object_table_index) { |
750 ASSERT(object_table_index >= 0); | 726 ASSERT(object_table_index >= 0); |
751 } | 727 } |
752 | 728 |
753 virtual intptr_t source_index() const { return object_table_index_; } | 729 virtual intptr_t source_index() const { return object_table_index_; } |
754 virtual DeoptInstr::Kind kind() const { return kPp; } | 730 virtual DeoptInstr::Kind kind() const { return kPp; } |
755 | 731 |
756 virtual const char* ArgumentsToCString() const { | 732 virtual const char* ArgumentsToCString() const { |
757 return Thread::Current()->zone()->PrintToString("%" Pd "", | 733 return Thread::Current()->zone()->PrintToString("%" Pd "", |
758 object_table_index_); | 734 object_table_index_); |
759 } | 735 } |
760 | 736 |
761 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 737 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
762 *dest_addr = Smi::RawValue(0); | 738 *dest_addr = Smi::RawValue(0); |
763 deopt_context->DeferPpMaterialization( | 739 deopt_context->DeferPpMaterialization( |
764 object_table_index_, reinterpret_cast<RawObject**>(dest_addr)); | 740 object_table_index_, reinterpret_cast<RawObject**>(dest_addr)); |
765 } | 741 } |
766 | 742 |
767 private: | 743 private: |
768 intptr_t object_table_index_; | 744 intptr_t object_table_index_; |
769 | 745 |
770 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); | 746 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); |
771 }; | 747 }; |
772 | 748 |
773 | |
774 // Deoptimization instruction copying the caller saved FP from optimized frame. | 749 // Deoptimization instruction copying the caller saved FP from optimized frame. |
775 class DeoptCallerFpInstr : public DeoptInstr { | 750 class DeoptCallerFpInstr : public DeoptInstr { |
776 public: | 751 public: |
777 DeoptCallerFpInstr() {} | 752 DeoptCallerFpInstr() {} |
778 | 753 |
779 virtual intptr_t source_index() const { return 0; } | 754 virtual intptr_t source_index() const { return 0; } |
780 virtual DeoptInstr::Kind kind() const { return kCallerFp; } | 755 virtual DeoptInstr::Kind kind() const { return kCallerFp; } |
781 | 756 |
782 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 757 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
783 *dest_addr = deopt_context->GetCallerFp(); | 758 *dest_addr = deopt_context->GetCallerFp(); |
784 deopt_context->SetCallerFp( | 759 deopt_context->SetCallerFp( |
785 reinterpret_cast<intptr_t>(dest_addr - kSavedCallerFpSlotFromFp)); | 760 reinterpret_cast<intptr_t>(dest_addr - kSavedCallerFpSlotFromFp)); |
786 } | 761 } |
787 | 762 |
788 private: | 763 private: |
789 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | 764 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); |
790 }; | 765 }; |
791 | 766 |
792 | |
793 // Deoptimization instruction copying the caller saved PP from optimized frame. | 767 // Deoptimization instruction copying the caller saved PP from optimized frame. |
794 class DeoptCallerPpInstr : public DeoptInstr { | 768 class DeoptCallerPpInstr : public DeoptInstr { |
795 public: | 769 public: |
796 DeoptCallerPpInstr() {} | 770 DeoptCallerPpInstr() {} |
797 | 771 |
798 virtual intptr_t source_index() const { return 0; } | 772 virtual intptr_t source_index() const { return 0; } |
799 virtual DeoptInstr::Kind kind() const { return kCallerPp; } | 773 virtual DeoptInstr::Kind kind() const { return kCallerPp; } |
800 | 774 |
801 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 775 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
802 *dest_addr = deopt_context->GetSourcePp(); | 776 *dest_addr = deopt_context->GetSourcePp(); |
803 } | 777 } |
804 | 778 |
805 private: | 779 private: |
806 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPpInstr); | 780 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPpInstr); |
807 }; | 781 }; |
808 | 782 |
809 | |
810 // Deoptimization instruction copying the caller return address from optimized | 783 // Deoptimization instruction copying the caller return address from optimized |
811 // frame. | 784 // frame. |
812 class DeoptCallerPcInstr : public DeoptInstr { | 785 class DeoptCallerPcInstr : public DeoptInstr { |
813 public: | 786 public: |
814 DeoptCallerPcInstr() {} | 787 DeoptCallerPcInstr() {} |
815 | 788 |
816 virtual intptr_t source_index() const { return 0; } | 789 virtual intptr_t source_index() const { return 0; } |
817 virtual DeoptInstr::Kind kind() const { return kCallerPc; } | 790 virtual DeoptInstr::Kind kind() const { return kCallerPc; } |
818 | 791 |
819 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 792 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
820 *dest_addr = deopt_context->GetSourcePc(); | 793 *dest_addr = deopt_context->GetSourcePc(); |
821 } | 794 } |
822 | 795 |
823 private: | 796 private: |
824 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 797 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
825 }; | 798 }; |
826 | 799 |
827 | |
828 // Write reference to a materialized object with the given index into the | 800 // Write reference to a materialized object with the given index into the |
829 // stack slot. | 801 // stack slot. |
830 class DeoptMaterializedObjectRefInstr : public DeoptInstr { | 802 class DeoptMaterializedObjectRefInstr : public DeoptInstr { |
831 public: | 803 public: |
832 explicit DeoptMaterializedObjectRefInstr(intptr_t index) : index_(index) { | 804 explicit DeoptMaterializedObjectRefInstr(intptr_t index) : index_(index) { |
833 ASSERT(index >= 0); | 805 ASSERT(index >= 0); |
834 } | 806 } |
835 | 807 |
836 virtual intptr_t source_index() const { return index_; } | 808 virtual intptr_t source_index() const { return index_; } |
837 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } | 809 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } |
838 | 810 |
839 virtual const char* ArgumentsToCString() const { | 811 virtual const char* ArgumentsToCString() const { |
840 return Thread::Current()->zone()->PrintToString("#%" Pd "", index_); | 812 return Thread::Current()->zone()->PrintToString("#%" Pd "", index_); |
841 } | 813 } |
842 | 814 |
843 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 815 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
844 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | 816 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
845 deopt_context->DeferMaterializedObjectRef(index_, dest_addr); | 817 deopt_context->DeferMaterializedObjectRef(index_, dest_addr); |
846 } | 818 } |
847 | 819 |
848 private: | 820 private: |
849 intptr_t index_; | 821 intptr_t index_; |
850 | 822 |
851 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); | 823 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); |
852 }; | 824 }; |
853 | 825 |
854 | |
855 // Materialize object with the given number of fields. | 826 // Materialize object with the given number of fields. |
856 // Arguments for materialization (class and field-value pairs) are pushed | 827 // Arguments for materialization (class and field-value pairs) are pushed |
857 // to the expression stack of the bottom-most frame. | 828 // to the expression stack of the bottom-most frame. |
858 class DeoptMaterializeObjectInstr : public DeoptInstr { | 829 class DeoptMaterializeObjectInstr : public DeoptInstr { |
859 public: | 830 public: |
860 explicit DeoptMaterializeObjectInstr(intptr_t field_count) | 831 explicit DeoptMaterializeObjectInstr(intptr_t field_count) |
861 : field_count_(field_count) { | 832 : field_count_(field_count) { |
862 ASSERT(field_count >= 0); | 833 ASSERT(field_count >= 0); |
863 } | 834 } |
864 | 835 |
865 virtual intptr_t source_index() const { return field_count_; } | 836 virtual intptr_t source_index() const { return field_count_; } |
866 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } | 837 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } |
867 | 838 |
868 virtual const char* ArgumentsToCString() const { | 839 virtual const char* ArgumentsToCString() const { |
869 return Thread::Current()->zone()->PrintToString("%" Pd "", field_count_); | 840 return Thread::Current()->zone()->PrintToString("%" Pd "", field_count_); |
870 } | 841 } |
871 | 842 |
872 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 843 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
873 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. | 844 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. |
874 UNREACHABLE(); | 845 UNREACHABLE(); |
875 } | 846 } |
876 | 847 |
877 private: | 848 private: |
878 intptr_t field_count_; | 849 intptr_t field_count_; |
879 | 850 |
880 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); | 851 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); |
881 }; | 852 }; |
882 | 853 |
883 | |
884 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, | 854 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, |
885 const ObjectPool& object_table, | 855 const ObjectPool& object_table, |
886 Code* code) { | 856 Code* code) { |
887 ASSERT(instr->kind() == kRetAddress); | 857 ASSERT(instr->kind() == kRetAddress); |
888 DeoptRetAddressInstr* ret_address_instr = | 858 DeoptRetAddressInstr* ret_address_instr = |
889 static_cast<DeoptRetAddressInstr*>(instr); | 859 static_cast<DeoptRetAddressInstr*>(instr); |
890 // The following assert may trigger when displaying a backtrace | 860 // The following assert may trigger when displaying a backtrace |
891 // from the simulator. | 861 // from the simulator. |
892 ASSERT(Thread::IsDeoptAfter(ret_address_instr->deopt_id())); | 862 ASSERT(Thread::IsDeoptAfter(ret_address_instr->deopt_id())); |
893 ASSERT(!object_table.IsNull()); | 863 ASSERT(!object_table.IsNull()); |
894 Thread* thread = Thread::Current(); | 864 Thread* thread = Thread::Current(); |
895 Zone* zone = thread->zone(); | 865 Zone* zone = thread->zone(); |
896 Function& function = Function::Handle(zone); | 866 Function& function = Function::Handle(zone); |
897 function ^= object_table.ObjectAt(ret_address_instr->object_table_index()); | 867 function ^= object_table.ObjectAt(ret_address_instr->object_table_index()); |
898 ASSERT(code != NULL); | 868 ASSERT(code != NULL); |
899 const Error& error = | 869 const Error& error = |
900 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); | 870 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); |
901 if (!error.IsNull()) { | 871 if (!error.IsNull()) { |
902 Exceptions::PropagateError(error); | 872 Exceptions::PropagateError(error); |
903 } | 873 } |
904 *code ^= function.unoptimized_code(); | 874 *code ^= function.unoptimized_code(); |
905 ASSERT(!code->IsNull()); | 875 ASSERT(!code->IsNull()); |
906 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), | 876 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), |
907 RawPcDescriptors::kDeopt); | 877 RawPcDescriptors::kDeopt); |
908 ASSERT(res != 0); | 878 ASSERT(res != 0); |
909 return res; | 879 return res; |
910 } | 880 } |
911 | 881 |
912 | |
913 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { | 882 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { |
914 Kind kind = static_cast<Kind>(kind_as_int); | 883 Kind kind = static_cast<Kind>(kind_as_int); |
915 switch (kind) { | 884 switch (kind) { |
916 case kWord: | 885 case kWord: |
917 return new DeoptWordInstr(source_index); | 886 return new DeoptWordInstr(source_index); |
918 case kDouble: | 887 case kDouble: |
919 return new DeoptDoubleInstr(source_index); | 888 return new DeoptDoubleInstr(source_index); |
920 case kMint: | 889 case kMint: |
921 return new DeoptMintInstr(source_index); | 890 return new DeoptMintInstr(source_index); |
922 case kMintPair: | 891 case kMintPair: |
(...skipping 24 matching lines...) Expand all Loading... |
947 return new DeoptCallerPcInstr(); | 916 return new DeoptCallerPcInstr(); |
948 case kMaterializedObjectRef: | 917 case kMaterializedObjectRef: |
949 return new DeoptMaterializedObjectRefInstr(source_index); | 918 return new DeoptMaterializedObjectRefInstr(source_index); |
950 case kMaterializeObject: | 919 case kMaterializeObject: |
951 return new DeoptMaterializeObjectInstr(source_index); | 920 return new DeoptMaterializeObjectInstr(source_index); |
952 } | 921 } |
953 UNREACHABLE(); | 922 UNREACHABLE(); |
954 return NULL; | 923 return NULL; |
955 } | 924 } |
956 | 925 |
957 | |
958 const char* DeoptInstr::KindToCString(Kind kind) { | 926 const char* DeoptInstr::KindToCString(Kind kind) { |
959 switch (kind) { | 927 switch (kind) { |
960 case kWord: | 928 case kWord: |
961 return "word"; | 929 return "word"; |
962 case kDouble: | 930 case kDouble: |
963 return "double"; | 931 return "double"; |
964 case kMint: | 932 case kMint: |
965 case kMintPair: | 933 case kMintPair: |
966 return "mint"; | 934 return "mint"; |
967 case kInt32: | 935 case kInt32: |
(...skipping 22 matching lines...) Expand all Loading... |
990 return "callerpc"; | 958 return "callerpc"; |
991 case kMaterializedObjectRef: | 959 case kMaterializedObjectRef: |
992 return "ref"; | 960 return "ref"; |
993 case kMaterializeObject: | 961 case kMaterializeObject: |
994 return "mat"; | 962 return "mat"; |
995 } | 963 } |
996 UNREACHABLE(); | 964 UNREACHABLE(); |
997 return NULL; | 965 return NULL; |
998 } | 966 } |
999 | 967 |
1000 | |
1001 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { | 968 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { |
1002 public: | 969 public: |
1003 // Construct the root node representing the implicit "shared" terminator | 970 // Construct the root node representing the implicit "shared" terminator |
1004 // at the end of each deopt info. | 971 // at the end of each deopt info. |
1005 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) {} | 972 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) {} |
1006 | 973 |
1007 // Construct a node representing a written instruction. | 974 // Construct a node representing a written instruction. |
1008 TrieNode(DeoptInstr* instruction, intptr_t info_number) | 975 TrieNode(DeoptInstr* instruction, intptr_t info_number) |
1009 : instruction_(instruction), info_number_(info_number), children_(4) {} | 976 : instruction_(instruction), info_number_(info_number), children_(4) {} |
1010 | 977 |
(...skipping 11 matching lines...) Expand all Loading... |
1022 return NULL; | 989 return NULL; |
1023 } | 990 } |
1024 | 991 |
1025 private: | 992 private: |
1026 const DeoptInstr* instruction_; // Instruction that was written. | 993 const DeoptInstr* instruction_; // Instruction that was written. |
1027 const intptr_t info_number_; // Index of the deopt info it was written to. | 994 const intptr_t info_number_; // Index of the deopt info it was written to. |
1028 | 995 |
1029 GrowableArray<TrieNode*> children_; | 996 GrowableArray<TrieNode*> children_; |
1030 }; | 997 }; |
1031 | 998 |
1032 | |
1033 DeoptInfoBuilder::DeoptInfoBuilder(Zone* zone, | 999 DeoptInfoBuilder::DeoptInfoBuilder(Zone* zone, |
1034 const intptr_t num_args, | 1000 const intptr_t num_args, |
1035 Assembler* assembler) | 1001 Assembler* assembler) |
1036 : zone_(zone), | 1002 : zone_(zone), |
1037 instructions_(), | 1003 instructions_(), |
1038 num_args_(num_args), | 1004 num_args_(num_args), |
1039 assembler_(assembler), | 1005 assembler_(assembler), |
1040 trie_root_(new (zone) TrieNode()), | 1006 trie_root_(new (zone) TrieNode()), |
1041 current_info_number_(0), | 1007 current_info_number_(0), |
1042 frame_start_(-1), | 1008 frame_start_(-1), |
1043 materializations_() {} | 1009 materializations_() {} |
1044 | 1010 |
1045 | |
1046 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { | 1011 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { |
1047 return assembler_->object_pool_wrapper().FindObject(obj); | 1012 return assembler_->object_pool_wrapper().FindObject(obj); |
1048 } | 1013 } |
1049 | 1014 |
1050 | |
1051 intptr_t DeoptInfoBuilder::CalculateStackIndex( | 1015 intptr_t DeoptInfoBuilder::CalculateStackIndex( |
1052 const Location& source_loc) const { | 1016 const Location& source_loc) const { |
1053 return source_loc.stack_index() < 0 | 1017 return source_loc.stack_index() < 0 |
1054 ? source_loc.stack_index() + num_args_ | 1018 ? source_loc.stack_index() + num_args_ |
1055 : source_loc.stack_index() + num_args_ + kDartFrameFixedSize; | 1019 : source_loc.stack_index() + num_args_ + kDartFrameFixedSize; |
1056 } | 1020 } |
1057 | 1021 |
1058 | |
1059 CpuRegisterSource DeoptInfoBuilder::ToCpuRegisterSource(const Location& loc) { | 1022 CpuRegisterSource DeoptInfoBuilder::ToCpuRegisterSource(const Location& loc) { |
1060 if (loc.IsRegister()) { | 1023 if (loc.IsRegister()) { |
1061 return CpuRegisterSource(CpuRegisterSource::kRegister, loc.reg()); | 1024 return CpuRegisterSource(CpuRegisterSource::kRegister, loc.reg()); |
1062 } else { | 1025 } else { |
1063 ASSERT(loc.IsStackSlot()); | 1026 ASSERT(loc.IsStackSlot()); |
1064 return CpuRegisterSource(CpuRegisterSource::kStackSlot, | 1027 return CpuRegisterSource(CpuRegisterSource::kStackSlot, |
1065 CalculateStackIndex(loc)); | 1028 CalculateStackIndex(loc)); |
1066 } | 1029 } |
1067 } | 1030 } |
1068 | 1031 |
1069 | |
1070 FpuRegisterSource DeoptInfoBuilder::ToFpuRegisterSource( | 1032 FpuRegisterSource DeoptInfoBuilder::ToFpuRegisterSource( |
1071 const Location& loc, | 1033 const Location& loc, |
1072 Location::Kind stack_slot_kind) { | 1034 Location::Kind stack_slot_kind) { |
1073 if (loc.IsFpuRegister()) { | 1035 if (loc.IsFpuRegister()) { |
1074 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); | 1036 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); |
1075 #if defined(TARGET_ARCH_DBC) | 1037 #if defined(TARGET_ARCH_DBC) |
1076 } else if (loc.IsRegister()) { | 1038 } else if (loc.IsRegister()) { |
1077 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg()); | 1039 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg()); |
1078 #endif | 1040 #endif |
1079 } else { | 1041 } else { |
1080 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || | 1042 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || |
1081 (stack_slot_kind == Location::kDoubleStackSlot)); | 1043 (stack_slot_kind == Location::kDoubleStackSlot)); |
1082 ASSERT(loc.kind() == stack_slot_kind); | 1044 ASSERT(loc.kind() == stack_slot_kind); |
1083 return FpuRegisterSource(FpuRegisterSource::kStackSlot, | 1045 return FpuRegisterSource(FpuRegisterSource::kStackSlot, |
1084 CalculateStackIndex(loc)); | 1046 CalculateStackIndex(loc)); |
1085 } | 1047 } |
1086 } | 1048 } |
1087 | 1049 |
1088 void DeoptInfoBuilder::AddReturnAddress(const Function& function, | 1050 void DeoptInfoBuilder::AddReturnAddress(const Function& function, |
1089 intptr_t deopt_id, | 1051 intptr_t deopt_id, |
1090 intptr_t dest_index) { | 1052 intptr_t dest_index) { |
1091 const intptr_t object_table_index = FindOrAddObjectInTable(function); | 1053 const intptr_t object_table_index = FindOrAddObjectInTable(function); |
1092 ASSERT(dest_index == FrameSize()); | 1054 ASSERT(dest_index == FrameSize()); |
1093 instructions_.Add(new (zone()) | 1055 instructions_.Add(new (zone()) |
1094 DeoptRetAddressInstr(object_table_index, deopt_id)); | 1056 DeoptRetAddressInstr(object_table_index, deopt_id)); |
1095 } | 1057 } |
1096 | 1058 |
1097 | |
1098 void DeoptInfoBuilder::AddPcMarker(const Function& function, | 1059 void DeoptInfoBuilder::AddPcMarker(const Function& function, |
1099 intptr_t dest_index) { | 1060 intptr_t dest_index) { |
1100 intptr_t object_table_index = FindOrAddObjectInTable(function); | 1061 intptr_t object_table_index = FindOrAddObjectInTable(function); |
1101 ASSERT(dest_index == FrameSize()); | 1062 ASSERT(dest_index == FrameSize()); |
1102 instructions_.Add(new (zone()) DeoptPcMarkerInstr(object_table_index)); | 1063 instructions_.Add(new (zone()) DeoptPcMarkerInstr(object_table_index)); |
1103 } | 1064 } |
1104 | 1065 |
1105 | |
1106 void DeoptInfoBuilder::AddPp(const Function& function, intptr_t dest_index) { | 1066 void DeoptInfoBuilder::AddPp(const Function& function, intptr_t dest_index) { |
1107 intptr_t object_table_index = FindOrAddObjectInTable(function); | 1067 intptr_t object_table_index = FindOrAddObjectInTable(function); |
1108 ASSERT(dest_index == FrameSize()); | 1068 ASSERT(dest_index == FrameSize()); |
1109 instructions_.Add(new (zone()) DeoptPpInstr(object_table_index)); | 1069 instructions_.Add(new (zone()) DeoptPpInstr(object_table_index)); |
1110 } | 1070 } |
1111 | 1071 |
1112 | |
1113 void DeoptInfoBuilder::AddCopy(Value* value, | 1072 void DeoptInfoBuilder::AddCopy(Value* value, |
1114 const Location& source_loc, | 1073 const Location& source_loc, |
1115 const intptr_t dest_index) { | 1074 const intptr_t dest_index) { |
1116 DeoptInstr* deopt_instr = NULL; | 1075 DeoptInstr* deopt_instr = NULL; |
1117 if (source_loc.IsConstant()) { | 1076 if (source_loc.IsConstant()) { |
1118 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); | 1077 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); |
1119 deopt_instr = new (zone()) DeoptConstantInstr(object_table_index); | 1078 deopt_instr = new (zone()) DeoptConstantInstr(object_table_index); |
1120 } else if (source_loc.IsInvalid() && | 1079 } else if (source_loc.IsInvalid() && |
1121 value->definition()->IsMaterializeObject()) { | 1080 value->definition()->IsMaterializeObject()) { |
1122 const intptr_t index = | 1081 const intptr_t index = |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 default: | 1135 default: |
1177 UNREACHABLE(); | 1136 UNREACHABLE(); |
1178 break; | 1137 break; |
1179 } | 1138 } |
1180 } | 1139 } |
1181 ASSERT(dest_index == FrameSize()); | 1140 ASSERT(dest_index == FrameSize()); |
1182 ASSERT(deopt_instr != NULL); | 1141 ASSERT(deopt_instr != NULL); |
1183 instructions_.Add(deopt_instr); | 1142 instructions_.Add(deopt_instr); |
1184 } | 1143 } |
1185 | 1144 |
1186 | |
1187 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { | 1145 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { |
1188 ASSERT(dest_index == FrameSize()); | 1146 ASSERT(dest_index == FrameSize()); |
1189 instructions_.Add(new (zone()) DeoptCallerFpInstr()); | 1147 instructions_.Add(new (zone()) DeoptCallerFpInstr()); |
1190 } | 1148 } |
1191 | 1149 |
1192 | |
1193 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { | 1150 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { |
1194 ASSERT(dest_index == FrameSize()); | 1151 ASSERT(dest_index == FrameSize()); |
1195 instructions_.Add(new (zone()) DeoptCallerPpInstr()); | 1152 instructions_.Add(new (zone()) DeoptCallerPpInstr()); |
1196 } | 1153 } |
1197 | 1154 |
1198 | |
1199 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { | 1155 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { |
1200 ASSERT(dest_index == FrameSize()); | 1156 ASSERT(dest_index == FrameSize()); |
1201 instructions_.Add(new (zone()) DeoptCallerPcInstr()); | 1157 instructions_.Add(new (zone()) DeoptCallerPcInstr()); |
1202 } | 1158 } |
1203 | 1159 |
1204 | |
1205 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { | 1160 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { |
1206 ASSERT(dest_index == FrameSize()); | 1161 ASSERT(dest_index == FrameSize()); |
1207 intptr_t object_table_index = FindOrAddObjectInTable(obj); | 1162 intptr_t object_table_index = FindOrAddObjectInTable(obj); |
1208 instructions_.Add(new (zone()) DeoptConstantInstr(object_table_index)); | 1163 instructions_.Add(new (zone()) DeoptConstantInstr(object_table_index)); |
1209 } | 1164 } |
1210 | 1165 |
1211 | |
1212 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { | 1166 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { |
1213 const intptr_t index = FindMaterialization(mat); | 1167 const intptr_t index = FindMaterialization(mat); |
1214 if (index >= 0) { | 1168 if (index >= 0) { |
1215 return; // Already added. | 1169 return; // Already added. |
1216 } | 1170 } |
1217 materializations_.Add(mat); | 1171 materializations_.Add(mat); |
1218 | 1172 |
1219 // Count initialized fields and emit kMaterializeObject instruction. | 1173 // Count initialized fields and emit kMaterializeObject instruction. |
1220 // There is no need to write nulls into fields because object is null | 1174 // There is no need to write nulls into fields because object is null |
1221 // initialized by default. | 1175 // initialized by default. |
1222 intptr_t non_null_fields = 0; | 1176 intptr_t non_null_fields = 0; |
1223 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1177 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
1224 if (!mat->InputAt(i)->BindsToConstantNull()) { | 1178 if (!mat->InputAt(i)->BindsToConstantNull()) { |
1225 non_null_fields++; | 1179 non_null_fields++; |
1226 } | 1180 } |
1227 } | 1181 } |
1228 | 1182 |
1229 instructions_.Add(new (zone()) DeoptMaterializeObjectInstr(non_null_fields)); | 1183 instructions_.Add(new (zone()) DeoptMaterializeObjectInstr(non_null_fields)); |
1230 | 1184 |
1231 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1185 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
1232 MaterializeObjectInstr* nested_mat = | 1186 MaterializeObjectInstr* nested_mat = |
1233 mat->InputAt(i)->definition()->AsMaterializeObject(); | 1187 mat->InputAt(i)->definition()->AsMaterializeObject(); |
1234 if (nested_mat != NULL) { | 1188 if (nested_mat != NULL) { |
1235 AddMaterialization(nested_mat); | 1189 AddMaterialization(nested_mat); |
1236 } | 1190 } |
1237 } | 1191 } |
1238 } | 1192 } |
1239 | 1193 |
1240 | |
1241 intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) { | 1194 intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) { |
1242 ASSERT(dest_index == kDartFrameFixedSize); | 1195 ASSERT(dest_index == kDartFrameFixedSize); |
1243 for (intptr_t i = 0; i < materializations_.length(); i++) { | 1196 for (intptr_t i = 0; i < materializations_.length(); i++) { |
1244 MaterializeObjectInstr* mat = materializations_[i]; | 1197 MaterializeObjectInstr* mat = materializations_[i]; |
1245 // Class of the instance to allocate. | 1198 // Class of the instance to allocate. |
1246 AddConstant(mat->cls(), dest_index++); | 1199 AddConstant(mat->cls(), dest_index++); |
1247 AddConstant(Smi::ZoneHandle(Smi::New(mat->num_variables())), dest_index++); | 1200 AddConstant(Smi::ZoneHandle(Smi::New(mat->num_variables())), dest_index++); |
1248 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1201 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
1249 if (!mat->InputAt(i)->BindsToConstantNull()) { | 1202 if (!mat->InputAt(i)->BindsToConstantNull()) { |
1250 // Emit offset-value pair. | 1203 // Emit offset-value pair. |
1251 AddConstant(Smi::ZoneHandle(Smi::New(mat->FieldOffsetAt(i))), | 1204 AddConstant(Smi::ZoneHandle(Smi::New(mat->FieldOffsetAt(i))), |
1252 dest_index++); | 1205 dest_index++); |
1253 AddCopy(mat->InputAt(i), mat->LocationAt(i), dest_index++); | 1206 AddCopy(mat->InputAt(i), mat->LocationAt(i), dest_index++); |
1254 } | 1207 } |
1255 } | 1208 } |
1256 } | 1209 } |
1257 return dest_index; | 1210 return dest_index; |
1258 } | 1211 } |
1259 | 1212 |
1260 | |
1261 intptr_t DeoptInfoBuilder::FindMaterialization( | 1213 intptr_t DeoptInfoBuilder::FindMaterialization( |
1262 MaterializeObjectInstr* mat) const { | 1214 MaterializeObjectInstr* mat) const { |
1263 for (intptr_t i = 0; i < materializations_.length(); i++) { | 1215 for (intptr_t i = 0; i < materializations_.length(); i++) { |
1264 if (materializations_[i] == mat) { | 1216 if (materializations_[i] == mat) { |
1265 return i; | 1217 return i; |
1266 } | 1218 } |
1267 } | 1219 } |
1268 return -1; | 1220 return -1; |
1269 } | 1221 } |
1270 | 1222 |
1271 | |
1272 static uint8_t* ZoneReAlloc(uint8_t* ptr, | 1223 static uint8_t* ZoneReAlloc(uint8_t* ptr, |
1273 intptr_t old_size, | 1224 intptr_t old_size, |
1274 intptr_t new_size) { | 1225 intptr_t new_size) { |
1275 return Thread::Current()->zone()->Realloc<uint8_t>(ptr, old_size, new_size); | 1226 return Thread::Current()->zone()->Realloc<uint8_t>(ptr, old_size, new_size); |
1276 } | 1227 } |
1277 | 1228 |
1278 | |
1279 RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) { | 1229 RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) { |
1280 intptr_t length = instructions_.length(); | 1230 intptr_t length = instructions_.length(); |
1281 | 1231 |
1282 // Count the number of instructions that are a shared suffix of some deopt | 1232 // Count the number of instructions that are a shared suffix of some deopt |
1283 // info already written. | 1233 // info already written. |
1284 TrieNode* suffix = trie_root_; | 1234 TrieNode* suffix = trie_root_; |
1285 intptr_t suffix_length = 0; | 1235 intptr_t suffix_length = 0; |
1286 if (FLAG_compress_deopt_info) { | 1236 if (FLAG_compress_deopt_info) { |
1287 for (intptr_t i = length - 1; i >= 0; --i) { | 1237 for (intptr_t i = length - 1; i >= 0; --i) { |
1288 TrieNode* node = suffix->FindChild(*instructions_[i]); | 1238 TrieNode* node = suffix->FindChild(*instructions_[i]); |
1289 if (node == NULL) break; | 1239 if (node == NULL) break; |
1290 suffix = node; | 1240 suffix = node; |
1291 ++suffix_length; | 1241 ++suffix_length; |
1292 } | 1242 } |
1293 } | 1243 } |
1294 | 1244 |
1295 | |
1296 // Allocate space for the translation. If the shared suffix is longer | 1245 // Allocate space for the translation. If the shared suffix is longer |
1297 // than one instruction, we replace it with a single suffix instruction. | 1246 // than one instruction, we replace it with a single suffix instruction. |
1298 const bool use_suffix = suffix_length > 1; | 1247 const bool use_suffix = suffix_length > 1; |
1299 if (use_suffix) { | 1248 if (use_suffix) { |
1300 length -= (suffix_length - 1); | 1249 length -= (suffix_length - 1); |
1301 } | 1250 } |
1302 | 1251 |
1303 uint8_t* buffer; | 1252 uint8_t* buffer; |
1304 typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer; | 1253 typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer; |
1305 WriteStream stream(&buffer, ZoneReAlloc, 2 * length * kWordSize); | 1254 WriteStream stream(&buffer, ZoneReAlloc, 2 * length * kWordSize); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 ASSERT( | 1286 ASSERT( |
1338 DeoptInfo::VerifyDecompression(instructions_, deopt_table, deopt_info)); | 1287 DeoptInfo::VerifyDecompression(instructions_, deopt_table, deopt_info)); |
1339 instructions_.Clear(); | 1288 instructions_.Clear(); |
1340 materializations_.Clear(); | 1289 materializations_.Clear(); |
1341 frame_start_ = -1; | 1290 frame_start_ = -1; |
1342 | 1291 |
1343 ++current_info_number_; | 1292 ++current_info_number_; |
1344 return deopt_info.raw(); | 1293 return deopt_info.raw(); |
1345 } | 1294 } |
1346 | 1295 |
1347 | |
1348 intptr_t DeoptTable::SizeFor(intptr_t length) { | 1296 intptr_t DeoptTable::SizeFor(intptr_t length) { |
1349 return length * kEntrySize; | 1297 return length * kEntrySize; |
1350 } | 1298 } |
1351 | 1299 |
1352 void DeoptTable::SetEntry(const Array& table, | 1300 void DeoptTable::SetEntry(const Array& table, |
1353 intptr_t index, | 1301 intptr_t index, |
1354 const Smi& offset, | 1302 const Smi& offset, |
1355 const TypedData& info, | 1303 const TypedData& info, |
1356 const Smi& reason) { | 1304 const Smi& reason) { |
1357 ASSERT((table.Length() % kEntrySize) == 0); | 1305 ASSERT((table.Length() % kEntrySize) == 0); |
1358 intptr_t i = index * kEntrySize; | 1306 intptr_t i = index * kEntrySize; |
1359 table.SetAt(i, offset); | 1307 table.SetAt(i, offset); |
1360 table.SetAt(i + 1, info); | 1308 table.SetAt(i + 1, info); |
1361 table.SetAt(i + 2, reason); | 1309 table.SetAt(i + 2, reason); |
1362 } | 1310 } |
1363 | 1311 |
1364 | |
1365 intptr_t DeoptTable::GetLength(const Array& table) { | 1312 intptr_t DeoptTable::GetLength(const Array& table) { |
1366 ASSERT((table.Length() % kEntrySize) == 0); | 1313 ASSERT((table.Length() % kEntrySize) == 0); |
1367 return table.Length() / kEntrySize; | 1314 return table.Length() / kEntrySize; |
1368 } | 1315 } |
1369 | 1316 |
1370 | |
1371 void DeoptTable::GetEntry(const Array& table, | 1317 void DeoptTable::GetEntry(const Array& table, |
1372 intptr_t index, | 1318 intptr_t index, |
1373 Smi* offset, | 1319 Smi* offset, |
1374 TypedData* info, | 1320 TypedData* info, |
1375 Smi* reason) { | 1321 Smi* reason) { |
1376 intptr_t i = index * kEntrySize; | 1322 intptr_t i = index * kEntrySize; |
1377 *offset ^= table.At(i); | 1323 *offset ^= table.At(i); |
1378 *info ^= table.At(i + 1); | 1324 *info ^= table.At(i + 1); |
1379 *reason ^= table.At(i + 2); | 1325 *reason ^= table.At(i + 2); |
1380 } | 1326 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1478 GrowableArray<DeoptInstr*> unpacked; | 1424 GrowableArray<DeoptInstr*> unpacked; |
1479 Unpack(deopt_table, packed, &unpacked); | 1425 Unpack(deopt_table, packed, &unpacked); |
1480 ASSERT(unpacked.length() == original.length()); | 1426 ASSERT(unpacked.length() == original.length()); |
1481 for (intptr_t i = 0; i < unpacked.length(); ++i) { | 1427 for (intptr_t i = 0; i < unpacked.length(); ++i) { |
1482 ASSERT(unpacked[i]->Equals(*original[i])); | 1428 ASSERT(unpacked[i]->Equals(*original[i])); |
1483 } | 1429 } |
1484 return true; | 1430 return true; |
1485 } | 1431 } |
1486 | 1432 |
1487 } // namespace dart | 1433 } // namespace dart |
OLD | NEW |