Chromium Code Reviews| Index: runtime/vm/code_generator.cc |
| =================================================================== |
| --- runtime/vm/code_generator.cc (revision 27970) |
| +++ 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. |
| +// Copy optimized frame into the DeoptContext.. |
| // 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) { |
| +static void CopyFrame(DeoptContext* deopt_context, |
| + const Code& optimized_code, |
| + const StackFrame& frame) { |
| 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,7 @@ |
| for (intptr_t i = 0; i < frame_copy_size; i++) { |
| frame_copy[i] = *(start + i); |
| } |
| - Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size); |
| + deopt_context->SetFromFrame(frame_copy, frame_copy_size); |
| } |
| @@ -1562,9 +1565,11 @@ |
| + (kNumberOfCpuRegisters * kWordSize) |
| + (kNumberOfFpuRegisters * kFpuRegisterSize) |
| - ((kFirstLocalSlotFromFp + 1) * kWordSize); |
| - CopySavedRegisters(saved_registers_address); |
| + fpu_register_t* fpu_registers; |
| + intptr_t* cpu_registers; |
| + CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); |
| - // Get optimized code and frame that need to be deoptimized. |
| + // Get optimized code and frame that needs to be deoptimized. |
| DartFrameIterator iterator(last_fp); |
| StackFrame* caller_frame = iterator.NextFrame(); |
| ASSERT(caller_frame != NULL); |
| @@ -1576,9 +1581,21 @@ |
| 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); |
| + |
| + // TODO(turnidge): Why can't I move CopySavedRegisters here? |
|
turnidge
2013/09/26 21:17:28
Srdjan, any idea on this one? When I move CopySav
srdjan
2013/09/27 17:04:54
I do not understand why. CC-d Kevin and Florian th
|
| + deopt_context->SetSavedRegisters(fpu_registers, cpu_registers); |
| + CopyFrame(deopt_context, optimized_code, *caller_frame); |
| + |
| 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,24 +1608,21 @@ |
| // 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 |
| - num_args |
| - kParamEndSlotFromFp |
| - - 1; // For fp. |
| + - 1; // For fp. |
| return unoptimized_stack_size * kWordSize; // Stack size (FP - SP) in bytes. |
| } |
| 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 +1640,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->SetToFrame(start, to_frame_size); |
| + |
| const intptr_t frame_size = deopt_info.FrameSize(); |
| // All kMaterializeObject instructions are emitted before the instructions |
| @@ -1642,15 +1654,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->GetToFrameAddressAt(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 +1670,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->GetToFrameAddressAt(to_index); |
| + deopt_instructions[from_index]->Execute(deopt_context, to_addr); |
| } |
| if (FLAG_trace_deoptimization_verbose) { |
| @@ -1691,26 +1703,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 +1723,20 @@ |
| // 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(); |
| + // Delete temporary copies of frame and registers. |
| + isolate->set_deopt_context(NULL); |
| + delete[] deopt_context->from_frame(); // Allocated in CopyFrame. |
| + delete[] deopt_context->fpu_registers(); // Allocated in CopySavedRegisters. |
| + delete[] deopt_context->cpu_registers(); // Allocated in CopySavedRegisters. |
| + 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); |
| } |
| } |