| Index: runtime/vm/flow_graph_compiler.cc
|
| diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
|
| index 5e3bd7810648a398df14d6f269f42ee359bd1fa1..543db79fad6bbfe0b1b48e47c90b039ca767c9d1 100644
|
| --- a/runtime/vm/flow_graph_compiler.cc
|
| +++ b/runtime/vm/flow_graph_compiler.cc
|
| @@ -45,46 +45,69 @@ void CompilerDeoptInfoWithStub::BuildReturnAddress(DeoptInfoBuilder* builder,
|
| }
|
|
|
|
|
| +// Assign locations to incoming arguments, i.e., values pushed above spill slots
|
| +// with PushArgument. Recursively allocates from outermost to innermost
|
| +// environment.
|
| +void CompilerDeoptInfo::AllocateIncomingParametersRecursive(
|
| + Environment* env,
|
| + intptr_t* stack_height) {
|
| + if (env == NULL) return;
|
| + AllocateIncomingParametersRecursive(env->outer(), stack_height);
|
| + for (Environment::ShallowIterator it(env); !it.Done(); it.Advance()) {
|
| + if (it.CurrentLocation().IsInvalid()) {
|
| + ASSERT(it.CurrentValue()->definition()->IsPushArgument());
|
| + it.SetCurrentLocation(Location::StackSlot((*stack_height)++));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler) {
|
| if (deoptimization_env_ == NULL) return DeoptInfo::null();
|
| +
|
| + intptr_t stack_height = compiler->StackSize();
|
| + AllocateIncomingParametersRecursive(deoptimization_env_, &stack_height);
|
| +
|
| const Function& function = compiler->parsed_function().function();
|
| - // For functions with optional arguments, all incoming are copied to local
|
| - // area below FP, deoptimization environment does not track them.
|
| - const intptr_t num_args =
|
| + // For functions with optional arguments, all incoming arguments are copied
|
| + // to spill slots. The deoptimization environment does not track them.
|
| + const intptr_t incoming_arg_count =
|
| function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
|
| - const intptr_t fixed_parameter_count =
|
| - deoptimization_env_->fixed_parameter_count();
|
| - DeoptInfoBuilder builder(compiler->object_table(), num_args);
|
| + DeoptInfoBuilder builder(compiler->object_table(), incoming_arg_count);
|
|
|
| intptr_t slot_ix = 0;
|
| - BuildReturnAddress(&builder, function, slot_ix++);
|
| -
|
| - // Assign locations to values pushed above spill slots with PushArgument.
|
| - intptr_t height = compiler->StackSize();
|
| - for (intptr_t i = 0; i < deoptimization_env_->Length(); i++) {
|
| - if (deoptimization_env_->LocationAt(i).IsInvalid()) {
|
| - ASSERT(deoptimization_env_->ValueAt(i)->definition()->IsPushArgument());
|
| - *deoptimization_env_->LocationSlotAt(i) = Location::StackSlot(height++);
|
| + Environment* env = deoptimization_env_;
|
| + while (env != NULL) {
|
| + const Function& function = env->function();
|
| + const intptr_t fixed_parameter_count = env->fixed_parameter_count();
|
| +
|
| + if (slot_ix == 0) {
|
| + // For the innermost environment call the virtual return builder.
|
| + BuildReturnAddress(&builder, function, slot_ix++);
|
| + } else {
|
| + // For any outer environment the deopt id is that of the call instruction
|
| + // which is recorded in the outer environment.
|
| + builder.AddReturnAddressAfter(function, env->deopt_id(), slot_ix++);
|
| }
|
| - }
|
|
|
| - for (intptr_t i = deoptimization_env_->Length() - 1;
|
| - i >= fixed_parameter_count;
|
| - i--) {
|
| - builder.AddCopy(deoptimization_env_->LocationAt(i),
|
| - *deoptimization_env_->ValueAt(i),
|
| - slot_ix++);
|
| - }
|
| + for (intptr_t i = env->Length() - 1; i >= fixed_parameter_count; i--) {
|
| + builder.AddCopy(env->LocationAt(i), *env->ValueAt(i), slot_ix++);
|
| + }
|
| +
|
| + // PC marker and caller FP.
|
| + builder.AddPcMarker(function, slot_ix++);
|
| + builder.AddCallerFp(slot_ix++);
|
| +
|
| + // On the outermost environment set caller PC and incoming arguments.
|
| + if (env->outer() == NULL) {
|
| + builder.AddCallerPc(slot_ix++);
|
| + for (intptr_t i = fixed_parameter_count - 1; i >= 0; i--) {
|
| + builder.AddCopy(env->LocationAt(i), *env->ValueAt(i), slot_ix++);
|
| + }
|
| + }
|
|
|
| - // PC marker, caller-fp, caller-pc.
|
| - builder.AddPcMarker(function, slot_ix++);
|
| - builder.AddCallerFp(slot_ix++);
|
| - builder.AddCallerPc(slot_ix++);
|
| - // Incoming arguments.
|
| - for (intptr_t i = fixed_parameter_count - 1; i >= 0; i--) {
|
| - builder.AddCopy(deoptimization_env_->LocationAt(i),
|
| - *deoptimization_env_->ValueAt(i),
|
| - slot_ix++);
|
| + // Iterate on the outer environment.
|
| + env = env->outer();
|
| }
|
|
|
| const DeoptInfo& deopt_info = DeoptInfo::Handle(builder.CreateDeoptInfo());
|
| @@ -342,7 +365,7 @@ void FlowGraphCompiler::FinalizePcDescriptors(const Code& code) {
|
| ASSERT(pc_descriptors_list_ != NULL);
|
| const PcDescriptors& descriptors = PcDescriptors::Handle(
|
| pc_descriptors_list_->FinalizePcDescriptors(code.EntryPoint()));
|
| - descriptors.Verify(parsed_function_.function().is_optimizable());
|
| + if (!is_optimizing_) descriptors.Verify(parsed_function_.function());
|
| code.set_pc_descriptors(descriptors);
|
| }
|
|
|
|
|