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, compress_deopt_info, true, | 20 DEFINE_FLAG(bool, |
| 21 compress_deopt_info, |
| 22 true, |
21 "Compress the size of the deoptimization info for optimized code."); | 23 "Compress the size of the deoptimization info for optimized code."); |
22 DECLARE_FLAG(bool, trace_deoptimization); | 24 DECLARE_FLAG(bool, trace_deoptimization); |
23 DECLARE_FLAG(bool, trace_deoptimization_verbose); | 25 DECLARE_FLAG(bool, trace_deoptimization_verbose); |
24 | 26 |
25 | 27 |
26 DeoptContext::DeoptContext(const StackFrame* frame, | 28 DeoptContext::DeoptContext(const StackFrame* frame, |
27 const Code& code, | 29 const Code& code, |
28 DestFrameOptions dest_options, | 30 DestFrameOptions dest_options, |
29 fpu_register_t* fpu_registers, | 31 fpu_register_t* fpu_registers, |
30 intptr_t* cpu_registers, | 32 intptr_t* cpu_registers, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 ASSERT(!deopt_info.IsNull()); | 65 ASSERT(!deopt_info.IsNull()); |
64 deopt_info_ = deopt_info.raw(); | 66 deopt_info_ = deopt_info.raw(); |
65 | 67 |
66 const Function& function = Function::Handle(code.function()); | 68 const Function& function = Function::Handle(code.function()); |
67 | 69 |
68 // Do not include incoming arguments if there are optional arguments | 70 // Do not include incoming arguments if there are optional arguments |
69 // (they are copied into local space at method entry). | 71 // (they are copied into local space at method entry). |
70 num_args_ = | 72 num_args_ = |
71 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 73 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
72 | 74 |
73 // The fixed size section of the (fake) Dart frame called via a stub by the | 75 // The fixed size section of the (fake) Dart frame called via a stub by the |
74 // optimized function contains FP, PP (ARM and MIPS only), PC-marker and | 76 // optimized function contains FP, PP (ARM and MIPS only), PC-marker and |
75 // return-address. This section is copied as well, so that its contained | 77 // return-address. This section is copied as well, so that its contained |
76 // values can be updated before returning to the deoptimized function. | 78 // values can be updated before returning to the deoptimized function. |
77 // Note: on DBC stack grows upwards unlike on all other architectures. | 79 // Note: on DBC stack grows upwards unlike on all other architectures. |
78 #if defined(TARGET_ARCH_DBC) | 80 #if defined(TARGET_ARCH_DBC) |
79 ASSERT(frame->sp() >= frame->fp()); | 81 ASSERT(frame->sp() >= frame->fp()); |
80 const intptr_t frame_size = (frame->sp() - frame->fp()) / kWordSize; | 82 const intptr_t frame_size = (frame->sp() - frame->fp()) / kWordSize; |
81 #else | 83 #else |
82 ASSERT(frame->fp() >= frame->sp()); | 84 ASSERT(frame->fp() >= frame->sp()); |
83 const intptr_t frame_size = (frame->fp() - frame->sp()) / kWordSize; | 85 const intptr_t frame_size = (frame->fp() - frame->sp()) / kWordSize; |
84 #endif | 86 #endif |
85 | 87 |
86 source_frame_size_ = | 88 source_frame_size_ = +kDartFrameFixedSize // For saved values below sp. |
87 + kDartFrameFixedSize // For saved values below sp. | 89 + frame_size // For frame size incl. sp. |
88 + frame_size // For frame size incl. sp. | 90 + 1 // For fp. |
89 + 1 // For fp. | 91 + kParamEndSlotFromFp // For saved values above fp. |
90 + kParamEndSlotFromFp // For saved values above fp. | 92 + num_args_; // For arguments. |
91 + num_args_; // For arguments. | |
92 | 93 |
93 source_frame_ = FrameBase(frame); | 94 source_frame_ = FrameBase(frame); |
94 | 95 |
95 if (dest_options == kDestIsOriginalFrame) { | 96 if (dest_options == kDestIsOriginalFrame) { |
96 // Work from a copy of the source frame. | 97 // Work from a copy of the source frame. |
97 intptr_t* original_frame = source_frame_; | 98 intptr_t* original_frame = source_frame_; |
98 source_frame_ = new intptr_t[source_frame_size_]; | 99 source_frame_ = new intptr_t[source_frame_size_]; |
99 ASSERT(source_frame_ != NULL); | 100 ASSERT(source_frame_ != NULL); |
100 for (intptr_t i = 0; i < source_frame_size_; i++) { | 101 for (intptr_t i = 0; i < source_frame_size_; i++) { |
101 source_frame_[i] = original_frame[i]; | 102 source_frame_[i] = original_frame[i]; |
(...skipping 16 matching lines...) Expand all Loading... |
118 if (dest_options != kDestIsAllocated) { | 119 if (dest_options != kDestIsAllocated) { |
119 // kDestIsAllocated is used by the debugger to generate a stack trace | 120 // kDestIsAllocated is used by the debugger to generate a stack trace |
120 // and does not signal a real deopt. | 121 // and does not signal a real deopt. |
121 deopt_start_micros_ = OS::GetCurrentMonotonicMicros(); | 122 deopt_start_micros_ = OS::GetCurrentMonotonicMicros(); |
122 } | 123 } |
123 | 124 |
124 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | 125 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
125 THR_Print( | 126 THR_Print( |
126 "Deoptimizing (reason %d '%s') at " | 127 "Deoptimizing (reason %d '%s') at " |
127 "pc=%" Pp " fp=%" Pp " '%s' (count %d)\n", | 128 "pc=%" Pp " fp=%" Pp " '%s' (count %d)\n", |
128 deopt_reason(), | 129 deopt_reason(), DeoptReasonToCString(deopt_reason()), frame->pc(), |
129 DeoptReasonToCString(deopt_reason()), | 130 frame->fp(), function.ToFullyQualifiedCString(), |
130 frame->pc(), | |
131 frame->fp(), | |
132 function.ToFullyQualifiedCString(), | |
133 function.deoptimization_counter()); | 131 function.deoptimization_counter()); |
134 } | 132 } |
135 } | 133 } |
136 | 134 |
137 | 135 |
138 DeoptContext::~DeoptContext() { | 136 DeoptContext::~DeoptContext() { |
139 // Delete memory for source frame and registers. | 137 // Delete memory for source frame and registers. |
140 if (source_frame_is_allocated_) { | 138 if (source_frame_is_allocated_) { |
141 delete[] source_frame_; | 139 delete[] source_frame_; |
142 } | 140 } |
(...skipping 22 matching lines...) Expand all Loading... |
165 // Allocate all Dart objects needed before calling StartEvent, | 163 // Allocate all Dart objects needed before calling StartEvent, |
166 // which blocks safe points until Complete is called. | 164 // which blocks safe points until Complete is called. |
167 const Code& code = Code::Handle(zone(), code_); | 165 const Code& code = Code::Handle(zone(), code_); |
168 const Function& function = Function::Handle(zone(), code.function()); | 166 const Function& function = Function::Handle(zone(), code.function()); |
169 const String& function_name = | 167 const String& function_name = |
170 String::Handle(zone(), function.QualifiedScrubbedName()); | 168 String::Handle(zone(), function.QualifiedScrubbedName()); |
171 const char* reason = DeoptReasonToCString(deopt_reason()); | 169 const char* reason = DeoptReasonToCString(deopt_reason()); |
172 const int counter = function.deoptimization_counter(); | 170 const int counter = function.deoptimization_counter(); |
173 TimelineEvent* timeline_event = compiler_stream->StartEvent(); | 171 TimelineEvent* timeline_event = compiler_stream->StartEvent(); |
174 if (timeline_event != NULL) { | 172 if (timeline_event != NULL) { |
175 timeline_event->Duration("Deoptimize", | 173 timeline_event->Duration("Deoptimize", deopt_start_micros_, |
176 deopt_start_micros_, | |
177 OS::GetCurrentMonotonicMicros()); | 174 OS::GetCurrentMonotonicMicros()); |
178 timeline_event->SetNumArguments(3); | 175 timeline_event->SetNumArguments(3); |
179 timeline_event->CopyArgument(0, "function", function_name.ToCString()); | 176 timeline_event->CopyArgument(0, "function", function_name.ToCString()); |
180 timeline_event->CopyArgument(1, "reason", reason); | 177 timeline_event->CopyArgument(1, "reason", reason); |
181 timeline_event->FormatArgument(2, "deoptimizationCount", "%d", counter); | 178 timeline_event->FormatArgument(2, "deoptimizationCount", "%d", counter); |
182 timeline_event->Complete(); | 179 timeline_event->Complete(); |
183 } | 180 } |
184 } | 181 } |
185 } | 182 } |
186 #endif // !PRODUCT | 183 #endif // !PRODUCT |
187 } | 184 } |
188 | 185 |
189 | 186 |
190 void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 187 void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
191 visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_pool_)); | 188 visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_pool_)); |
192 visitor->VisitPointer(reinterpret_cast<RawObject**>(&deopt_info_)); | 189 visitor->VisitPointer(reinterpret_cast<RawObject**>(&deopt_info_)); |
193 | 190 |
194 // Visit any object pointers on the destination stack. | 191 // Visit any object pointers on the destination stack. |
195 if (dest_frame_is_allocated_) { | 192 if (dest_frame_is_allocated_) { |
196 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 193 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
197 if (dest_frame_[i] != 0) { | 194 if (dest_frame_[i] != 0) { |
198 visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i])); | 195 visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i])); |
199 } | 196 } |
200 } | 197 } |
201 } | 198 } |
202 } | 199 } |
203 | 200 |
204 | 201 |
205 intptr_t DeoptContext::DestStackAdjustment() const { | 202 intptr_t DeoptContext::DestStackAdjustment() const { |
206 return dest_frame_size_ | 203 return dest_frame_size_ - kDartFrameFixedSize - num_args_ |
207 - kDartFrameFixedSize | |
208 - num_args_ | |
209 #if !defined(TARGET_ARCH_DBC) | 204 #if !defined(TARGET_ARCH_DBC) |
210 - 1 // For fp. | 205 - 1 // For fp. |
211 #endif | 206 #endif |
212 - kParamEndSlotFromFp; | 207 - kParamEndSlotFromFp; |
213 } | 208 } |
214 | 209 |
215 | 210 |
216 intptr_t DeoptContext::GetSourceFp() const { | 211 intptr_t DeoptContext::GetSourceFp() const { |
217 #if !defined(TARGET_ARCH_DBC) | 212 #if !defined(TARGET_ARCH_DBC) |
218 return source_frame_[source_frame_size_ - 1 - num_args_ - | 213 return source_frame_[source_frame_size_ - 1 - num_args_ - |
219 kParamEndSlotFromFp]; | 214 kParamEndSlotFromFp]; |
220 #else | 215 #else |
221 return source_frame_[num_args_ + kDartFrameFixedSize + | 216 return source_frame_[num_args_ + kDartFrameFixedSize + |
222 kSavedCallerFpSlotFromFp]; | 217 kSavedCallerFpSlotFromFp]; |
223 #endif | 218 #endif |
224 } | 219 } |
225 | 220 |
226 | 221 |
227 intptr_t DeoptContext::GetSourcePp() const { | 222 intptr_t DeoptContext::GetSourcePp() const { |
228 #if !defined(TARGET_ARCH_DBC) | 223 #if !defined(TARGET_ARCH_DBC) |
229 return source_frame_[source_frame_size_ - 1 - num_args_ - | 224 return source_frame_[source_frame_size_ - 1 - num_args_ - |
230 kParamEndSlotFromFp + | 225 kParamEndSlotFromFp + |
231 StackFrame::SavedCallerPpSlotFromFp()]; | 226 StackFrame::SavedCallerPpSlotFromFp()]; |
232 #else | 227 #else |
233 UNREACHABLE(); | 228 UNREACHABLE(); |
234 return 0; | 229 return 0; |
235 #endif | 230 #endif |
236 } | 231 } |
237 | 232 |
238 | 233 |
239 intptr_t DeoptContext::GetSourcePc() const { | 234 intptr_t DeoptContext::GetSourcePc() const { |
240 #if !defined(TARGET_ARCH_DBC) | 235 #if !defined(TARGET_ARCH_DBC) |
241 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; | 236 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; |
242 #else | 237 #else |
243 return source_frame_[num_args_ + kDartFrameFixedSize + | 238 return source_frame_[num_args_ + kDartFrameFixedSize + |
244 kSavedCallerPcSlotFromFp]; | 239 kSavedCallerPcSlotFromFp]; |
245 #endif | 240 #endif |
246 } | 241 } |
247 | 242 |
248 | 243 |
249 intptr_t DeoptContext::GetCallerFp() const { | 244 intptr_t DeoptContext::GetCallerFp() const { |
250 return caller_fp_; | 245 return caller_fp_; |
251 } | 246 } |
252 | 247 |
253 | 248 |
254 void DeoptContext::SetCallerFp(intptr_t caller_fp) { | 249 void DeoptContext::SetCallerFp(intptr_t caller_fp) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 // objects until the frame is fully reconstructed and it is safe to perform | 307 // objects until the frame is fully reconstructed and it is safe to perform |
313 // GC. | 308 // GC. |
314 // Arguments (class of the instance to allocate and field-value pairs) are | 309 // Arguments (class of the instance to allocate and field-value pairs) are |
315 // described as part of the expression stack for the bottom-most deoptimized | 310 // described as part of the expression stack for the bottom-most deoptimized |
316 // frame. They will be used during materialization and removed from the stack | 311 // frame. They will be used during materialization and removed from the stack |
317 // right before control switches to the unoptimized code. | 312 // right before control switches to the unoptimized code. |
318 const intptr_t num_materializations = | 313 const intptr_t num_materializations = |
319 DeoptInfo::NumMaterializations(deopt_instructions); | 314 DeoptInfo::NumMaterializations(deopt_instructions); |
320 PrepareForDeferredMaterialization(num_materializations); | 315 PrepareForDeferredMaterialization(num_materializations); |
321 for (intptr_t from_index = 0, to_index = kDartFrameFixedSize; | 316 for (intptr_t from_index = 0, to_index = kDartFrameFixedSize; |
322 from_index < num_materializations; | 317 from_index < num_materializations; from_index++) { |
323 from_index++) { | |
324 const intptr_t field_count = | 318 const intptr_t field_count = |
325 DeoptInstr::GetFieldCount(deopt_instructions[from_index]); | 319 DeoptInstr::GetFieldCount(deopt_instructions[from_index]); |
326 intptr_t* args = GetDestFrameAddressAt(to_index); | 320 intptr_t* args = GetDestFrameAddressAt(to_index); |
327 DeferredObject* obj = new DeferredObject(field_count, args); | 321 DeferredObject* obj = new DeferredObject(field_count, args); |
328 SetDeferredObjectAt(from_index, obj); | 322 SetDeferredObjectAt(from_index, obj); |
329 to_index += obj->ArgumentCount(); | 323 to_index += obj->ArgumentCount(); |
330 } | 324 } |
331 | 325 |
332 // Populate stack frames. | 326 // Populate stack frames. |
333 for (intptr_t to_index = frame_size - 1, from_index = len - 1; | 327 for (intptr_t to_index = frame_size - 1, from_index = len - 1; to_index >= 0; |
334 to_index >= 0; | |
335 to_index--, from_index--) { | 328 to_index--, from_index--) { |
336 intptr_t* to_addr = GetDestFrameAddressAt(to_index); | 329 intptr_t* to_addr = GetDestFrameAddressAt(to_index); |
337 DeoptInstr* instr = deopt_instructions[from_index]; | 330 DeoptInstr* instr = deopt_instructions[from_index]; |
338 if (!objects_only || IsObjectInstruction(instr->kind())) { | 331 if (!objects_only || IsObjectInstruction(instr->kind())) { |
339 instr->Execute(this, to_addr); | 332 instr->Execute(this, to_addr); |
340 } else { | 333 } else { |
341 *reinterpret_cast<RawObject**>(to_addr) = Object::null(); | 334 *reinterpret_cast<RawObject**>(to_addr) = Object::null(); |
342 } | 335 } |
343 } | 336 } |
344 | 337 |
345 if (FLAG_trace_deoptimization_verbose) { | 338 if (FLAG_trace_deoptimization_verbose) { |
346 for (intptr_t i = 0; i < frame_size; i++) { | 339 for (intptr_t i = 0; i < frame_size; i++) { |
347 intptr_t* to_addr = GetDestFrameAddressAt(i); | 340 intptr_t* to_addr = GetDestFrameAddressAt(i); |
348 THR_Print("*%" Pd ". [%p] 0x%" Px " [%s]\n", | 341 THR_Print("*%" Pd ". [%p] 0x%" Px " [%s]\n", i, to_addr, *to_addr, |
349 i, | |
350 to_addr, | |
351 *to_addr, | |
352 deopt_instructions[i + (len - frame_size)]->ToCString()); | 342 deopt_instructions[i + (len - frame_size)]->ToCString()); |
353 } | 343 } |
354 } | 344 } |
355 } | 345 } |
356 | 346 |
357 | 347 |
358 static void FillDeferredSlots(DeoptContext* deopt_context, | 348 static void FillDeferredSlots(DeoptContext* deopt_context, |
359 DeferredSlot** slot_list) { | 349 DeferredSlot** slot_list) { |
360 DeferredSlot* slot = *slot_list; | 350 DeferredSlot* slot = *slot_list; |
361 *slot_list = NULL; | 351 *slot_list = NULL; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 ASSERT(top_frame != NULL); | 385 ASSERT(top_frame != NULL); |
396 const Code& code = Code::Handle(top_frame->LookupDartCode()); | 386 const Code& code = Code::Handle(top_frame->LookupDartCode()); |
397 const Function& top_function = Function::Handle(code.function()); | 387 const Function& top_function = Function::Handle(code.function()); |
398 const Script& script = Script::Handle(top_function.script()); | 388 const Script& script = Script::Handle(top_function.script()); |
399 const TokenPosition token_pos = code.GetTokenIndexOfPC(top_frame->pc()); | 389 const TokenPosition token_pos = code.GetTokenIndexOfPC(top_frame->pc()); |
400 intptr_t line, column; | 390 intptr_t line, column; |
401 script.GetTokenLocation(token_pos, &line, &column); | 391 script.GetTokenLocation(token_pos, &line, &column); |
402 String& line_string = String::Handle(script.GetLine(line)); | 392 String& line_string = String::Handle(script.GetLine(line)); |
403 THR_Print(" Function: %s\n", top_function.ToFullyQualifiedCString()); | 393 THR_Print(" Function: %s\n", top_function.ToFullyQualifiedCString()); |
404 char line_buffer[80]; | 394 char line_buffer[80]; |
405 OS::SNPrint(line_buffer, sizeof(line_buffer), " Line %" Pd ": '%s'", | 395 OS::SNPrint(line_buffer, sizeof(line_buffer), " Line %" Pd ": '%s'", line, |
406 line, line_string.ToCString()); | 396 line_string.ToCString()); |
407 THR_Print("%s\n", line_buffer); | 397 THR_Print("%s\n", line_buffer); |
408 THR_Print(" Deopt args: %" Pd "\n", deopt_arg_count); | 398 THR_Print(" Deopt args: %" Pd "\n", deopt_arg_count); |
409 } | 399 } |
410 | 400 |
411 return deopt_arg_count; | 401 return deopt_arg_count; |
412 } | 402 } |
413 | 403 |
414 | 404 |
415 RawArray* DeoptContext::DestFrameAsArray() { | 405 RawArray* DeoptContext::DestFrameAsArray() { |
416 ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_); | 406 ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_); |
417 const Array& dest_array = | 407 const Array& dest_array = Array::Handle(zone(), Array::New(dest_frame_size_)); |
418 Array::Handle(zone(), Array::New(dest_frame_size_)); | |
419 PassiveObject& obj = PassiveObject::Handle(zone()); | 408 PassiveObject& obj = PassiveObject::Handle(zone()); |
420 for (intptr_t i = 0; i < dest_frame_size_; i++) { | 409 for (intptr_t i = 0; i < dest_frame_size_; i++) { |
421 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); | 410 obj = reinterpret_cast<RawObject*>(dest_frame_[i]); |
422 dest_array.SetAt(i, obj); | 411 dest_array.SetAt(i, obj); |
423 } | 412 } |
424 return dest_array.raw(); | 413 return dest_array.raw(); |
425 } | 414 } |
426 | 415 |
427 | 416 |
428 // Deoptimization instruction creating return address using function and | 417 // Deoptimization instruction creating return address using function and |
429 // deopt-id stored at 'object_table_index'. | 418 // deopt-id stored at 'object_table_index'. |
430 class DeoptRetAddressInstr : public DeoptInstr { | 419 class DeoptRetAddressInstr : public DeoptInstr { |
431 public: | 420 public: |
432 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) | 421 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) |
433 : object_table_index_(object_table_index), deopt_id_(deopt_id) { | 422 : object_table_index_(object_table_index), deopt_id_(deopt_id) { |
434 ASSERT(object_table_index >= 0); | 423 ASSERT(object_table_index >= 0); |
435 ASSERT(deopt_id >= 0); | 424 ASSERT(deopt_id >= 0); |
436 } | 425 } |
437 | 426 |
438 explicit DeoptRetAddressInstr(intptr_t source_index) | 427 explicit DeoptRetAddressInstr(intptr_t source_index) |
439 : object_table_index_(ObjectTableIndex::decode(source_index)), | 428 : object_table_index_(ObjectTableIndex::decode(source_index)), |
440 deopt_id_(DeoptId::decode(source_index)) { | 429 deopt_id_(DeoptId::decode(source_index)) {} |
441 } | |
442 | 430 |
443 virtual intptr_t source_index() const { | 431 virtual intptr_t source_index() const { |
444 return ObjectTableIndex::encode(object_table_index_) | | 432 return ObjectTableIndex::encode(object_table_index_) | |
445 DeoptId::encode(deopt_id_); | 433 DeoptId::encode(deopt_id_); |
446 } | 434 } |
447 | 435 |
448 virtual DeoptInstr::Kind kind() const { return kRetAddress; } | 436 virtual DeoptInstr::Kind kind() const { return kRetAddress; } |
449 | 437 |
450 virtual const char* ArgumentsToCString() const { | 438 virtual const char* ArgumentsToCString() const { |
451 return Thread::Current()->zone()->PrintToString( | 439 return Thread::Current()->zone()->PrintToString( |
452 "%" Pd ", %" Pd "", object_table_index_, deopt_id_); | 440 "%" Pd ", %" Pd "", object_table_index_, deopt_id_); |
453 } | 441 } |
454 | 442 |
455 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 443 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
456 *dest_addr = Smi::RawValue(0); | 444 *dest_addr = Smi::RawValue(0); |
457 deopt_context->DeferRetAddrMaterialization( | 445 deopt_context->DeferRetAddrMaterialization(object_table_index_, deopt_id_, |
458 object_table_index_, deopt_id_, dest_addr); | 446 dest_addr); |
459 } | 447 } |
460 | 448 |
461 intptr_t object_table_index() const { return object_table_index_; } | 449 intptr_t object_table_index() const { return object_table_index_; } |
462 intptr_t deopt_id() const { return deopt_id_; } | 450 intptr_t deopt_id() const { return deopt_id_; } |
463 | 451 |
464 private: | 452 private: |
465 static const intptr_t kFieldWidth = kBitsPerWord / 2; | 453 static const intptr_t kFieldWidth = kBitsPerWord / 2; |
466 class ObjectTableIndex : | 454 class ObjectTableIndex : public BitField<intptr_t, intptr_t, 0, kFieldWidth> { |
467 public BitField<intptr_t, intptr_t, 0, kFieldWidth> { }; | 455 }; |
468 class DeoptId : | 456 class DeoptId |
469 public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> { }; | 457 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; |
470 | 458 |
471 const intptr_t object_table_index_; | 459 const intptr_t object_table_index_; |
472 const intptr_t deopt_id_; | 460 const intptr_t deopt_id_; |
473 | 461 |
474 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddressInstr); | 462 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddressInstr); |
475 }; | 463 }; |
476 | 464 |
477 | 465 |
478 // Deoptimization instruction moving a constant stored at 'object_table_index'. | 466 // Deoptimization instruction moving a constant stored at 'object_table_index'. |
479 class DeoptConstantInstr : public DeoptInstr { | 467 class DeoptConstantInstr : public DeoptInstr { |
480 public: | 468 public: |
481 explicit DeoptConstantInstr(intptr_t object_table_index) | 469 explicit DeoptConstantInstr(intptr_t object_table_index) |
482 : object_table_index_(object_table_index) { | 470 : object_table_index_(object_table_index) { |
483 ASSERT(object_table_index >= 0); | 471 ASSERT(object_table_index >= 0); |
484 } | 472 } |
485 | 473 |
486 virtual intptr_t source_index() const { return object_table_index_; } | 474 virtual intptr_t source_index() const { return object_table_index_; } |
487 virtual DeoptInstr::Kind kind() const { return kConstant; } | 475 virtual DeoptInstr::Kind kind() const { return kConstant; } |
488 | 476 |
489 virtual const char* ArgumentsToCString() const { | 477 virtual const char* ArgumentsToCString() const { |
490 return Thread::Current()->zone()->PrintToString( | 478 return Thread::Current()->zone()->PrintToString("%" Pd "", |
491 "%" Pd "", object_table_index_); | 479 object_table_index_); |
492 } | 480 } |
493 | 481 |
494 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 482 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
495 const PassiveObject& obj = PassiveObject::Handle( | 483 const PassiveObject& obj = PassiveObject::Handle( |
496 deopt_context->zone(), deopt_context->ObjectAt(object_table_index_)); | 484 deopt_context->zone(), deopt_context->ObjectAt(object_table_index_)); |
497 *reinterpret_cast<RawObject**>(dest_addr) = obj.raw(); | 485 *reinterpret_cast<RawObject**>(dest_addr) = obj.raw(); |
498 } | 486 } |
499 | 487 |
500 private: | 488 private: |
501 const intptr_t object_table_index_; | 489 const intptr_t object_table_index_; |
502 | 490 |
503 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | 491 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); |
504 }; | 492 }; |
505 | 493 |
506 | 494 |
507 // Deoptimization instruction moving value from optimized frame at | 495 // Deoptimization instruction moving value from optimized frame at |
508 // 'source_index' to specified slots in the unoptimized frame. | 496 // 'source_index' to specified slots in the unoptimized frame. |
509 // 'source_index' represents the slot index of the frame (0 being | 497 // 'source_index' represents the slot index of the frame (0 being |
510 // first argument) and accounts for saved return address, frame | 498 // first argument) and accounts for saved return address, frame |
511 // pointer, pool pointer and pc marker. | 499 // pointer, pool pointer and pc marker. |
512 // Deoptimization instruction moving a CPU register. | 500 // Deoptimization instruction moving a CPU register. |
513 class DeoptWordInstr: public DeoptInstr { | 501 class DeoptWordInstr : public DeoptInstr { |
514 public: | 502 public: |
515 explicit DeoptWordInstr(intptr_t source_index) | 503 explicit DeoptWordInstr(intptr_t source_index) : source_(source_index) {} |
516 : source_(source_index) {} | |
517 | 504 |
518 explicit DeoptWordInstr(const CpuRegisterSource& source) | 505 explicit DeoptWordInstr(const CpuRegisterSource& source) : source_(source) {} |
519 : source_(source) {} | |
520 | 506 |
521 virtual intptr_t source_index() const { return source_.source_index(); } | 507 virtual intptr_t source_index() const { return source_.source_index(); } |
522 virtual DeoptInstr::Kind kind() const { return kWord; } | 508 virtual DeoptInstr::Kind kind() const { return kWord; } |
523 | 509 |
524 virtual const char* ArgumentsToCString() const { | 510 virtual const char* ArgumentsToCString() const { return source_.ToCString(); } |
525 return source_.ToCString(); | |
526 } | |
527 | 511 |
528 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 512 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
529 *dest_addr = source_.Value<intptr_t>(deopt_context); | 513 *dest_addr = source_.Value<intptr_t>(deopt_context); |
530 } | 514 } |
531 | 515 |
532 private: | 516 private: |
533 const CpuRegisterSource source_; | 517 const CpuRegisterSource source_; |
534 | 518 |
535 DISALLOW_COPY_AND_ASSIGN(DeoptWordInstr); | 519 DISALLOW_COPY_AND_ASSIGN(DeoptWordInstr); |
536 }; | 520 }; |
537 | 521 |
538 | 522 |
539 class DeoptIntegerInstrBase: public DeoptInstr { | 523 class DeoptIntegerInstrBase : public DeoptInstr { |
540 public: | 524 public: |
541 DeoptIntegerInstrBase() { } | 525 DeoptIntegerInstrBase() {} |
542 | 526 |
543 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 527 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
544 const int64_t value = GetValue(deopt_context); | 528 const int64_t value = GetValue(deopt_context); |
545 if (Smi::IsValid(value)) { | 529 if (Smi::IsValid(value)) { |
546 *dest_addr = Smi::RawValue(static_cast<intptr_t>(value)); | 530 *dest_addr = Smi::RawValue(static_cast<intptr_t>(value)); |
547 } else { | 531 } else { |
548 *dest_addr = Smi::RawValue(0); | 532 *dest_addr = Smi::RawValue(0); |
549 deopt_context->DeferMintMaterialization( | 533 deopt_context->DeferMintMaterialization( |
550 value, reinterpret_cast<RawMint**>(dest_addr)); | 534 value, reinterpret_cast<RawMint**>(dest_addr)); |
551 } | 535 } |
552 } | 536 } |
553 | 537 |
554 virtual int64_t GetValue(DeoptContext* deopt_context) = 0; | 538 virtual int64_t GetValue(DeoptContext* deopt_context) = 0; |
555 | 539 |
556 private: | 540 private: |
557 DISALLOW_COPY_AND_ASSIGN(DeoptIntegerInstrBase); | 541 DISALLOW_COPY_AND_ASSIGN(DeoptIntegerInstrBase); |
558 }; | 542 }; |
559 | 543 |
560 | 544 |
561 class DeoptMintPairInstr: public DeoptIntegerInstrBase { | 545 class DeoptMintPairInstr : public DeoptIntegerInstrBase { |
562 public: | 546 public: |
563 explicit DeoptMintPairInstr(intptr_t source_index) | 547 explicit DeoptMintPairInstr(intptr_t source_index) |
564 : DeoptIntegerInstrBase(), | 548 : DeoptIntegerInstrBase(), |
565 lo_(LoRegister::decode(source_index)), | 549 lo_(LoRegister::decode(source_index)), |
566 hi_(HiRegister::decode(source_index)) { | 550 hi_(HiRegister::decode(source_index)) {} |
567 } | |
568 | 551 |
569 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) | 552 DeoptMintPairInstr(const CpuRegisterSource& lo, const CpuRegisterSource& hi) |
570 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} | 553 : DeoptIntegerInstrBase(), lo_(lo), hi_(hi) {} |
571 | 554 |
572 virtual intptr_t source_index() const { | 555 virtual intptr_t source_index() const { |
573 return LoRegister::encode(lo_.source_index()) | | 556 return LoRegister::encode(lo_.source_index()) | |
574 HiRegister::encode(hi_.source_index()); | 557 HiRegister::encode(hi_.source_index()); |
575 } | 558 } |
576 virtual DeoptInstr::Kind kind() const { return kMintPair; } | 559 virtual DeoptInstr::Kind kind() const { return kMintPair; } |
577 | 560 |
578 virtual const char* ArgumentsToCString() const { | 561 virtual const char* ArgumentsToCString() const { |
579 return Thread::Current()->zone()->PrintToString( | 562 return Thread::Current()->zone()->PrintToString("%s,%s", lo_.ToCString(), |
580 "%s,%s", | 563 hi_.ToCString()); |
581 lo_.ToCString(), | |
582 hi_.ToCString()); | |
583 } | 564 } |
584 | 565 |
585 virtual int64_t GetValue(DeoptContext* deopt_context) { | 566 virtual int64_t GetValue(DeoptContext* deopt_context) { |
586 return Utils::LowHighTo64Bits( | 567 return Utils::LowHighTo64Bits(lo_.Value<uint32_t>(deopt_context), |
587 lo_.Value<uint32_t>(deopt_context), hi_.Value<int32_t>(deopt_context)); | 568 hi_.Value<int32_t>(deopt_context)); |
588 } | 569 } |
589 | 570 |
590 private: | 571 private: |
591 static const intptr_t kFieldWidth = kBitsPerWord / 2; | 572 static const intptr_t kFieldWidth = kBitsPerWord / 2; |
592 class LoRegister : public BitField<intptr_t, intptr_t, 0, kFieldWidth> { }; | 573 class LoRegister : public BitField<intptr_t, intptr_t, 0, kFieldWidth> {}; |
593 class HiRegister : | 574 class HiRegister |
594 public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> { }; | 575 : public BitField<intptr_t, intptr_t, kFieldWidth, kFieldWidth> {}; |
595 | 576 |
596 const CpuRegisterSource lo_; | 577 const CpuRegisterSource lo_; |
597 const CpuRegisterSource hi_; | 578 const CpuRegisterSource hi_; |
598 | 579 |
599 DISALLOW_COPY_AND_ASSIGN(DeoptMintPairInstr); | 580 DISALLOW_COPY_AND_ASSIGN(DeoptMintPairInstr); |
600 }; | 581 }; |
601 | 582 |
602 | 583 |
603 template<DeoptInstr::Kind K, typename T> | 584 template <DeoptInstr::Kind K, typename T> |
604 class DeoptIntInstr : public DeoptIntegerInstrBase { | 585 class DeoptIntInstr : public DeoptIntegerInstrBase { |
605 public: | 586 public: |
606 explicit DeoptIntInstr(intptr_t source_index) | 587 explicit DeoptIntInstr(intptr_t source_index) |
607 : DeoptIntegerInstrBase(), source_(source_index) { | 588 : DeoptIntegerInstrBase(), source_(source_index) {} |
608 } | |
609 | 589 |
610 explicit DeoptIntInstr(const CpuRegisterSource& source) | 590 explicit DeoptIntInstr(const CpuRegisterSource& source) |
611 : DeoptIntegerInstrBase(), source_(source) { | 591 : DeoptIntegerInstrBase(), source_(source) {} |
612 } | |
613 | 592 |
614 virtual intptr_t source_index() const { return source_.source_index(); } | 593 virtual intptr_t source_index() const { return source_.source_index(); } |
615 virtual DeoptInstr::Kind kind() const { return K; } | 594 virtual DeoptInstr::Kind kind() const { return K; } |
616 | 595 |
617 virtual const char* ArgumentsToCString() const { | 596 virtual const char* ArgumentsToCString() const { return source_.ToCString(); } |
618 return source_.ToCString(); | |
619 } | |
620 | 597 |
621 virtual int64_t GetValue(DeoptContext* deopt_context) { | 598 virtual int64_t GetValue(DeoptContext* deopt_context) { |
622 return static_cast<int64_t>(source_.Value<T>(deopt_context)); | 599 return static_cast<int64_t>(source_.Value<T>(deopt_context)); |
623 } | 600 } |
624 | 601 |
625 private: | 602 private: |
626 const CpuRegisterSource source_; | 603 const CpuRegisterSource source_; |
627 | 604 |
628 DISALLOW_COPY_AND_ASSIGN(DeoptIntInstr); | 605 DISALLOW_COPY_AND_ASSIGN(DeoptIntInstr); |
629 }; | 606 }; |
630 | 607 |
631 | 608 |
632 typedef DeoptIntInstr<DeoptInstr::kUint32, uint32_t> DeoptUint32Instr; | 609 typedef DeoptIntInstr<DeoptInstr::kUint32, uint32_t> DeoptUint32Instr; |
633 typedef DeoptIntInstr<DeoptInstr::kInt32, int32_t> DeoptInt32Instr; | 610 typedef DeoptIntInstr<DeoptInstr::kInt32, int32_t> DeoptInt32Instr; |
634 typedef DeoptIntInstr<DeoptInstr::kMint, int64_t> DeoptMintInstr; | 611 typedef DeoptIntInstr<DeoptInstr::kMint, int64_t> DeoptMintInstr; |
635 | 612 |
636 | 613 |
637 template<DeoptInstr::Kind K, | 614 template <DeoptInstr::Kind K, typename Type, typename RawObjectType> |
638 typename Type, | 615 class DeoptFpuInstr : public DeoptInstr { |
639 typename RawObjectType> | |
640 class DeoptFpuInstr: public DeoptInstr { | |
641 public: | 616 public: |
642 explicit DeoptFpuInstr(intptr_t source_index) | 617 explicit DeoptFpuInstr(intptr_t source_index) : source_(source_index) {} |
643 : source_(source_index) {} | |
644 | 618 |
645 explicit DeoptFpuInstr(const FpuRegisterSource& source) | 619 explicit DeoptFpuInstr(const FpuRegisterSource& source) : source_(source) {} |
646 : source_(source) {} | |
647 | 620 |
648 virtual intptr_t source_index() const { return source_.source_index(); } | 621 virtual intptr_t source_index() const { return source_.source_index(); } |
649 virtual DeoptInstr::Kind kind() const { return K; } | 622 virtual DeoptInstr::Kind kind() const { return K; } |
650 | 623 |
651 virtual const char* ArgumentsToCString() const { | 624 virtual const char* ArgumentsToCString() const { return source_.ToCString(); } |
652 return source_.ToCString(); | |
653 } | |
654 | 625 |
655 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 626 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
656 *dest_addr = Smi::RawValue(0); | 627 *dest_addr = Smi::RawValue(0); |
657 deopt_context->DeferMaterialization( | 628 deopt_context->DeferMaterialization( |
658 source_.Value<Type>(deopt_context), | 629 source_.Value<Type>(deopt_context), |
659 reinterpret_cast<RawObjectType**>(dest_addr)); | 630 reinterpret_cast<RawObjectType**>(dest_addr)); |
660 } | 631 } |
661 | 632 |
662 private: | 633 private: |
663 const FpuRegisterSource source_; | 634 const FpuRegisterSource source_; |
(...skipping 19 matching lines...) Expand all Loading... |
683 public: | 654 public: |
684 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | 655 explicit DeoptPcMarkerInstr(intptr_t object_table_index) |
685 : object_table_index_(object_table_index) { | 656 : object_table_index_(object_table_index) { |
686 ASSERT(object_table_index >= 0); | 657 ASSERT(object_table_index >= 0); |
687 } | 658 } |
688 | 659 |
689 virtual intptr_t source_index() const { return object_table_index_; } | 660 virtual intptr_t source_index() const { return object_table_index_; } |
690 virtual DeoptInstr::Kind kind() const { return kPcMarker; } | 661 virtual DeoptInstr::Kind kind() const { return kPcMarker; } |
691 | 662 |
692 virtual const char* ArgumentsToCString() const { | 663 virtual const char* ArgumentsToCString() const { |
693 return Thread::Current()->zone()->PrintToString( | 664 return Thread::Current()->zone()->PrintToString("%" Pd "", |
694 "%" Pd "", object_table_index_); | 665 object_table_index_); |
695 } | 666 } |
696 | 667 |
697 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 668 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
698 Function& function = Function::Handle(deopt_context->zone()); | 669 Function& function = Function::Handle(deopt_context->zone()); |
699 function ^= deopt_context->ObjectAt(object_table_index_); | 670 function ^= deopt_context->ObjectAt(object_table_index_); |
700 if (function.IsNull()) { | 671 if (function.IsNull()) { |
701 *reinterpret_cast<RawObject**>(dest_addr) = deopt_context->is_lazy_deopt() | 672 *reinterpret_cast<RawObject**>(dest_addr) = |
702 ? StubCode::DeoptimizeLazyFromReturn_entry()->code() | 673 deopt_context->is_lazy_deopt() |
703 : StubCode::Deoptimize_entry()->code(); | 674 ? StubCode::DeoptimizeLazyFromReturn_entry()->code() |
| 675 : StubCode::Deoptimize_entry()->code(); |
704 return; | 676 return; |
705 } | 677 } |
706 | 678 |
707 // We don't always have the Code object for the frame's corresponding | 679 // We don't always have the Code object for the frame's corresponding |
708 // unoptimized code as it may have been collected. Use a stub as the pc | 680 // unoptimized code as it may have been collected. Use a stub as the pc |
709 // marker until we can recreate that Code object during deferred | 681 // marker until we can recreate that Code object during deferred |
710 // materialization to maintain the invariant that Dart frames always have | 682 // materialization to maintain the invariant that Dart frames always have |
711 // a pc marker. | 683 // a pc marker. |
712 *reinterpret_cast<RawObject**>(dest_addr) = | 684 *reinterpret_cast<RawObject**>(dest_addr) = |
713 StubCode::FrameAwaitingMaterialization_entry()->code(); | 685 StubCode::FrameAwaitingMaterialization_entry()->code(); |
(...skipping 13 matching lines...) Expand all Loading... |
727 public: | 699 public: |
728 explicit DeoptPpInstr(intptr_t object_table_index) | 700 explicit DeoptPpInstr(intptr_t object_table_index) |
729 : object_table_index_(object_table_index) { | 701 : object_table_index_(object_table_index) { |
730 ASSERT(object_table_index >= 0); | 702 ASSERT(object_table_index >= 0); |
731 } | 703 } |
732 | 704 |
733 virtual intptr_t source_index() const { return object_table_index_; } | 705 virtual intptr_t source_index() const { return object_table_index_; } |
734 virtual DeoptInstr::Kind kind() const { return kPp; } | 706 virtual DeoptInstr::Kind kind() const { return kPp; } |
735 | 707 |
736 virtual const char* ArgumentsToCString() const { | 708 virtual const char* ArgumentsToCString() const { |
737 return Thread::Current()->zone()->PrintToString( | 709 return Thread::Current()->zone()->PrintToString("%" Pd "", |
738 "%" Pd "", object_table_index_); | 710 object_table_index_); |
739 } | 711 } |
740 | 712 |
741 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 713 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
742 *dest_addr = Smi::RawValue(0); | 714 *dest_addr = Smi::RawValue(0); |
743 deopt_context->DeferPpMaterialization(object_table_index_, | 715 deopt_context->DeferPpMaterialization( |
744 reinterpret_cast<RawObject**>(dest_addr)); | 716 object_table_index_, reinterpret_cast<RawObject**>(dest_addr)); |
745 } | 717 } |
746 | 718 |
747 private: | 719 private: |
748 intptr_t object_table_index_; | 720 intptr_t object_table_index_; |
749 | 721 |
750 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); | 722 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); |
751 }; | 723 }; |
752 | 724 |
753 | 725 |
754 // Deoptimization instruction copying the caller saved FP from optimized frame. | 726 // Deoptimization instruction copying the caller saved FP from optimized frame. |
755 class DeoptCallerFpInstr : public DeoptInstr { | 727 class DeoptCallerFpInstr : public DeoptInstr { |
756 public: | 728 public: |
757 DeoptCallerFpInstr() {} | 729 DeoptCallerFpInstr() {} |
758 | 730 |
759 virtual intptr_t source_index() const { return 0; } | 731 virtual intptr_t source_index() const { return 0; } |
760 virtual DeoptInstr::Kind kind() const { return kCallerFp; } | 732 virtual DeoptInstr::Kind kind() const { return kCallerFp; } |
761 | 733 |
762 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 734 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
763 *dest_addr = deopt_context->GetCallerFp(); | 735 *dest_addr = deopt_context->GetCallerFp(); |
764 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>( | 736 deopt_context->SetCallerFp( |
765 dest_addr - kSavedCallerFpSlotFromFp)); | 737 reinterpret_cast<intptr_t>(dest_addr - kSavedCallerFpSlotFromFp)); |
766 } | 738 } |
767 | 739 |
768 private: | 740 private: |
769 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | 741 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); |
770 }; | 742 }; |
771 | 743 |
772 | 744 |
773 // Deoptimization instruction copying the caller saved PP from optimized frame. | 745 // Deoptimization instruction copying the caller saved PP from optimized frame. |
774 class DeoptCallerPpInstr : public DeoptInstr { | 746 class DeoptCallerPpInstr : public DeoptInstr { |
775 public: | 747 public: |
(...skipping 26 matching lines...) Expand all Loading... |
802 | 774 |
803 private: | 775 private: |
804 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 776 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
805 }; | 777 }; |
806 | 778 |
807 | 779 |
808 // Write reference to a materialized object with the given index into the | 780 // Write reference to a materialized object with the given index into the |
809 // stack slot. | 781 // stack slot. |
810 class DeoptMaterializedObjectRefInstr : public DeoptInstr { | 782 class DeoptMaterializedObjectRefInstr : public DeoptInstr { |
811 public: | 783 public: |
812 explicit DeoptMaterializedObjectRefInstr(intptr_t index) | 784 explicit DeoptMaterializedObjectRefInstr(intptr_t index) : index_(index) { |
813 : index_(index) { | |
814 ASSERT(index >= 0); | 785 ASSERT(index >= 0); |
815 } | 786 } |
816 | 787 |
817 virtual intptr_t source_index() const { return index_; } | 788 virtual intptr_t source_index() const { return index_; } |
818 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } | 789 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } |
819 | 790 |
820 virtual const char* ArgumentsToCString() const { | 791 virtual const char* ArgumentsToCString() const { |
821 return Thread::Current()->zone()->PrintToString( | 792 return Thread::Current()->zone()->PrintToString("#%" Pd "", index_); |
822 "#%" Pd "", index_); | |
823 } | 793 } |
824 | 794 |
825 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 795 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
826 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | 796 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
827 deopt_context->DeferMaterializedObjectRef( | 797 deopt_context->DeferMaterializedObjectRef(index_, dest_addr); |
828 index_, dest_addr); | |
829 } | 798 } |
830 | 799 |
831 private: | 800 private: |
832 intptr_t index_; | 801 intptr_t index_; |
833 | 802 |
834 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); | 803 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); |
835 }; | 804 }; |
836 | 805 |
837 | 806 |
838 // Materialize object with the given number of fields. | 807 // Materialize object with the given number of fields. |
839 // Arguments for materialization (class and field-value pairs) are pushed | 808 // Arguments for materialization (class and field-value pairs) are pushed |
840 // to the expression stack of the bottom-most frame. | 809 // to the expression stack of the bottom-most frame. |
841 class DeoptMaterializeObjectInstr : public DeoptInstr { | 810 class DeoptMaterializeObjectInstr : public DeoptInstr { |
842 public: | 811 public: |
843 explicit DeoptMaterializeObjectInstr(intptr_t field_count) | 812 explicit DeoptMaterializeObjectInstr(intptr_t field_count) |
844 : field_count_(field_count) { | 813 : field_count_(field_count) { |
845 ASSERT(field_count >= 0); | 814 ASSERT(field_count >= 0); |
846 } | 815 } |
847 | 816 |
848 virtual intptr_t source_index() const { return field_count_; } | 817 virtual intptr_t source_index() const { return field_count_; } |
849 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } | 818 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } |
850 | 819 |
851 virtual const char* ArgumentsToCString() const { | 820 virtual const char* ArgumentsToCString() const { |
852 return Thread::Current()->zone()->PrintToString( | 821 return Thread::Current()->zone()->PrintToString("%" Pd "", field_count_); |
853 "%" Pd "", field_count_); | |
854 } | 822 } |
855 | 823 |
856 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 824 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
857 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. | 825 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. |
858 UNREACHABLE(); | 826 UNREACHABLE(); |
859 } | 827 } |
860 | 828 |
861 private: | 829 private: |
862 intptr_t field_count_; | 830 intptr_t field_count_; |
863 | 831 |
864 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); | 832 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); |
865 }; | 833 }; |
866 | 834 |
867 | 835 |
868 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, | 836 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, |
869 const ObjectPool& object_table, | 837 const ObjectPool& object_table, |
870 Code* code) { | 838 Code* code) { |
871 ASSERT(instr->kind() == kRetAddress); | 839 ASSERT(instr->kind() == kRetAddress); |
872 DeoptRetAddressInstr* ret_address_instr = | 840 DeoptRetAddressInstr* ret_address_instr = |
873 static_cast<DeoptRetAddressInstr*>(instr); | 841 static_cast<DeoptRetAddressInstr*>(instr); |
874 // The following assert may trigger when displaying a backtrace | 842 // The following assert may trigger when displaying a backtrace |
875 // from the simulator. | 843 // from the simulator. |
876 ASSERT(Thread::IsDeoptAfter(ret_address_instr->deopt_id())); | 844 ASSERT(Thread::IsDeoptAfter(ret_address_instr->deopt_id())); |
877 ASSERT(!object_table.IsNull()); | 845 ASSERT(!object_table.IsNull()); |
878 Thread* thread = Thread::Current(); | 846 Thread* thread = Thread::Current(); |
879 Zone* zone = thread->zone(); | 847 Zone* zone = thread->zone(); |
880 Function& function = Function::Handle(zone); | 848 Function& function = Function::Handle(zone); |
881 function ^= object_table.ObjectAt(ret_address_instr->object_table_index()); | 849 function ^= object_table.ObjectAt(ret_address_instr->object_table_index()); |
882 ASSERT(code != NULL); | 850 ASSERT(code != NULL); |
883 const Error& error = Error::Handle(zone, | 851 const Error& error = |
884 Compiler::EnsureUnoptimizedCode(thread, function)); | 852 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); |
885 if (!error.IsNull()) { | 853 if (!error.IsNull()) { |
886 Exceptions::PropagateError(error); | 854 Exceptions::PropagateError(error); |
887 } | 855 } |
888 *code ^= function.unoptimized_code(); | 856 *code ^= function.unoptimized_code(); |
889 ASSERT(!code->IsNull()); | 857 ASSERT(!code->IsNull()); |
890 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), | 858 uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(), |
891 RawPcDescriptors::kDeopt); | 859 RawPcDescriptors::kDeopt); |
892 ASSERT(res != 0); | 860 ASSERT(res != 0); |
893 return res; | 861 return res; |
894 } | 862 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 } | 947 } |
980 UNREACHABLE(); | 948 UNREACHABLE(); |
981 return NULL; | 949 return NULL; |
982 } | 950 } |
983 | 951 |
984 | 952 |
985 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { | 953 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { |
986 public: | 954 public: |
987 // Construct the root node representing the implicit "shared" terminator | 955 // Construct the root node representing the implicit "shared" terminator |
988 // at the end of each deopt info. | 956 // at the end of each deopt info. |
989 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) { } | 957 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) {} |
990 | 958 |
991 // Construct a node representing a written instruction. | 959 // Construct a node representing a written instruction. |
992 TrieNode(DeoptInstr* instruction, intptr_t info_number) | 960 TrieNode(DeoptInstr* instruction, intptr_t info_number) |
993 : instruction_(instruction), info_number_(info_number), children_(4) { } | 961 : instruction_(instruction), info_number_(info_number), children_(4) {} |
994 | 962 |
995 intptr_t info_number() const { return info_number_; } | 963 intptr_t info_number() const { return info_number_; } |
996 | 964 |
997 void AddChild(TrieNode* child) { | 965 void AddChild(TrieNode* child) { |
998 if (child != NULL) children_.Add(child); | 966 if (child != NULL) children_.Add(child); |
999 } | 967 } |
1000 | 968 |
1001 TrieNode* FindChild(const DeoptInstr& instruction) { | 969 TrieNode* FindChild(const DeoptInstr& instruction) { |
1002 for (intptr_t i = 0; i < children_.length(); ++i) { | 970 for (intptr_t i = 0; i < children_.length(); ++i) { |
1003 TrieNode* child = children_[i]; | 971 TrieNode* child = children_[i]; |
1004 if (child->instruction_->Equals(instruction)) return child; | 972 if (child->instruction_->Equals(instruction)) return child; |
1005 } | 973 } |
1006 return NULL; | 974 return NULL; |
1007 } | 975 } |
1008 | 976 |
1009 private: | 977 private: |
1010 const DeoptInstr* instruction_; // Instruction that was written. | 978 const DeoptInstr* instruction_; // Instruction that was written. |
1011 const intptr_t info_number_; // Index of the deopt info it was written to. | 979 const intptr_t info_number_; // Index of the deopt info it was written to. |
1012 | 980 |
1013 GrowableArray<TrieNode*> children_; | 981 GrowableArray<TrieNode*> children_; |
1014 }; | 982 }; |
1015 | 983 |
1016 | 984 |
1017 DeoptInfoBuilder::DeoptInfoBuilder(Zone* zone, | 985 DeoptInfoBuilder::DeoptInfoBuilder(Zone* zone, |
1018 const intptr_t num_args, | 986 const intptr_t num_args, |
1019 Assembler* assembler) | 987 Assembler* assembler) |
1020 : zone_(zone), | 988 : zone_(zone), |
1021 instructions_(), | 989 instructions_(), |
1022 num_args_(num_args), | 990 num_args_(num_args), |
1023 assembler_(assembler), | 991 assembler_(assembler), |
1024 trie_root_(new(zone) TrieNode()), | 992 trie_root_(new (zone) TrieNode()), |
1025 current_info_number_(0), | 993 current_info_number_(0), |
1026 frame_start_(-1), | 994 frame_start_(-1), |
1027 materializations_() { | 995 materializations_() {} |
1028 } | |
1029 | 996 |
1030 | 997 |
1031 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { | 998 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { |
1032 return assembler_->object_pool_wrapper().FindObject(obj); | 999 return assembler_->object_pool_wrapper().FindObject(obj); |
1033 } | 1000 } |
1034 | 1001 |
1035 | 1002 |
1036 intptr_t DeoptInfoBuilder::CalculateStackIndex( | 1003 intptr_t DeoptInfoBuilder::CalculateStackIndex( |
1037 const Location& source_loc) const { | 1004 const Location& source_loc) const { |
1038 return source_loc.stack_index() < 0 ? | 1005 return source_loc.stack_index() < 0 |
1039 source_loc.stack_index() + num_args_ : | 1006 ? source_loc.stack_index() + num_args_ |
1040 source_loc.stack_index() + num_args_ + kDartFrameFixedSize; | 1007 : source_loc.stack_index() + num_args_ + kDartFrameFixedSize; |
1041 } | 1008 } |
1042 | 1009 |
1043 | 1010 |
1044 CpuRegisterSource DeoptInfoBuilder::ToCpuRegisterSource(const Location& loc) { | 1011 CpuRegisterSource DeoptInfoBuilder::ToCpuRegisterSource(const Location& loc) { |
1045 if (loc.IsRegister()) { | 1012 if (loc.IsRegister()) { |
1046 return CpuRegisterSource(CpuRegisterSource::kRegister, loc.reg()); | 1013 return CpuRegisterSource(CpuRegisterSource::kRegister, loc.reg()); |
1047 } else { | 1014 } else { |
1048 ASSERT(loc.IsStackSlot()); | 1015 ASSERT(loc.IsStackSlot()); |
1049 return CpuRegisterSource( | 1016 return CpuRegisterSource(CpuRegisterSource::kStackSlot, |
1050 CpuRegisterSource::kStackSlot, CalculateStackIndex(loc)); | 1017 CalculateStackIndex(loc)); |
1051 } | 1018 } |
1052 } | 1019 } |
1053 | 1020 |
1054 | 1021 |
1055 FpuRegisterSource DeoptInfoBuilder::ToFpuRegisterSource( | 1022 FpuRegisterSource DeoptInfoBuilder::ToFpuRegisterSource( |
1056 const Location& loc, | 1023 const Location& loc, |
1057 Location::Kind stack_slot_kind) { | 1024 Location::Kind stack_slot_kind) { |
1058 if (loc.IsFpuRegister()) { | 1025 if (loc.IsFpuRegister()) { |
1059 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); | 1026 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); |
1060 #if defined(TARGET_ARCH_DBC) | 1027 #if defined(TARGET_ARCH_DBC) |
1061 } else if (loc.IsRegister()) { | 1028 } else if (loc.IsRegister()) { |
1062 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg()); | 1029 return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg()); |
1063 #endif | 1030 #endif |
1064 } else { | 1031 } else { |
1065 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || | 1032 ASSERT((stack_slot_kind == Location::kQuadStackSlot) || |
1066 (stack_slot_kind == Location::kDoubleStackSlot)); | 1033 (stack_slot_kind == Location::kDoubleStackSlot)); |
1067 ASSERT(loc.kind() == stack_slot_kind); | 1034 ASSERT(loc.kind() == stack_slot_kind); |
1068 return FpuRegisterSource( | 1035 return FpuRegisterSource(FpuRegisterSource::kStackSlot, |
1069 FpuRegisterSource::kStackSlot, CalculateStackIndex(loc)); | 1036 CalculateStackIndex(loc)); |
1070 } | 1037 } |
1071 } | 1038 } |
1072 | 1039 |
1073 void DeoptInfoBuilder::AddReturnAddress(const Function& function, | 1040 void DeoptInfoBuilder::AddReturnAddress(const Function& function, |
1074 intptr_t deopt_id, | 1041 intptr_t deopt_id, |
1075 intptr_t dest_index) { | 1042 intptr_t dest_index) { |
1076 const intptr_t object_table_index = FindOrAddObjectInTable(function); | 1043 const intptr_t object_table_index = FindOrAddObjectInTable(function); |
1077 ASSERT(dest_index == FrameSize()); | 1044 ASSERT(dest_index == FrameSize()); |
1078 instructions_.Add( | 1045 instructions_.Add(new (zone()) |
1079 new(zone()) DeoptRetAddressInstr(object_table_index, deopt_id)); | 1046 DeoptRetAddressInstr(object_table_index, deopt_id)); |
1080 } | 1047 } |
1081 | 1048 |
1082 | 1049 |
1083 void DeoptInfoBuilder::AddPcMarker(const Function& function, | 1050 void DeoptInfoBuilder::AddPcMarker(const Function& function, |
1084 intptr_t dest_index) { | 1051 intptr_t dest_index) { |
1085 intptr_t object_table_index = FindOrAddObjectInTable(function); | 1052 intptr_t object_table_index = FindOrAddObjectInTable(function); |
1086 ASSERT(dest_index == FrameSize()); | 1053 ASSERT(dest_index == FrameSize()); |
1087 instructions_.Add(new(zone()) DeoptPcMarkerInstr(object_table_index)); | 1054 instructions_.Add(new (zone()) DeoptPcMarkerInstr(object_table_index)); |
1088 } | 1055 } |
1089 | 1056 |
1090 | 1057 |
1091 void DeoptInfoBuilder::AddPp(const Function& function, | 1058 void DeoptInfoBuilder::AddPp(const Function& function, intptr_t dest_index) { |
1092 intptr_t dest_index) { | |
1093 intptr_t object_table_index = FindOrAddObjectInTable(function); | 1059 intptr_t object_table_index = FindOrAddObjectInTable(function); |
1094 ASSERT(dest_index == FrameSize()); | 1060 ASSERT(dest_index == FrameSize()); |
1095 instructions_.Add(new(zone()) DeoptPpInstr(object_table_index)); | 1061 instructions_.Add(new (zone()) DeoptPpInstr(object_table_index)); |
1096 } | 1062 } |
1097 | 1063 |
1098 | 1064 |
1099 void DeoptInfoBuilder::AddCopy(Value* value, | 1065 void DeoptInfoBuilder::AddCopy(Value* value, |
1100 const Location& source_loc, | 1066 const Location& source_loc, |
1101 const intptr_t dest_index) { | 1067 const intptr_t dest_index) { |
1102 DeoptInstr* deopt_instr = NULL; | 1068 DeoptInstr* deopt_instr = NULL; |
1103 if (source_loc.IsConstant()) { | 1069 if (source_loc.IsConstant()) { |
1104 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); | 1070 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); |
1105 deopt_instr = new(zone()) DeoptConstantInstr(object_table_index); | 1071 deopt_instr = new (zone()) DeoptConstantInstr(object_table_index); |
1106 } else if (source_loc.IsInvalid() && | 1072 } else if (source_loc.IsInvalid() && |
1107 value->definition()->IsMaterializeObject()) { | 1073 value->definition()->IsMaterializeObject()) { |
1108 const intptr_t index = FindMaterialization( | 1074 const intptr_t index = |
1109 value->definition()->AsMaterializeObject()); | 1075 FindMaterialization(value->definition()->AsMaterializeObject()); |
1110 ASSERT(index >= 0); | 1076 ASSERT(index >= 0); |
1111 deopt_instr = new(zone()) DeoptMaterializedObjectRefInstr(index); | 1077 deopt_instr = new (zone()) DeoptMaterializedObjectRefInstr(index); |
1112 } else { | 1078 } else { |
1113 ASSERT(!source_loc.IsInvalid()); | 1079 ASSERT(!source_loc.IsInvalid()); |
1114 switch (value->definition()->representation()) { | 1080 switch (value->definition()->representation()) { |
1115 case kTagged: | 1081 case kTagged: |
1116 deopt_instr = new(zone()) DeoptWordInstr( | 1082 deopt_instr = |
1117 ToCpuRegisterSource(source_loc)); | 1083 new (zone()) DeoptWordInstr(ToCpuRegisterSource(source_loc)); |
1118 break; | 1084 break; |
1119 case kUnboxedMint: { | 1085 case kUnboxedMint: { |
1120 if (source_loc.IsPairLocation()) { | 1086 if (source_loc.IsPairLocation()) { |
1121 PairLocation* pair = source_loc.AsPairLocation(); | 1087 PairLocation* pair = source_loc.AsPairLocation(); |
1122 deopt_instr = new(zone()) DeoptMintPairInstr( | 1088 deopt_instr = |
1123 ToCpuRegisterSource(pair->At(0)), | 1089 new (zone()) DeoptMintPairInstr(ToCpuRegisterSource(pair->At(0)), |
1124 ToCpuRegisterSource(pair->At(1))); | 1090 ToCpuRegisterSource(pair->At(1))); |
1125 } else { | 1091 } else { |
1126 ASSERT(!source_loc.IsPairLocation()); | 1092 ASSERT(!source_loc.IsPairLocation()); |
1127 deopt_instr = new(zone()) DeoptMintInstr( | 1093 deopt_instr = |
1128 ToCpuRegisterSource(source_loc)); | 1094 new (zone()) DeoptMintInstr(ToCpuRegisterSource(source_loc)); |
1129 } | 1095 } |
1130 break; | 1096 break; |
1131 } | 1097 } |
1132 case kUnboxedInt32: | 1098 case kUnboxedInt32: |
1133 deopt_instr = new(zone()) DeoptInt32Instr( | 1099 deopt_instr = |
1134 ToCpuRegisterSource(source_loc)); | 1100 new (zone()) DeoptInt32Instr(ToCpuRegisterSource(source_loc)); |
1135 break; | 1101 break; |
1136 case kUnboxedUint32: | 1102 case kUnboxedUint32: |
1137 deopt_instr = new(zone()) DeoptUint32Instr( | 1103 deopt_instr = |
1138 ToCpuRegisterSource(source_loc)); | 1104 new (zone()) DeoptUint32Instr(ToCpuRegisterSource(source_loc)); |
1139 break; | 1105 break; |
1140 case kUnboxedDouble: | 1106 case kUnboxedDouble: |
1141 deopt_instr = new(zone()) DeoptDoubleInstr( | 1107 deopt_instr = new (zone()) DeoptDoubleInstr( |
1142 ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot)); | 1108 ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot)); |
1143 break; | 1109 break; |
1144 case kUnboxedFloat32x4: | 1110 case kUnboxedFloat32x4: |
1145 deopt_instr = new(zone()) DeoptFloat32x4Instr( | 1111 deopt_instr = new (zone()) DeoptFloat32x4Instr( |
1146 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); | 1112 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
1147 break; | 1113 break; |
1148 case kUnboxedFloat64x2: | 1114 case kUnboxedFloat64x2: |
1149 deopt_instr = new(zone()) DeoptFloat64x2Instr( | 1115 deopt_instr = new (zone()) DeoptFloat64x2Instr( |
1150 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); | 1116 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
1151 break; | 1117 break; |
1152 case kUnboxedInt32x4: | 1118 case kUnboxedInt32x4: |
1153 deopt_instr = new(zone()) DeoptInt32x4Instr( | 1119 deopt_instr = new (zone()) DeoptInt32x4Instr( |
1154 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); | 1120 ToFpuRegisterSource(source_loc, Location::kQuadStackSlot)); |
1155 break; | 1121 break; |
1156 default: | 1122 default: |
1157 UNREACHABLE(); | 1123 UNREACHABLE(); |
1158 break; | 1124 break; |
1159 } | 1125 } |
1160 } | 1126 } |
1161 ASSERT(dest_index == FrameSize()); | 1127 ASSERT(dest_index == FrameSize()); |
1162 ASSERT(deopt_instr != NULL); | 1128 ASSERT(deopt_instr != NULL); |
1163 instructions_.Add(deopt_instr); | 1129 instructions_.Add(deopt_instr); |
1164 } | 1130 } |
1165 | 1131 |
1166 | 1132 |
1167 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { | 1133 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { |
1168 ASSERT(dest_index == FrameSize()); | 1134 ASSERT(dest_index == FrameSize()); |
1169 instructions_.Add(new(zone()) DeoptCallerFpInstr()); | 1135 instructions_.Add(new (zone()) DeoptCallerFpInstr()); |
1170 } | 1136 } |
1171 | 1137 |
1172 | 1138 |
1173 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { | 1139 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { |
1174 ASSERT(dest_index == FrameSize()); | 1140 ASSERT(dest_index == FrameSize()); |
1175 instructions_.Add(new(zone()) DeoptCallerPpInstr()); | 1141 instructions_.Add(new (zone()) DeoptCallerPpInstr()); |
1176 } | 1142 } |
1177 | 1143 |
1178 | 1144 |
1179 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { | 1145 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { |
1180 ASSERT(dest_index == FrameSize()); | 1146 ASSERT(dest_index == FrameSize()); |
1181 instructions_.Add(new(zone()) DeoptCallerPcInstr()); | 1147 instructions_.Add(new (zone()) DeoptCallerPcInstr()); |
1182 } | 1148 } |
1183 | 1149 |
1184 | 1150 |
1185 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { | 1151 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { |
1186 ASSERT(dest_index == FrameSize()); | 1152 ASSERT(dest_index == FrameSize()); |
1187 intptr_t object_table_index = FindOrAddObjectInTable(obj); | 1153 intptr_t object_table_index = FindOrAddObjectInTable(obj); |
1188 instructions_.Add(new(zone()) DeoptConstantInstr(object_table_index)); | 1154 instructions_.Add(new (zone()) DeoptConstantInstr(object_table_index)); |
1189 } | 1155 } |
1190 | 1156 |
1191 | 1157 |
1192 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { | 1158 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { |
1193 const intptr_t index = FindMaterialization(mat); | 1159 const intptr_t index = FindMaterialization(mat); |
1194 if (index >= 0) { | 1160 if (index >= 0) { |
1195 return; // Already added. | 1161 return; // Already added. |
1196 } | 1162 } |
1197 materializations_.Add(mat); | 1163 materializations_.Add(mat); |
1198 | 1164 |
1199 // Count initialized fields and emit kMaterializeObject instruction. | 1165 // Count initialized fields and emit kMaterializeObject instruction. |
1200 // There is no need to write nulls into fields because object is null | 1166 // There is no need to write nulls into fields because object is null |
1201 // initialized by default. | 1167 // initialized by default. |
1202 intptr_t non_null_fields = 0; | 1168 intptr_t non_null_fields = 0; |
1203 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1169 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
1204 if (!mat->InputAt(i)->BindsToConstantNull()) { | 1170 if (!mat->InputAt(i)->BindsToConstantNull()) { |
1205 non_null_fields++; | 1171 non_null_fields++; |
1206 } | 1172 } |
1207 } | 1173 } |
1208 | 1174 |
1209 instructions_.Add( | 1175 instructions_.Add(new (zone()) DeoptMaterializeObjectInstr(non_null_fields)); |
1210 new(zone()) DeoptMaterializeObjectInstr(non_null_fields)); | |
1211 | 1176 |
1212 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1177 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
1213 MaterializeObjectInstr* nested_mat = mat->InputAt(i)->definition()-> | 1178 MaterializeObjectInstr* nested_mat = |
1214 AsMaterializeObject(); | 1179 mat->InputAt(i)->definition()->AsMaterializeObject(); |
1215 if (nested_mat != NULL) { | 1180 if (nested_mat != NULL) { |
1216 AddMaterialization(nested_mat); | 1181 AddMaterialization(nested_mat); |
1217 } | 1182 } |
1218 } | 1183 } |
1219 } | 1184 } |
1220 | 1185 |
1221 | 1186 |
1222 intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) { | 1187 intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) { |
1223 ASSERT(dest_index == kDartFrameFixedSize); | 1188 ASSERT(dest_index == kDartFrameFixedSize); |
1224 for (intptr_t i = 0; i < materializations_.length(); i++) { | 1189 for (intptr_t i = 0; i < materializations_.length(); i++) { |
(...skipping 21 matching lines...) Expand all Loading... |
1246 return i; | 1211 return i; |
1247 } | 1212 } |
1248 } | 1213 } |
1249 return -1; | 1214 return -1; |
1250 } | 1215 } |
1251 | 1216 |
1252 | 1217 |
1253 static uint8_t* ZoneReAlloc(uint8_t* ptr, | 1218 static uint8_t* ZoneReAlloc(uint8_t* ptr, |
1254 intptr_t old_size, | 1219 intptr_t old_size, |
1255 intptr_t new_size) { | 1220 intptr_t new_size) { |
1256 return Thread::Current()->zone()->Realloc<uint8_t>( | 1221 return Thread::Current()->zone()->Realloc<uint8_t>(ptr, old_size, new_size); |
1257 ptr, old_size, new_size); | |
1258 } | 1222 } |
1259 | 1223 |
1260 | 1224 |
1261 RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) { | 1225 RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) { |
1262 intptr_t length = instructions_.length(); | 1226 intptr_t length = instructions_.length(); |
1263 | 1227 |
1264 // Count the number of instructions that are a shared suffix of some deopt | 1228 // Count the number of instructions that are a shared suffix of some deopt |
1265 // info already written. | 1229 // info already written. |
1266 TrieNode* suffix = trie_root_; | 1230 TrieNode* suffix = trie_root_; |
1267 intptr_t suffix_length = 0; | 1231 intptr_t suffix_length = 0; |
(...skipping 28 matching lines...) Expand all Loading... |
1296 } | 1260 } |
1297 | 1261 |
1298 // Write the unshared instructions and build their sub-tree. | 1262 // Write the unshared instructions and build their sub-tree. |
1299 TrieNode* node = use_suffix ? suffix : trie_root_; | 1263 TrieNode* node = use_suffix ? suffix : trie_root_; |
1300 const intptr_t write_count = use_suffix ? length - 1 : length; | 1264 const intptr_t write_count = use_suffix ? length - 1 : length; |
1301 for (intptr_t i = write_count - 1; i >= 0; --i) { | 1265 for (intptr_t i = write_count - 1; i >= 0; --i) { |
1302 DeoptInstr* instr = instructions_[i]; | 1266 DeoptInstr* instr = instructions_[i]; |
1303 Writer::Write(&stream, instr->kind()); | 1267 Writer::Write(&stream, instr->kind()); |
1304 Writer::Write(&stream, instr->source_index()); | 1268 Writer::Write(&stream, instr->source_index()); |
1305 | 1269 |
1306 TrieNode* child = new(zone()) TrieNode(instr, current_info_number_); | 1270 TrieNode* child = new (zone()) TrieNode(instr, current_info_number_); |
1307 node->AddChild(child); | 1271 node->AddChild(child); |
1308 node = child; | 1272 node = child; |
1309 } | 1273 } |
1310 | 1274 |
1311 const TypedData& deopt_info = TypedData::Handle(zone(), TypedData::New( | 1275 const TypedData& deopt_info = TypedData::Handle( |
1312 kTypedDataUint8ArrayCid, stream.bytes_written(), Heap::kOld)); | 1276 zone(), TypedData::New(kTypedDataUint8ArrayCid, stream.bytes_written(), |
| 1277 Heap::kOld)); |
1313 { | 1278 { |
1314 NoSafepointScope no_safepoint; | 1279 NoSafepointScope no_safepoint; |
1315 memmove(deopt_info.DataAddr(0), | 1280 memmove(deopt_info.DataAddr(0), stream.buffer(), stream.bytes_written()); |
1316 stream.buffer(), | |
1317 stream.bytes_written()); | |
1318 } | 1281 } |
1319 | 1282 |
1320 ASSERT(DeoptInfo::VerifyDecompression( | 1283 ASSERT( |
1321 instructions_, deopt_table, deopt_info)); | 1284 DeoptInfo::VerifyDecompression(instructions_, deopt_table, deopt_info)); |
1322 instructions_.Clear(); | 1285 instructions_.Clear(); |
1323 materializations_.Clear(); | 1286 materializations_.Clear(); |
1324 frame_start_ = -1; | 1287 frame_start_ = -1; |
1325 | 1288 |
1326 ++current_info_number_; | 1289 ++current_info_number_; |
1327 return deopt_info.raw(); | 1290 return deopt_info.raw(); |
1328 } | 1291 } |
1329 | 1292 |
1330 | 1293 |
1331 intptr_t DeoptTable::SizeFor(intptr_t length) { | 1294 intptr_t DeoptTable::SizeFor(intptr_t length) { |
(...skipping 24 matching lines...) Expand all Loading... |
1356 Smi* offset, | 1319 Smi* offset, |
1357 TypedData* info, | 1320 TypedData* info, |
1358 Smi* reason) { | 1321 Smi* reason) { |
1359 intptr_t i = index * kEntrySize; | 1322 intptr_t i = index * kEntrySize; |
1360 *offset ^= table.At(i); | 1323 *offset ^= table.At(i); |
1361 *info ^= table.At(i + 1); | 1324 *info ^= table.At(i + 1); |
1362 *reason ^= table.At(i + 2); | 1325 *reason ^= table.At(i + 2); |
1363 } | 1326 } |
1364 | 1327 |
1365 } // namespace dart | 1328 } // namespace dart |
OLD | NEW |