Index: src/wasm/ast-decoder.cc |
diff --git a/src/wasm/ast-decoder.cc b/src/wasm/ast-decoder.cc |
index 3d45476192926aea55218a602a6ea63805e559e1..4795f84e7a8440ab3c57d0782a87090e8dd54c8e 100644 |
--- a/src/wasm/ast-decoder.cc |
+++ b/src/wasm/ast-decoder.cc |
@@ -68,54 +68,43 @@ struct Value { |
LocalType type; |
}; |
-// An entry on the control stack (i.e. if, block, loop). |
+struct Control; |
+ |
+// An entry on the control stack (i.e. if, block, loop, try). |
struct Control { |
const byte* pc; |
- int stack_depth; // stack height at the beginning of the construct. |
- SsaEnv* end_env; // end environment for the construct. |
- SsaEnv* false_env; // false environment (only for if). |
- SsaEnv* catch_env; // catch environment (only for try with catch). |
- SsaEnv* finish_try_env; // the environment where a try with finally lives. |
- TFNode* node; // result node for the construct. |
- LocalType type; // result type for the construct. |
- bool is_loop; // true if this is the inner label of a loop. |
+ int stack_depth; // stack height at the beginning of the construct. |
+ SsaEnv* end_env; // end environment for the construct. |
+ SsaEnv* false_env; // false environment (only for if). |
+ SsaEnv* catch_env; // catch environment (only for try). |
+ TFNode* node; // result node for the construct. |
+ LocalType type; // result type for the construct. |
+ bool is_loop; // true if this is the inner label of a loop. |
bool is_if() const { return *pc == kExprIf; } |
- bool is_try() const { |
- return *pc == kExprTryCatch || *pc == kExprTryCatchFinally || |
- *pc == kExprTryFinally; |
- } |
- |
- bool has_catch() const { |
- return *pc == kExprTryCatch || *pc == kExprTryCatchFinally; |
- } |
- |
- bool has_finally() const { |
- return *pc == kExprTryCatchFinally || *pc == kExprTryFinally; |
- } |
+ bool is_try() const { return *pc == kExprTry; } |
// Named constructors. |
static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env) { |
- return {pc, stack_depth, end_env, nullptr, nullptr, |
+ return {pc, stack_depth, end_env, nullptr, |
nullptr, nullptr, kAstEnd, false}; |
} |
static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, |
SsaEnv* false_env) { |
- return {pc, stack_depth, end_env, false_env, nullptr, |
+ return {pc, stack_depth, end_env, false_env, |
nullptr, nullptr, kAstStmt, false}; |
} |
static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env) { |
- return {pc, stack_depth, end_env, nullptr, nullptr, |
- nullptr, nullptr, kAstEnd, true}; |
+ return {pc, stack_depth, end_env, nullptr, nullptr, nullptr, kAstEnd, true}; |
} |
static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, |
- SsaEnv* catch_env, SsaEnv* finish_try_env) { |
- return {pc, stack_depth, end_env, nullptr, catch_env, finish_try_env, |
- nullptr, kAstEnd, false}; |
+ SsaEnv* catch_env) { |
+ return {pc, stack_depth, end_env, nullptr, |
+ catch_env, nullptr, kAstEnd, false}; |
} |
}; |
@@ -288,10 +277,7 @@ class WasmDecoder : public Decoder { |
case kExprEnd: |
case kExprBlock: |
case kExprThrow: |
- case kExprTryCatch: |
- case kExprTryCatchFinally: |
- case kExprTryFinally: |
- case kExprFinally: |
+ case kExprTry: |
case kExprLoop: |
return 0; |
@@ -686,32 +672,13 @@ class WasmFullDecoder : public WasmDecoder { |
// TODO(jpp): start exception propagation. |
break; |
} |
- case kExprTryCatch: { |
- CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
- SsaEnv* outer_env = ssa_env_; |
- SsaEnv* try_env = Steal(outer_env); |
- SsaEnv* catch_env = Split(try_env); |
- PushTry(outer_env, catch_env, nullptr); |
- SetEnv("try_catch:start", try_env); |
- break; |
- } |
- case kExprTryCatchFinally: { |
+ case kExprTry: { |
CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
SsaEnv* outer_env = ssa_env_; |
SsaEnv* try_env = Steal(outer_env); |
SsaEnv* catch_env = Split(try_env); |
- SsaEnv* finally_env = Split(try_env); |
- PushTry(finally_env, catch_env, outer_env); |
- SetEnv("try_catch_finally:start", try_env); |
- break; |
- } |
- case kExprTryFinally: { |
- CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
- SsaEnv* outer_env = ssa_env_; |
- SsaEnv* try_env = Steal(outer_env); |
- SsaEnv* finally_env = Split(outer_env); |
- PushTry(finally_env, nullptr, outer_env); |
- SetEnv("try_finally:start", try_env); |
+ PushTry(outer_env, catch_env); |
+ SetEnv("try:start", try_env); |
break; |
} |
case kExprCatch: { |
@@ -725,8 +692,8 @@ class WasmFullDecoder : public WasmDecoder { |
} |
Control* c = &control_.back(); |
- if (!c->has_catch()) { |
- error(pc_, "catch does not match a try with catch"); |
+ if (!c->is_try()) { |
+ error(pc_, "catch does not match a try"); |
break; |
} |
@@ -753,50 +720,6 @@ class WasmFullDecoder : public WasmDecoder { |
break; |
} |
- case kExprFinally: { |
- CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
- if (control_.empty()) { |
- error(pc_, "finally does not match a any try"); |
- break; |
- } |
- |
- Control* c = &control_.back(); |
- if (c->has_catch() && c->catch_env != nullptr) { |
- error(pc_, "missing catch for try with catch and finally"); |
- break; |
- } |
- |
- if (!c->has_finally()) { |
- error(pc_, "finally does not match a try with finally"); |
- break; |
- } |
- |
- if (c->finish_try_env == nullptr) { |
- error(pc_, "finally already present for try with finally"); |
- break; |
- } |
- |
- // ssa_env_ is either the env for either the try or the catch, but |
- // it does not matter: either way we need to direct the control flow |
- // to the end_env, which is the env for the finally. |
- // c->finish_try_env is the the environment enclosing the try block. |
- Goto(ssa_env_, c->end_env); |
- |
- PopUpTo(c->stack_depth); |
- |
- // The current environment becomes end_env, and finish_try_env |
- // becomes the new end_env. This ensures that any control flow |
- // leaving a try block up to now will do so by branching to the |
- // finally block. Setting the end_env to be finish_try_env ensures |
- // that kExprEnd below can handle the try block as it would any |
- // other block construct. |
- SsaEnv* finally_env = c->end_env; |
- c->end_env = c->finish_try_env; |
- SetEnv("finally:begin", finally_env); |
- c->finish_try_env = nullptr; |
- |
- break; |
- } |
case kExprLoop: { |
// The break environment is the outer environment. |
SsaEnv* break_env = ssa_env_; |
@@ -847,7 +770,7 @@ class WasmFullDecoder : public WasmDecoder { |
} |
case kExprEnd: { |
if (control_.empty()) { |
- error(pc_, "end does not match any if or block"); |
+ error(pc_, "end does not match any if, try, or block"); |
break; |
} |
const char* name = "block:end"; |
@@ -855,7 +778,7 @@ class WasmFullDecoder : public WasmDecoder { |
Value val = PopUpTo(c->stack_depth); |
if (c->is_loop) { |
// Loops always push control in pairs. |
- control_.pop_back(); |
+ PopControl(); |
c = &control_.back(); |
name = "loop:end"; |
} else if (c->is_if()) { |
@@ -871,28 +794,21 @@ class WasmFullDecoder : public WasmDecoder { |
} else if (c->is_try()) { |
name = "try:end"; |
- // try blocks do not yield a value. |
- val = {val.pc, nullptr, kAstStmt}; |
- |
- // validate that catch/finally were seen. |
+ // validate that catch was seen. |
if (c->catch_env != nullptr) { |
- error(pc_, "missing catch in try with catch"); |
- break; |
- } |
- |
- if (c->finish_try_env != nullptr) { |
- error(pc_, "missing finally in try with finally"); |
+ error(pc_, "missing catch in try"); |
break; |
} |
} |
if (ssa_env_->go()) { |
+ // Adds a fallthrough edge to the next control block. |
MergeInto(c->end_env, &c->node, &c->type, val); |
} |
SetEnv(name, c->end_env); |
stack_.resize(c->stack_depth); |
Push(c->type, c->node); |
- control_.pop_back(); |
+ PopControl(); |
break; |
} |
case kExprSelect: { |
@@ -1293,12 +1209,13 @@ class WasmFullDecoder : public WasmDecoder { |
control_.emplace_back(Control::If(pc_, stack_depth, end_env, false_env)); |
} |
- void PushTry(SsaEnv* end_env, SsaEnv* catch_env, SsaEnv* finish_try_env) { |
+ void PushTry(SsaEnv* end_env, SsaEnv* catch_env) { |
const int stack_depth = static_cast<int>(stack_.size()); |
- control_.emplace_back( |
- Control::Try(pc_, stack_depth, end_env, catch_env, finish_try_env)); |
+ control_.emplace_back(Control::Try(pc_, stack_depth, end_env, catch_env)); |
} |
+ void PopControl() { control_.pop_back(); } |
+ |
int DecodeLoadMem(LocalType type, MachineType mem_type) { |
MemoryAccessOperand operand(this, pc_, |
ElementSizeLog2Of(mem_type.representation())); |
@@ -1419,7 +1336,7 @@ class WasmFullDecoder : public WasmDecoder { |
int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } |
- void BreakTo(Control* block, Value& val) { |
+ void BreakTo(Control* block, const Value& val) { |
if (block->is_loop) { |
// This is the inner loop block, which does not have a value. |
Goto(ssa_env_, block->end_env); |
@@ -1429,7 +1346,8 @@ class WasmFullDecoder : public WasmDecoder { |
} |
} |
- void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, Value& val) { |
+ void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, |
+ const Value& val) { |
if (!ssa_env_->go()) return; |
DCHECK_NE(kAstEnd, val.type); |
@@ -1674,9 +1592,7 @@ class WasmFullDecoder : public WasmDecoder { |
case kExprLoop: |
case kExprIf: |
case kExprBlock: |
- case kExprTryCatch: |
- case kExprTryCatchFinally: |
- case kExprTryFinally: |
+ case kExprTry: |
depth++; |
DCHECK_EQ(1, OpcodeLength(pc)); |
break; |
@@ -1847,9 +1763,7 @@ bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body, |
case kExprElse: |
case kExprLoop: |
case kExprBlock: |
- case kExprTryCatch: |
- case kExprTryCatchFinally: |
- case kExprTryFinally: |
+ case kExprTry: |
os << " // @" << i.pc_offset(); |
control_depth++; |
break; |