Commit 83a2c8ed authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[interpreter] Reachability is implied by live environment.

The reachability of a bytecode is implied by a live environment reaching
the bytecode during the abstract control flow simulation of the bytecode
iteration perfromed by the graph builder. There is no need to compute it
upfront anymore.

Also, the upfront computation was only an approximation when it came to
the reachability of an exception handler. This is why several tests for
translation of exception handlers can now be enabled.

R=oth@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#33634}
parent ee5b58d9
......@@ -49,41 +49,16 @@ BytecodeBranchAnalysis::BytecodeBranchAnalysis(
Handle<BytecodeArray> bytecode_array, Zone* zone)
: branch_infos_(zone),
bytecode_array_(bytecode_array),
reachable_(bytecode_array->length(), zone),
zone_(zone) {}
void BytecodeBranchAnalysis::Analyze() {
interpreter::BytecodeArrayIterator iterator(bytecode_array());
AnalyzeExceptionHandlers();
bool reachable = true;
while (!iterator.done()) {
interpreter::Bytecode bytecode = iterator.current_bytecode();
int current_offset = iterator.current_offset();
// All bytecode basic blocks are generated to be forward reachable
// and may also be backward reachable. Hence if there's a forward
// branch targetting here the code becomes reachable.
reachable = reachable || forward_branches_target(current_offset);
// Some bytecode basic blocks are reachable through a side-entry
// (e.g. exception handler), which has been represented in the
// bit-vector by a corresponding pre-pass.
reachable = reachable || reachable_.Contains(current_offset);
if (reachable) {
reachable_.Add(current_offset);
if (interpreter::Bytecodes::IsConditionalJump(bytecode)) {
// Only the branch is recorded, the forward path falls through
// and is handled as normal bytecode data flow.
AddBranch(current_offset, iterator.GetJumpTargetOffset());
} else if (interpreter::Bytecodes::IsJump(bytecode)) {
// Unless the branch targets the next bytecode it's not
// reachable. If it targets the next bytecode the check at the
// start of the loop will set the reachable flag.
AddBranch(current_offset, iterator.GetJumpTargetOffset());
reachable = false;
} else if (interpreter::Bytecodes::IsJumpOrReturn(bytecode)) {
DCHECK_EQ(bytecode, interpreter::Bytecode::kReturn);
reachable = false;
}
if (interpreter::Bytecodes::IsJump(bytecode)) {
AddBranch(current_offset, iterator.GetJumpTargetOffset());
}
iterator.Advance();
}
......@@ -123,13 +98,6 @@ void BytecodeBranchAnalysis::AddBranch(int source_offset, int target_offset) {
branch_info->AddBranch(source_offset, target_offset);
}
void BytecodeBranchAnalysis::AnalyzeExceptionHandlers() {
HandlerTable* table = HandlerTable::cast(bytecode_array()->handler_table());
for (int i = 0; i < table->NumberOfRangeEntries(); ++i) {
reachable_.Add(table->GetRangeHandler(i));
}
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -19,9 +19,9 @@ namespace compiler {
class BytecodeBranchInfo;
// A class for identifying the branch targets and their branch sites
// within a bytecode array and also identifying which bytecodes are
// reachable. This information can be used to construct the local
// control flow logic for high-level IR graphs built from bytecode.
// within a bytecode array. This information can be used to construct
// the local control flow logic for high-level IR graphs built from
// bytecode.
//
// NB This class relies on the only backwards branches in bytecode
// being jumps back to loop headers.
......@@ -34,9 +34,6 @@ class BytecodeBranchAnalysis BASE_EMBEDDED {
// until this has been called.
void Analyze();
// Returns true if the bytecode at |offset| is reachable.
bool is_reachable(int offset) const { return reachable_.Contains(offset); }
// Returns true if there are any forward branches to the bytecode at
// |offset|.
bool forward_branches_target(int offset) const {
......@@ -53,7 +50,6 @@ class BytecodeBranchAnalysis BASE_EMBEDDED {
private:
void AddBranch(int origin_offset, int target_offset);
void AnalyzeExceptionHandlers();
// Offsets of bytecodes having a backward branch to the bytecode at |offset|.
const ZoneVector<int>* BackwardBranchesTargetting(int offset) const;
......@@ -66,7 +62,6 @@ class BytecodeBranchAnalysis BASE_EMBEDDED {
ZoneMap<int, BytecodeBranchInfo*> branch_infos_;
Handle<BytecodeArray> bytecode_array_;
BitVector reachable_;
Zone* zone_;
DISALLOW_COPY_AND_ASSIGN(BytecodeBranchAnalysis);
......
......@@ -615,9 +615,9 @@ void BytecodeGraphBuilder::VisitBytecodes() {
set_bytecode_iterator(&iterator);
while (!iterator.done()) {
int current_offset = iterator.current_offset();
if (analysis.is_reachable(current_offset)) {
EnterAndExitExceptionHandlers(current_offset);
SwitchToMergeEnvironment(current_offset);
EnterAndExitExceptionHandlers(current_offset);
SwitchToMergeEnvironment(current_offset);
if (environment() != nullptr) {
BuildLoopHeaderEnvironment(current_offset);
switch (iterator.current_bytecode()) {
......
......@@ -1418,9 +1418,8 @@ TEST(BytecodeGraphBuilderTryCatch) {
Zone* zone = scope.main_zone();
ExpectedSnippet<0> snippets[] = {
// TODO(mstarzinger): Fix cases where nothing throws.
// {"var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
// {handle(Smi::FromInt(2), isolate)}},
{"var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
{handle(Smi::FromInt(2), isolate)}},
{"var a; try { undef.x } catch(e) { a = 2 }; return a;",
{handle(Smi::FromInt(2), isolate)}},
{"var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
......@@ -1451,19 +1450,19 @@ TEST(BytecodeGraphBuilderTryFinally1) {
ExpectedSnippet<0> snippets[] = {
{"var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
{handle(Smi::FromInt(4), isolate)}},
// TODO(mstarzinger): Fix cases where nothing throws.
// {"var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
// {handle(Smi::FromInt(23), isolate)}},
{"var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
{handle(Smi::FromInt(23), isolate)}},
{"var a = 1; try { a = 2; throw 23; } finally { return a; };",
{handle(Smi::FromInt(2), isolate)}},
// {"var a = 1; for (var i = 10; i < 20; i += 5) {"
// " try { a = 2; break; } finally { a = 3; }"
// "} return a + i;",
// {handle(Smi::FromInt(13), isolate)}},
// {"var a = 1; for (var i = 10; i < 20; i += 5) {"
// " try { a = 2; continue; } finally { a = 3; }"
// "} return a + i;",
// {handle(Smi::FromInt(23), isolate)}},
{"var a = 1; for (var i = 10; i < 20; i += 5) {"
" try { a = 2; break; } finally { a = 3; }"
"} return a + i;",
{handle(Smi::FromInt(13), isolate)}},
{"var a = 1; for (var i = 10; i < 20; i += 5) {"
" try { a = 2; continue; } finally { a = 3; }"
"} return a + i;",
{handle(Smi::FromInt(23), isolate)}},
// TODO(mstarzinger): Investigate failure!
// {"var a = 1; try { a = 2;"
// " try { a = 3; throw 23; } finally { a = 4; }"
// "} catch(e) { a = a + e; } return a;",
......
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