Index: runtime/vm/code_generator.cc |
=================================================================== |
--- runtime/vm/code_generator.cc (revision 28466) |
+++ runtime/vm/code_generator.cc (working copy) |
@@ -1520,39 +1520,6 @@ |
} |
-// Copy optimized frame. The first incoming argument is stored at the |
-// last entry in the copied frame buffer. |
-static void CopyFrame(const Code& optimized_code, |
- const StackFrame& frame, |
- intptr_t** frame_start, |
- intptr_t* frame_size) { |
- const Function& function = Function::Handle(optimized_code.function()); |
- // Do not copy incoming arguments if there are optional arguments (they |
- // are copied into local space at method entry). |
- const intptr_t num_args = |
- function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
- // The fixed size section of the (fake) Dart frame called via a stub by the |
- // optimized function contains FP, PP (ARM and MIPS only), PC-marker and |
- // return-address. This section is copied as well, so that its contained |
- // values can be updated before returning to the deoptimized function. |
- const intptr_t frame_copy_size = |
- + kDartFrameFixedSize // For saved values below sp. |
- + ((frame.fp() - frame.sp()) / kWordSize) // For frame size incl. sp. |
- + 1 // For fp. |
- + kParamEndSlotFromFp // For saved values above fp. |
- + num_args; // For arguments. |
- intptr_t* frame_copy = new intptr_t[frame_copy_size]; |
- ASSERT(frame_copy != NULL); |
- intptr_t* start = reinterpret_cast<intptr_t*>( |
- frame.sp() - (kDartFrameFixedSize * kWordSize)); |
- for (intptr_t i = 0; i < frame_copy_size; i++) { |
- frame_copy[i] = *(start + i); |
- } |
- *frame_start = frame_copy; |
- *frame_size = frame_copy_size; |
-} |
- |
- |
// Copies saved registers and caller's frame into temporary buffers. |
// Returns the stack size of unoptimized frame. |
DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
@@ -1574,123 +1541,24 @@ |
const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
ASSERT(optimized_code.is_optimized()); |
- intptr_t deopt_reason = kDeoptUnknown; |
- const DeoptInfo& deopt_info = DeoptInfo::Handle( |
- optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); |
- ASSERT(!deopt_info.IsNull()); |
- |
- // Create the DeoptContext for this deoptimization. Store in isolate. |
- const Function& function = Function::Handle(optimized_code.function()); |
- const intptr_t num_args = |
- function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
- DeoptContext* deopt_context = new DeoptContext( |
- Array::Handle(optimized_code.object_table()), |
- num_args, |
- static_cast<DeoptReasonId>(deopt_reason)); |
- isolate->set_deopt_context(deopt_context); |
- |
- // Copy the saved registers and the source frame. |
+ // Copy the saved registers from the stack. |
fpu_register_t* fpu_registers; |
intptr_t* cpu_registers; |
- intptr_t* frame_start; |
- intptr_t frame_size; |
CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); |
- CopyFrame(optimized_code, *caller_frame, &frame_start, &frame_size); |
- deopt_context->SetSourceArgs(frame_start, frame_size, |
- fpu_registers, cpu_registers, |
- true); // true = source frame is a copy. |
- if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
- OS::PrintErr( |
- "Deoptimizing (reason %" Pd " '%s') at pc %#" Px " '%s' (count %d)\n", |
- deopt_reason, |
- DeoptReasonToText(deopt_reason), |
- caller_frame->pc(), |
- function.ToFullyQualifiedCString(), |
- function.deoptimization_counter()); |
- } |
+ // Create the DeoptContext. |
+ DeoptContext* deopt_context = |
+ new DeoptContext(caller_frame, optimized_code, |
+ DeoptContext::kDestIsOriginalFrame, |
+ fpu_registers, cpu_registers); |
+ isolate->set_deopt_context(deopt_context); |
- // Compute the stack size of the unoptimized frame. For functions with |
- // optional arguments the deoptimization info does not describe the |
- // incoming arguments. |
- const intptr_t unoptimized_stack_size = |
- + deopt_info.FrameSize() |
- - kDartFrameFixedSize |
- - num_args |
- - kParamEndSlotFromFp |
- - 1; // For fp. |
- return unoptimized_stack_size * kWordSize; // Stack size (FP - SP) in bytes. |
+ // Stack size (FP - SP) in bytes. |
+ return deopt_context->DestStackAdjustment() * kWordSize; |
} |
END_LEAF_RUNTIME_ENTRY |
-static void DeoptimizeWithDeoptInfo(DeoptContext* deopt_context, |
- const Code& code, |
- const DeoptInfo& deopt_info, |
- const StackFrame& caller_frame) { |
- const intptr_t len = deopt_info.TranslationLength(); |
- GrowableArray<DeoptInstr*> deopt_instructions(len); |
- const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
- ASSERT(!deopt_table.IsNull()); |
- deopt_info.ToInstructions(deopt_table, &deopt_instructions); |
- |
- intptr_t* start = reinterpret_cast<intptr_t*>( |
- caller_frame.sp() - (kDartFrameFixedSize * kWordSize)); |
- const Function& function = Function::Handle(code.function()); |
- const intptr_t num_args = |
- function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
- const intptr_t to_frame_size = |
- + kDartFrameFixedSize // For saved values below sp. |
- + (caller_frame.fp() - caller_frame.sp()) / kWordSize |
- + 1 // For fp. |
- + kParamEndSlotFromFp |
- + num_args; |
- |
- deopt_context->SetDestArgs(start, to_frame_size); |
- |
- const intptr_t frame_size = deopt_info.FrameSize(); |
- |
- // All kMaterializeObject instructions are emitted before the instructions |
- // that describe stack frames. Skip them and defer materialization of |
- // objects until the frame is fully reconstructed and it is safe to perform |
- // GC. |
- // Arguments (class of the instance to allocate and field-value pairs) are |
- // described as part of the expression stack for the bottom-most deoptimized |
- // frame. They will be used during materialization and removed from the stack |
- // right before control switches to the unoptimized code. |
- const intptr_t num_materializations = len - frame_size; |
- deopt_context->PrepareForDeferredMaterialization(num_materializations); |
- for (intptr_t from_index = 0, to_index = kDartFrameFixedSize; |
- from_index < num_materializations; |
- from_index++) { |
- const intptr_t field_count = |
- DeoptInstr::GetFieldCount(deopt_instructions[from_index]); |
- intptr_t* args = deopt_context->GetDestFrameAddressAt(to_index); |
- DeferredObject* obj = new DeferredObject(field_count, args); |
- deopt_context->SetDeferredObjectAt(from_index, obj); |
- to_index += obj->ArgumentCount(); |
- } |
- |
- // Populate stack frames. |
- for (intptr_t to_index = frame_size - 1, from_index = len - 1; |
- to_index >= 0; |
- to_index--, from_index--) { |
- intptr_t* to_addr = deopt_context->GetDestFrameAddressAt(to_index); |
- deopt_instructions[from_index]->Execute(deopt_context, to_addr); |
- } |
- |
- if (FLAG_trace_deoptimization_verbose) { |
- for (intptr_t i = 0; i < frame_size; i++) { |
- OS::PrintErr("*%" Pd ". [%" Px "] %#014" Px " [%s]\n", |
- i, |
- reinterpret_cast<uword>(&start[i]), |
- start[i], |
- deopt_instructions[i + (len - frame_size)]->ToCString()); |
- } |
- } |
-} |
- |
- |
// The stack has been adjusted to fit all values for unoptimized frame. |
// Fill the unoptimized frame. |
DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, 1, uword last_fp) { |
@@ -1698,26 +1566,37 @@ |
StackZone zone(isolate); |
HANDLESCOPE(isolate); |
+ DeoptContext* deopt_context = isolate->deopt_context(); |
DartFrameIterator iterator(last_fp); |
StackFrame* caller_frame = iterator.NextFrame(); |
ASSERT(caller_frame != NULL); |
- const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
- const Function& function = Function::Handle(optimized_code.function()); |
- ASSERT(!function.IsNull()); |
- const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); |
- ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); |
- ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); |
- intptr_t deopt_reason = kDeoptUnknown; |
- const DeoptInfo& deopt_info = DeoptInfo::Handle( |
- optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); |
- ASSERT(!deopt_info.IsNull()); |
+#if defined(DEBUG) |
+ { |
+ // The code from the deopt_context. |
+ const Code& code = Code::Handle(deopt_context->code()); |
- DeoptContext* deopt_context = isolate->deopt_context(); |
- DeoptimizeWithDeoptInfo(deopt_context, |
- optimized_code, |
- deopt_info, |
- *caller_frame); |
+ // The code from our frame. |
+ const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
+ const Function& function = Function::Handle(optimized_code.function()); |
+ ASSERT(!function.IsNull()); |
+ |
+ // The code will be the same as before. |
+ ASSERT(code.raw() == optimized_code.raw()); |
+ |
+ // Some sanity checking of the optimized/unoptimized code. |
+ const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); |
+ ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); |
+ ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); |
+ } |
+#endif |
+ |
+ // TODO(turnidge): Compute the start of the dest frame in the |
+ // DeoptContext instead of passing it in here. |
+ intptr_t* start = reinterpret_cast<intptr_t*>( |
+ caller_frame->sp() - (kDartFrameFixedSize * kWordSize)); |
+ deopt_context->set_dest_frame(start); |
+ deopt_context->FillDestFrame(); |
} |
END_LEAF_RUNTIME_ENTRY |
@@ -1729,7 +1608,6 @@ |
// materialization phase. |
DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { |
DeoptContext* deopt_context = isolate->deopt_context(); |
- |
intptr_t deopt_arg_count = deopt_context->MaterializeDeferredObjects(); |
isolate->set_deopt_context(NULL); |
delete deopt_context; |
@@ -1737,24 +1615,6 @@ |
// Return value tells deoptimization stub to remove the given number of bytes |
// from the stack. |
arguments.SetReturn(Smi::Handle(Smi::New(deopt_arg_count * kWordSize))); |
- |
- // Since this is the only step where GC can occur during deoptimization, |
- // use it to report the source line where deoptimization occured. |
- if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
- DartFrameIterator iterator; |
- StackFrame* top_frame = iterator.NextFrame(); |
- ASSERT(top_frame != NULL); |
- const Code& code = Code::Handle(top_frame->LookupDartCode()); |
- const Function& top_function = Function::Handle(code.function()); |
- const Script& script = Script::Handle(top_function.script()); |
- const intptr_t token_pos = code.GetTokenIndexOfPC(top_frame->pc()); |
- intptr_t line, column; |
- script.GetTokenLocation(token_pos, &line, &column); |
- String& line_string = String::Handle(script.GetLine(line)); |
- OS::PrintErr(" Function: %s\n", top_function.ToFullyQualifiedCString()); |
- OS::PrintErr(" Line %" Pd ": '%s'\n", line, line_string.ToCString()); |
- OS::PrintErr(" Deopt args: %" Pd "\n", deopt_arg_count); |
- } |
} |