| Index: runtime/vm/code_generator.cc
|
| ===================================================================
|
| --- runtime/vm/code_generator.cc (revision 28111)
|
| +++ runtime/vm/code_generator.cc (working copy)
|
| @@ -1494,8 +1494,9 @@
|
| }
|
|
|
|
|
| -// Copy saved registers into the isolate buffer.
|
| -static void CopySavedRegisters(uword saved_registers_address) {
|
| +static void CopySavedRegisters(uword saved_registers_address,
|
| + fpu_register_t** fpu_registers,
|
| + intptr_t** cpu_registers) {
|
| ASSERT(sizeof(fpu_register_t) == kFpuRegisterSize);
|
| fpu_register_t* fpu_registers_copy =
|
| new fpu_register_t[kNumberOfFpuRegisters];
|
| @@ -1505,7 +1506,7 @@
|
| *reinterpret_cast<fpu_register_t*>(saved_registers_address);
|
| saved_registers_address += kFpuRegisterSize;
|
| }
|
| - Isolate::Current()->set_deopt_fpu_registers_copy(fpu_registers_copy);
|
| + *fpu_registers = fpu_registers_copy;
|
|
|
| ASSERT(sizeof(intptr_t) == kWordSize);
|
| intptr_t* cpu_registers_copy = new intptr_t[kNumberOfCpuRegisters];
|
| @@ -1515,14 +1516,16 @@
|
| *reinterpret_cast<intptr_t*>(saved_registers_address);
|
| saved_registers_address += kWordSize;
|
| }
|
| - Isolate::Current()->set_deopt_cpu_registers_copy(cpu_registers_copy);
|
| + *cpu_registers = cpu_registers_copy;
|
| }
|
|
|
|
|
| -// Copy optimized frame into the isolate buffer.
|
| -// 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) {
|
| +// 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).
|
| @@ -1545,7 +1548,8 @@
|
| for (intptr_t i = 0; i < frame_copy_size; i++) {
|
| frame_copy[i] = *(start + i);
|
| }
|
| - Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size);
|
| + *frame_start = frame_copy;
|
| + *frame_size = frame_copy_size;
|
| }
|
|
|
|
|
| @@ -1562,7 +1566,6 @@
|
| + (kNumberOfCpuRegisters * kWordSize)
|
| + (kNumberOfFpuRegisters * kFpuRegisterSize)
|
| - ((kFirstLocalSlotFromFp + 1) * kWordSize);
|
| - CopySavedRegisters(saved_registers_address);
|
|
|
| // Get optimized code and frame that need to be deoptimized.
|
| DartFrameIterator iterator(last_fp);
|
| @@ -1576,9 +1579,28 @@
|
| optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason));
|
| ASSERT(!deopt_info.IsNull());
|
|
|
| - CopyFrame(optimized_code, *caller_frame);
|
| + // 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.
|
| + 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) {
|
| - Function& function = Function::Handle(optimized_code.function());
|
| OS::PrintErr(
|
| "Deoptimizing (reason %" Pd " '%s') at pc %#" Px " '%s' (count %d)\n",
|
| deopt_reason,
|
| @@ -1591,9 +1613,6 @@
|
| // Compute the stack size of the unoptimized frame. For functions with
|
| // optional arguments the deoptimization info does not describe the
|
| // incoming arguments.
|
| - const Function& function = Function::Handle(optimized_code.function());
|
| - const intptr_t num_args =
|
| - function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
|
| const intptr_t unoptimized_stack_size =
|
| + deopt_info.FrameSize()
|
| - kDartFrameFixedSize
|
| @@ -1605,10 +1624,10 @@
|
| END_LEAF_RUNTIME_ENTRY
|
|
|
|
|
| -static void DeoptimizeWithDeoptInfo(const Code& code,
|
| +static void DeoptimizeWithDeoptInfo(DeoptContext* deopt_context,
|
| + const Code& code,
|
| const DeoptInfo& deopt_info,
|
| - const StackFrame& caller_frame,
|
| - intptr_t deopt_reason) {
|
| + 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());
|
| @@ -1626,11 +1645,9 @@
|
| + 1 // For fp.
|
| + kParamEndSlotFromFp
|
| + num_args;
|
| - DeoptimizationContext deopt_context(start,
|
| - to_frame_size,
|
| - Array::Handle(code.object_table()),
|
| - num_args,
|
| - static_cast<DeoptReasonId>(deopt_reason));
|
| +
|
| + deopt_context->SetDestArgs(start, to_frame_size);
|
| +
|
| const intptr_t frame_size = deopt_info.FrameSize();
|
|
|
| // All kMaterializeObject instructions are emitted before the instructions
|
| @@ -1642,15 +1659,15 @@
|
| // 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;
|
| - Isolate::Current()->PrepareForDeferredMaterialization(num_materializations);
|
| + 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.GetToFrameAddressAt(to_index);
|
| + intptr_t* args = deopt_context->GetDestFrameAddressAt(to_index);
|
| DeferredObject* obj = new DeferredObject(field_count, args);
|
| - Isolate::Current()->SetDeferredObjectAt(from_index, obj);
|
| + deopt_context->SetDeferredObjectAt(from_index, obj);
|
| to_index += obj->ArgumentCount();
|
| }
|
|
|
| @@ -1658,8 +1675,8 @@
|
| 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.GetToFrameAddressAt(to_index);
|
| - deopt_instructions[from_index]->Execute(&deopt_context, to_addr);
|
| + intptr_t* to_addr = deopt_context->GetDestFrameAddressAt(to_index);
|
| + deopt_instructions[from_index]->Execute(deopt_context, to_addr);
|
| }
|
|
|
| if (FLAG_trace_deoptimization_verbose) {
|
| @@ -1691,26 +1708,16 @@
|
| ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized());
|
| ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized());
|
|
|
| - intptr_t* frame_copy = isolate->deopt_frame_copy();
|
| - intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy();
|
| - fpu_register_t* fpu_registers_copy = isolate->deopt_fpu_registers_copy();
|
| -
|
| intptr_t deopt_reason = kDeoptUnknown;
|
| const DeoptInfo& deopt_info = DeoptInfo::Handle(
|
| optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason));
|
| ASSERT(!deopt_info.IsNull());
|
|
|
| - DeoptimizeWithDeoptInfo(optimized_code,
|
| + DeoptContext* deopt_context = isolate->deopt_context();
|
| + DeoptimizeWithDeoptInfo(deopt_context,
|
| + optimized_code,
|
| deopt_info,
|
| - *caller_frame,
|
| - deopt_reason);
|
| -
|
| - isolate->SetDeoptFrameCopy(NULL, 0);
|
| - isolate->set_deopt_cpu_registers_copy(NULL);
|
| - isolate->set_deopt_fpu_registers_copy(NULL);
|
| - delete[] frame_copy;
|
| - delete[] cpu_registers_copy;
|
| - delete[] fpu_registers_copy;
|
| + *caller_frame);
|
| }
|
| END_LEAF_RUNTIME_ENTRY
|
|
|
| @@ -1721,25 +1728,15 @@
|
| // under return address to keep them discoverable by GC that can occur during
|
| // materialization phase.
|
| DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) {
|
| - // First materialize all unboxed "primitive" values (doubles, mints, simd)
|
| - // then materialize objects. The order is important: objects might be
|
| - // referencing boxes allocated on the first step. At the same time
|
| - // objects can't be referencing other deferred objects because storing
|
| - // an object into a field is always conservatively treated as escaping by
|
| - // allocation sinking and load forwarding.
|
| - isolate->MaterializeDeferredBoxes();
|
| - isolate->MaterializeDeferredObjects();
|
| + DeoptContext* deopt_context = isolate->deopt_context();
|
|
|
| - // Compute total number of artificial arguments used during deoptimization.
|
| - intptr_t deopt_arguments = 0;
|
| - for (intptr_t i = 0; i < isolate->DeferredObjectsCount(); i++) {
|
| - deopt_arguments += isolate->GetDeferredObject(i)->ArgumentCount();
|
| - }
|
| - Isolate::Current()->DeleteDeferredObjects();
|
| + intptr_t deopt_arg_count = deopt_context->MaterializeDeferredObjects();
|
| + isolate->set_deopt_context(NULL);
|
| + delete deopt_context;
|
|
|
| // Return value tells deoptimization stub to remove the given number of bytes
|
| // from the stack.
|
| - arguments.SetReturn(Smi::Handle(Smi::New(deopt_arguments * kWordSize)));
|
| + 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.
|
| @@ -1756,7 +1753,7 @@
|
| 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_arguments);
|
| + OS::PrintErr(" Deopt args: %" Pd "\n", deopt_arg_count);
|
| }
|
| }
|
|
|
|
|