Commit 7d07a6c4 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[interpreter] Deprecate notion of an unreachable environment.

The notion of an unreachable environment is useful for a recursive
descent iteration (e.g. over an AST) where nodes are created on the
ascent path as well. For a flat iteration (e.g. over bytecode stream)
environments become unreachable at the end of a visitation function.
Hence any unreachable path can be represented by nulling the tracked
environment completely. This further reduces the number of redundant
nodes being created.

R=oth@chromium.org

Review URL: https://codereview.chromium.org/1650483003

Cr-Commit-Position: refs/heads/master@{#33639}
parent d81edba7
......@@ -37,9 +37,6 @@ class BytecodeGraphBuilder::Environment : public ZoneObject {
FrameStateBeforeAndAfter* states = nullptr);
void RecordAfterState(Node* node, FrameStateBeforeAndAfter* states);
bool IsMarkedAsUnreachable() const;
void MarkAsUnreachable();
// Effect dependency tracked by this environment.
Node* GetEffectDependency() { return effect_dependency_; }
void UpdateEffectDependency(Node* dependency) {
......@@ -307,16 +304,6 @@ void BytecodeGraphBuilder::Environment::RecordAfterState(
}
bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const {
return GetControlDependency()->opcode() == IrOpcode::kDead;
}
void BytecodeGraphBuilder::Environment::MarkAsUnreachable() {
UpdateControlDependency(builder()->jsgraph()->Dead());
}
BytecodeGraphBuilder::Environment*
BytecodeGraphBuilder::Environment::CopyForLoop() {
PrepareForLoop();
......@@ -332,11 +319,6 @@ BytecodeGraphBuilder::Environment::CopyForConditional() const {
void BytecodeGraphBuilder::Environment::Merge(
BytecodeGraphBuilder::Environment* other) {
// Nothing to do if the other environment is dead.
if (other->IsMarkedAsUnreachable()) {
return;
}
// Create a merge of the control dependencies of both environments and update
// the current environment's control dependency accordingly.
Node* control = builder()->MergeControl(GetControlDependency(),
......@@ -1256,22 +1238,25 @@ void BytecodeGraphBuilder::VisitNew() { BuildCallConstruct(); }
void BytecodeGraphBuilder::VisitNewWide() { BuildCallConstruct(); }
void BytecodeGraphBuilder::VisitThrow() {
void BytecodeGraphBuilder::BuildThrowOp(const Operator* call_op) {
FrameStateBeforeAndAfter states(this);
Node* value = environment()->LookupAccumulator();
Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value);
Node* call = NewNode(call_op, value);
environment()->RecordAfterState(call, &states);
Node* control = NewNode(common()->Throw(), value);
UpdateControlDependencyToLeaveFunction(control);
}
void BytecodeGraphBuilder::VisitThrow() {
BuildThrowOp(javascript()->CallRuntime(Runtime::kThrow));
Node* control =
NewNode(common()->Throw(), environment()->LookupAccumulator());
MergeControlToLeaveFunction(control);
}
void BytecodeGraphBuilder::VisitReThrow() {
FrameStateBeforeAndAfter states(this);
Node* value = environment()->LookupAccumulator();
Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value);
environment()->RecordAfterState(call, &states);
Node* control = NewNode(common()->Throw(), value);
UpdateControlDependencyToLeaveFunction(control);
BuildThrowOp(javascript()->CallRuntime(Runtime::kReThrow));
Node* control =
NewNode(common()->Throw(), environment()->LookupAccumulator());
MergeControlToLeaveFunction(control);
}
void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) {
......@@ -1546,8 +1531,7 @@ void BytecodeGraphBuilder::VisitJumpIfUndefinedConstantWide() {
void BytecodeGraphBuilder::VisitReturn() {
Node* control =
NewNode(common()->Return(), environment()->LookupAccumulator());
UpdateControlDependencyToLeaveFunction(control);
set_environment(nullptr);
MergeControlToLeaveFunction(control);
}
void BytecodeGraphBuilder::BuildForInPrepare() {
......@@ -1632,6 +1616,10 @@ void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) {
set_environment(nullptr);
}
void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) {
exit_controls_.push_back(exit);
set_environment(nullptr);
}
void BytecodeGraphBuilder::BuildJump() {
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
......@@ -1747,36 +1735,34 @@ Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
*current_input++ = environment()->GetControlDependency();
}
result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
if (!environment()->IsMarkedAsUnreachable()) {
// Update the current control dependency for control-producing nodes.
if (NodeProperties::IsControl(result)) {
environment()->UpdateControlDependency(result);
}
// Update the current effect dependency for effect-producing nodes.
if (result->op()->EffectOutputCount() > 0) {
environment()->UpdateEffectDependency(result);
}
// Add implicit exception continuation for throwing nodes.
if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
int handler_offset = exception_handlers_.top().handler_offset_;
// TODO(mstarzinger): Thread through correct prediction!
IfExceptionHint hint = IfExceptionHint::kLocallyCaught;
Environment* success_env = environment()->CopyForConditional();
const Operator* op = common()->IfException(hint);
Node* effect = environment()->GetEffectDependency();
Node* on_exception = graph()->NewNode(op, effect, result);
environment()->UpdateControlDependency(on_exception);
environment()->UpdateEffectDependency(on_exception);
environment()->BindAccumulator(on_exception);
MergeIntoSuccessorEnvironment(handler_offset);
set_environment(success_env);
}
// Add implicit success continuation for throwing nodes.
if (!result->op()->HasProperty(Operator::kNoThrow)) {
const Operator* if_success = common()->IfSuccess();
Node* on_success = graph()->NewNode(if_success, result);
environment()->UpdateControlDependency(on_success);
}
// Update the current control dependency for control-producing nodes.
if (NodeProperties::IsControl(result)) {
environment()->UpdateControlDependency(result);
}
// Update the current effect dependency for effect-producing nodes.
if (result->op()->EffectOutputCount() > 0) {
environment()->UpdateEffectDependency(result);
}
// Add implicit exception continuation for throwing nodes.
if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
int handler_offset = exception_handlers_.top().handler_offset_;
// TODO(mstarzinger): Thread through correct prediction!
IfExceptionHint hint = IfExceptionHint::kLocallyCaught;
Environment* success_env = environment()->CopyForConditional();
const Operator* op = common()->IfException(hint);
Node* effect = environment()->GetEffectDependency();
Node* on_exception = graph()->NewNode(op, effect, result);
environment()->UpdateControlDependency(on_exception);
environment()->UpdateEffectDependency(on_exception);
environment()->BindAccumulator(on_exception);
MergeIntoSuccessorEnvironment(handler_offset);
set_environment(success_env);
}
// Add implicit success continuation for throwing nodes.
if (!result->op()->HasProperty(Operator::kNoThrow)) {
const Operator* if_success = common()->IfSuccess();
Node* on_success = graph()->NewNode(if_success, result);
environment()->UpdateControlDependency(on_success);
}
}
......@@ -1859,13 +1845,6 @@ Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
return value;
}
void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
if (environment()->IsMarkedAsUnreachable()) return;
environment()->MarkAsUnreachable();
exit_controls_.push_back(exit);
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -107,9 +107,6 @@ class BytecodeGraphBuilder {
Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs,
bool incomplete);
// Helper to indicate a node exits the function body.
void UpdateControlDependencyToLeaveFunction(Node* exit);
Node** EnsureInputBufferSize(int size);
Node* ProcessCallArguments(const Operator* call_op, Node* callee,
......@@ -139,10 +136,11 @@ class BytecodeGraphBuilder {
void BuildCallRuntime();
void BuildCallRuntimeForPair();
void BuildCallConstruct();
void BuildThrowOp(const Operator* op);
void BuildBinaryOp(const Operator* op);
void BuildCompareOp(const Operator* op);
void BuildDelete();
void BuildCastOperator(const Operator* js_op);
void BuildCastOperator(const Operator* op);
void BuildForInPrepare();
void BuildForInNext();
......@@ -157,6 +155,9 @@ class BytecodeGraphBuilder {
void BuildLoopHeaderEnvironment(int current_offset);
void SwitchToMergeEnvironment(int current_offset);
// Simulates control flow that exits the function body.
void MergeControlToLeaveFunction(Node* exit);
// Simulates entry and exit of exception handlers.
void EnterAndExitExceptionHandlers(int current_offset);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment