Index: src/wasm/function-body-decoder.cc |
diff --git a/src/wasm/function-body-decoder.cc b/src/wasm/function-body-decoder.cc |
index 86b83c069c1280acda3cf1439f2c91c2706197f0..7c95b5a672300eebed09d0fe7016ddd5f06a8cdb 100644 |
--- a/src/wasm/function-body-decoder.cc |
+++ b/src/wasm/function-body-decoder.cc |
@@ -99,7 +99,7 @@ enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry }; |
struct Control { |
const byte* pc; |
ControlKind kind; |
- int stack_depth; // stack height at the beginning of the construct. |
+ size_t 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). |
TryInfo* try_info; // Information used for compiling try statements. |
@@ -114,25 +114,25 @@ struct Control { |
inline bool is_try() const { return kind == kControlTry; } |
// Named constructors. |
- static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env, |
+ static Control Block(const byte* pc, size_t stack_depth, SsaEnv* end_env, |
int32_t previous_catch) { |
return {pc, kControlBlock, stack_depth, end_env, |
nullptr, nullptr, previous_catch, {0, {NO_VALUE}}}; |
} |
- static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, |
+ static Control If(const byte* pc, size_t stack_depth, SsaEnv* end_env, |
SsaEnv* false_env, int32_t previous_catch) { |
return {pc, kControlIf, stack_depth, end_env, |
false_env, nullptr, previous_catch, {0, {NO_VALUE}}}; |
} |
- static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env, |
+ static Control Loop(const byte* pc, size_t stack_depth, SsaEnv* end_env, |
int32_t previous_catch) { |
return {pc, kControlLoop, stack_depth, end_env, |
nullptr, nullptr, previous_catch, {0, {NO_VALUE}}}; |
} |
- static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, |
+ static Control Try(const byte* pc, size_t stack_depth, SsaEnv* end_env, |
Zone* zone, SsaEnv* catch_env, int32_t previous_catch) { |
DCHECK_NOT_NULL(catch_env); |
TryInfo* try_info = new (zone) TryInfo(catch_env); |
@@ -654,9 +654,7 @@ class WasmFullDecoder : public WasmDecoder { |
} |
} |
- if (pc_ >= end_) return; // Nothing to do. |
- |
- while (true) { // decoding loop. |
+ while (pc_ < end_) { // decoding loop. |
unsigned len = 1; |
WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); |
if (!WasmOpcodes::IsPrefixOpcode(opcode)) { |
@@ -811,8 +809,7 @@ class WasmFullDecoder : public WasmDecoder { |
if (c->false_env != nullptr) { |
// End the true branch of a one-armed if. |
Goto(c->false_env, c->end_env); |
- if (ssa_env_->go() && |
- static_cast<int>(stack_.size()) != c->stack_depth) { |
+ if (ssa_env_->go() && stack_.size() != c->stack_depth) { |
error("end of if expected empty stack"); |
stack_.resize(c->stack_depth); |
} |
@@ -846,12 +843,11 @@ class WasmFullDecoder : public WasmDecoder { |
} |
} |
- PopControl(); |
- |
- if (control_.empty()) { |
- // If the last (implicit) control was popped, check we are at end. |
+ if (control_.size() == 1) { |
+ // If at the last (implicit) control, check we are at end. |
if (pc_ + 1 != end_) { |
error(pc_, pc_ + 1, "trailing code after function end"); |
+ break; |
} |
last_end_found_ = true; |
if (ssa_env_->go()) { |
@@ -860,8 +856,8 @@ class WasmFullDecoder : public WasmDecoder { |
DoReturn(); |
TRACE("\n"); |
} |
- return; |
} |
+ PopControl(); |
break; |
} |
case kExprSelect: { |
@@ -1241,12 +1237,8 @@ class WasmFullDecoder : public WasmDecoder { |
} |
#endif |
pc_ += len; |
- if (pc_ >= end_) { |
- // End of code reached or exceeded. |
- if (pc_ > end_ && ok()) error("Beyond end of code"); |
- return; |
- } |
} // end decode loop |
+ if (pc_ > end_ && ok()) error("Beyond end of code"); |
} |
void EndControl() { ssa_env_->Kill(SsaEnv::kControlEnd); } |
@@ -1286,26 +1278,22 @@ class WasmFullDecoder : public WasmDecoder { |
} |
void PushBlock(SsaEnv* end_env) { |
- const int stack_depth = static_cast<int>(stack_.size()); |
control_.emplace_back( |
- Control::Block(pc_, stack_depth, end_env, current_catch_)); |
+ Control::Block(pc_, stack_.size(), end_env, current_catch_)); |
} |
void PushLoop(SsaEnv* end_env) { |
- const int stack_depth = static_cast<int>(stack_.size()); |
control_.emplace_back( |
- Control::Loop(pc_, stack_depth, end_env, current_catch_)); |
+ Control::Loop(pc_, stack_.size(), end_env, current_catch_)); |
} |
void PushIf(SsaEnv* end_env, SsaEnv* false_env) { |
- const int stack_depth = static_cast<int>(stack_.size()); |
control_.emplace_back( |
- Control::If(pc_, stack_depth, end_env, false_env, current_catch_)); |
+ Control::If(pc_, stack_.size(), end_env, false_env, current_catch_)); |
} |
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, zone_, |
+ control_.emplace_back(Control::Try(pc_, stack_.size(), end_env, zone_, |
catch_env, current_catch_)); |
current_catch_ = static_cast<int32_t>(control_.size() - 1); |
} |
@@ -1431,10 +1419,6 @@ class WasmFullDecoder : public WasmDecoder { |
} |
Value Pop(int index, ValueType expected) { |
- if (!ssa_env_->go()) { |
- // Unreachable code is essentially not typechecked. |
- return {pc_, nullptr, expected}; |
- } |
Value val = Pop(); |
if (val.type != expected) { |
if (val.type != kWasmEnd) { |
@@ -1447,14 +1431,13 @@ class WasmFullDecoder : public WasmDecoder { |
} |
Value Pop() { |
- if (!ssa_env_->go()) { |
- // Unreachable code is essentially not typechecked. |
- return {pc_, nullptr, kWasmEnd}; |
- } |
size_t limit = control_.empty() ? 0 : control_.back().stack_depth; |
if (stack_.size() <= limit) { |
- Value val = {pc_, nullptr, kWasmStmt}; |
- error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_)); |
+ Value val = {pc_, nullptr, kWasmEnd}; |
+ if (ssa_env_->go()) { |
+ // Popping past the current control start in reachable code. |
+ error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_)); |
+ } |
return val; |
} |
Value val = stack_.back(); |
@@ -1462,22 +1445,6 @@ class WasmFullDecoder : public WasmDecoder { |
return val; |
} |
- Value PopUpTo(int stack_depth) { |
- if (!ssa_env_->go()) { |
- // Unreachable code is essentially not typechecked. |
- return {pc_, nullptr, kWasmEnd}; |
- } |
- if (stack_depth == static_cast<int>(stack_.size())) { |
- Value val = {pc_, nullptr, kWasmStmt}; |
- return val; |
- } else { |
- DCHECK_LE(stack_depth, stack_.size()); |
- Value val = Pop(); |
- stack_.resize(stack_depth); |
- return val; |
- } |
- } |
- |
int baserel(const byte* ptr) { |
return base_ ? static_cast<int>(ptr - base_) : 0; |
} |
@@ -1508,7 +1475,7 @@ class WasmFullDecoder : public WasmDecoder { |
if (!ssa_env_->go()) return; |
// Merge the value(s) into the end of the block. |
int arity = static_cast<int>(c->merge.arity); |
- if (c->stack_depth + arity != static_cast<int>(stack_.size())) { |
+ if (c->stack_depth + arity != stack_.size()) { |
error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", |
arity, startrel(c->pc)); |
return; |
@@ -1524,7 +1491,7 @@ class WasmFullDecoder : public WasmDecoder { |
if (!ssa_env_->go()) return; |
// Fallthru must match arity exactly. |
int arity = static_cast<int>(c->merge.arity); |
- if (c->stack_depth + arity != static_cast<int>(stack_.size())) { |
+ if (c->stack_depth + arity != stack_.size()) { |
error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", |
arity, startrel(c->pc)); |
return; |