| 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;
|
|
|