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:
vegorov@google.com
2014-12-10 18:32:15 +00:00
parent ec5cdd5c26
commit a34c19ccca
4 changed files with 53 additions and 9 deletions
+6 -2
View File
@@ -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);
+4 -1
View File
@@ -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);
+34 -5
View File
@@ -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 {
+9 -1
View File
@@ -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;