Adjust environments we attach to the block entries.
There were two bugs in the code: - we did not ensure proper outer environment on block entries after inlining; - we did not correct the 'after' environment for eager deopt There is one bug still with the infrastructure: our deoptimization stub does *not* support eager deoptimization to the after deoptimization point. I am leaving it like this for now, because we don't actually ever perform such deoptimization (i.e. even though we diligently attach these environments we don't actually use them in the instruction that can deopt). R=fschneider@google.com BUG= Review URL: https://codereview.chromium.org//784223006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@42257 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -293,6 +293,9 @@ void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) {
|
||||
block->AsTargetEntry()->adjust_edge_weight(scale_factor);
|
||||
}
|
||||
Instruction* instr = block;
|
||||
if (block->env() != NULL) {
|
||||
call_->env()->DeepCopyToOuter(callee_graph->isolate(), block);
|
||||
}
|
||||
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
|
||||
instr = it.Current();
|
||||
// TODO(zerny): Avoid creating unnecessary environments. Note that some
|
||||
@@ -358,7 +361,6 @@ Definition* InlineExitCollector::JoinReturns(BlockEntryInstr** exit_block,
|
||||
caller_graph_->set_max_block_id(join_id);
|
||||
JoinEntryInstr* join =
|
||||
new(I) JoinEntryInstr(join_id, try_index);
|
||||
join->InheritDeoptTargetAfter(isolate(), call_);
|
||||
|
||||
// The dominator set of the join is the intersection of the dominator
|
||||
// sets of all the predecessors. If we keep the dominator sets ordered
|
||||
@@ -430,6 +432,7 @@ Definition* InlineExitCollector::JoinReturns(BlockEntryInstr** exit_block,
|
||||
phi->SetInputAt(i, ValueAt(i));
|
||||
}
|
||||
join->InsertPhi(phi);
|
||||
join->InheritDeoptTargetAfter(caller_graph_, call_, phi);
|
||||
return phi;
|
||||
} else {
|
||||
// In the case that the result is unused, remove the return value uses
|
||||
@@ -437,6 +440,7 @@ Definition* InlineExitCollector::JoinReturns(BlockEntryInstr** exit_block,
|
||||
for (intptr_t i = 0; i < num_exits; ++i) {
|
||||
ReturnAt(i)->UnuseAllInputs();
|
||||
}
|
||||
join->InheritDeoptTargetAfter(caller_graph_, call_, NULL);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -462,7 +466,7 @@ void InlineExitCollector::ReplaceCall(TargetEntryInstr* callee_entry) {
|
||||
TargetEntryInstr* false_block =
|
||||
new(I) TargetEntryInstr(caller_graph_->allocate_block_id(),
|
||||
call_block->try_index());
|
||||
false_block->InheritDeoptTargetAfter(isolate(), call_);
|
||||
false_block->InheritDeoptTargetAfter(caller_graph_, call_, NULL);
|
||||
false_block->LinkTo(call_->next());
|
||||
call_block->ReplaceAsPredecessorWith(false_block);
|
||||
|
||||
|
||||
@@ -1653,7 +1653,10 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
ReturnInstr* fallback_return =
|
||||
new ReturnInstr(call_->instance_call()->token_pos(),
|
||||
new Value(fallback_call));
|
||||
fallback_return->InheritDeoptTargetAfter(isolate(), call_);
|
||||
fallback_return->InheritDeoptTargetAfter(
|
||||
owner_->caller_graph(),
|
||||
call_,
|
||||
fallback_call);
|
||||
AppendInstruction(AppendInstruction(cursor, fallback_call),
|
||||
fallback_return);
|
||||
exit_collector_->AddExit(fallback_return);
|
||||
|
||||
@@ -739,11 +739,17 @@ void Instruction::UnuseAllInputs() {
|
||||
}
|
||||
|
||||
|
||||
void Instruction::InheritDeoptTargetAfter(Isolate* isolate,
|
||||
Instruction* other) {
|
||||
ASSERT(other->env() != NULL);
|
||||
deopt_id_ = Isolate::ToDeoptAfter(other->deopt_id_);
|
||||
other->env()->DeepCopyTo(isolate, this);
|
||||
void Instruction::InheritDeoptTargetAfter(FlowGraph* flow_graph,
|
||||
Definition* call,
|
||||
Definition* result) {
|
||||
ASSERT(call->env() != NULL);
|
||||
deopt_id_ = Isolate::ToDeoptAfter(call->deopt_id_);
|
||||
call->env()->DeepCopyAfterTo(flow_graph->isolate(),
|
||||
this,
|
||||
call->ArgumentCount(),
|
||||
flow_graph->constant_dead(),
|
||||
result != NULL ? result
|
||||
: flow_graph->constant_dead());
|
||||
env()->set_deopt_id(deopt_id_);
|
||||
}
|
||||
|
||||
@@ -3027,6 +3033,29 @@ void Environment::DeepCopyTo(Isolate* isolate, Instruction* instr) const {
|
||||
}
|
||||
|
||||
|
||||
void Environment::DeepCopyAfterTo(Isolate* isolate,
|
||||
Instruction* instr,
|
||||
intptr_t argc,
|
||||
Definition* dead,
|
||||
Definition* result) const {
|
||||
for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
|
||||
it.CurrentValue()->RemoveFromUseList();
|
||||
}
|
||||
|
||||
Environment* copy = DeepCopy(isolate, values_.length() - argc);
|
||||
for (intptr_t i = 0; i < argc; i++) {
|
||||
copy->values_.Add(new(isolate) Value(dead));
|
||||
}
|
||||
copy->values_.Add(new(isolate) Value(result));
|
||||
|
||||
instr->SetEnvironment(copy);
|
||||
for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
|
||||
Value* value = it.CurrentValue();
|
||||
value->definition()->AddEnvUse(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Copies the environment as outer on an inlined instruction and updates the
|
||||
// environment use lists.
|
||||
void Environment::DeepCopyToOuter(Isolate* isolate, Instruction* instr) const {
|
||||
|
||||
@@ -840,7 +840,9 @@ FOR_EACH_ABSTRACT_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
|
||||
return false;
|
||||
}
|
||||
|
||||
void InheritDeoptTargetAfter(Isolate* isolate, Instruction* other);
|
||||
void InheritDeoptTargetAfter(FlowGraph* flow_graph,
|
||||
Definition* call,
|
||||
Definition* result);
|
||||
|
||||
virtual bool MayThrow() const = 0;
|
||||
|
||||
@@ -7910,6 +7912,12 @@ class Environment : public ZoneAllocated {
|
||||
void DeepCopyTo(Isolate* isolate, Instruction* instr) const;
|
||||
void DeepCopyToOuter(Isolate* isolate, Instruction* instr) const;
|
||||
|
||||
void DeepCopyAfterTo(Isolate* isolate,
|
||||
Instruction* instr,
|
||||
intptr_t argc,
|
||||
Definition* dead,
|
||||
Definition* result) const;
|
||||
|
||||
void PrintTo(BufferFormatter* f) const;
|
||||
const char* ToCString() const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user