Chromium Code Reviews| Index: runtime/vm/code_generator.cc |
| diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc |
| index fb9e84635d038f7adc2ab0c2a6b9642b4080dfc4..5cf9f29b482735765493339b53077006b533653e 100644 |
| --- a/runtime/vm/code_generator.cc |
| +++ b/runtime/vm/code_generator.cc |
| @@ -1545,7 +1545,7 @@ DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| const intptr_t num_args = |
| function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| intptr_t unoptimized_stack_size = |
| - + deopt_info.TranslationLength() - num_args |
| + + deopt_info.FrameSize() - num_args |
| - kLastParamSlotIndex; // Subtract caller FP and PC (possibly pc marker). |
| return unoptimized_stack_size * kWordSize; |
| } |
| @@ -1577,16 +1577,44 @@ static intptr_t DeoptimizeWithDeoptInfo(const Code& code, |
| Array::Handle(code.object_table()), |
| num_args, |
| static_cast<DeoptReasonId>(deopt_reason)); |
| - for (intptr_t to_index = len - 1; to_index >= 0; to_index--) { |
| - deopt_instructions[to_index]->Execute(&deopt_context, to_index); |
| + 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; |
| + Isolate::Current()->PrepareForDeferredMaterialization(num_materializations); |
| + for (intptr_t from_index = 0, to_index = 1; |
| + 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); |
| + DeferredObject* obj = new DeferredObject(field_count, args); |
| + Isolate::Current()->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.GetToFrameAddressAt(to_index); |
| + deopt_instructions[from_index]->Execute(&deopt_context, to_addr); |
| + } |
| + |
| if (FLAG_trace_deoptimization_verbose) { |
| - for (intptr_t i = 0; i < len; i++) { |
| - OS::PrintErr("*%"Pd". [%p] %#014"Px" [%s]\n", |
| - i, |
| - &start[i], |
| - start[i], |
| - deopt_instructions[i]->ToCString()); |
| + 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()); |
| } |
| } |
| return deopt_context.GetCallerFp(); |
| @@ -1637,17 +1665,27 @@ END_LEAF_RUNTIME_ENTRY |
| // This is the last step in the deoptimization, GC can occur. |
| -DEFINE_RUNTIME_ENTRY(DeoptimizeMaterializeDoubles, 0) { |
| - DeferredObject* deferred_object = Isolate::Current()->DetachDeferredObjects(); |
| - |
| - while (deferred_object != NULL) { |
| - DeferredObject* current = deferred_object; |
| - deferred_object = deferred_object->next(); |
| - |
| - current->Materialize(); |
| - |
| - delete current; |
| +// Returns number of bytes to remove from the expression stack of the |
| +// bottom-most deoptimized frame. Those arguments were artificially injected |
| +// under return address to keep them discoverable by GC that can occur during |
| +// materialization phase. |
|
srdjan
2013/05/07 23:11:45
Add comment what it returns.
Vyacheslav Egorov (Google)
2013/05/07 23:28:21
The comment already starts with "Returns number" e
|
| +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. |
|
srdjan
2013/05/07 23:11:45
Add comment that deferred object cannot refer to o
Vyacheslav Egorov (Google)
2013/05/07 23:28:21
Done.
|
| + isolate->MaterializeDeferredBoxes(); |
| + isolate->MaterializeDeferredObjects(); |
| + |
| + // 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(); |
| + |
| + // Return value tells deoptimization stub to remove the given number of bytes |
| + // from the stack. |
| + arguments.SetReturn(Smi::Handle(Smi::New(deopt_arguments * kWordSize))); |
| // Since this is the only step where GC can occur during deoptimization, |
| // use it to report the source line where deoptimization occured. |