summaryrefslogtreecommitdiff
path: root/deps/v8/src/wasm/function-body-decoder-impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/wasm/function-body-decoder-impl.h')
-rw-r--r--deps/v8/src/wasm/function-body-decoder-impl.h90
1 files changed, 58 insertions, 32 deletions
diff --git a/deps/v8/src/wasm/function-body-decoder-impl.h b/deps/v8/src/wasm/function-body-decoder-impl.h
index 04d918b0a4..98aad07fcb 100644
--- a/deps/v8/src/wasm/function-body-decoder-impl.h
+++ b/deps/v8/src/wasm/function-body-decoder-impl.h
@@ -37,6 +37,12 @@ struct WasmException;
return true; \
}())
+#define RET_ON_PROTOTYPE_OPCODE(flag) \
+ DCHECK(!this->module_ || !this->module_->is_asm_js()); \
+ if (!FLAG_experimental_wasm_##flag) { \
+ this->error("Invalid opcode (enable with --experimental-wasm-" #flag ")"); \
+ }
+
#define CHECK_PROTOTYPE_OPCODE(flag) \
DCHECK(!this->module_ || !this->module_->is_asm_js()); \
if (!FLAG_experimental_wasm_##flag) { \
@@ -50,25 +56,25 @@ struct WasmException;
#define ATOMIC_OP_LIST(V) \
V(I32AtomicLoad, Uint32) \
- V(I32AtomicAdd, Uint32) \
- V(I32AtomicSub, Uint32) \
- V(I32AtomicAnd, Uint32) \
- V(I32AtomicOr, Uint32) \
- V(I32AtomicXor, Uint32) \
- V(I32AtomicExchange, Uint32) \
V(I32AtomicLoad8U, Uint8) \
- V(I32AtomicAdd8U, Uint8) \
- V(I32AtomicSub8U, Uint8) \
- V(I32AtomicAnd8U, Uint8) \
- V(I32AtomicOr8U, Uint8) \
- V(I32AtomicXor8U, Uint8) \
- V(I32AtomicExchange8U, Uint8) \
V(I32AtomicLoad16U, Uint16) \
+ V(I32AtomicAdd, Uint32) \
+ V(I32AtomicAdd8U, Uint8) \
V(I32AtomicAdd16U, Uint16) \
+ V(I32AtomicSub, Uint32) \
+ V(I32AtomicSub8U, Uint8) \
V(I32AtomicSub16U, Uint16) \
+ V(I32AtomicAnd, Uint32) \
+ V(I32AtomicAnd8U, Uint8) \
V(I32AtomicAnd16U, Uint16) \
+ V(I32AtomicOr, Uint32) \
+ V(I32AtomicOr8U, Uint8) \
V(I32AtomicOr16U, Uint16) \
+ V(I32AtomicXor, Uint32) \
+ V(I32AtomicXor8U, Uint8) \
V(I32AtomicXor16U, Uint16) \
+ V(I32AtomicExchange, Uint32) \
+ V(I32AtomicExchange8U, Uint8) \
V(I32AtomicExchange16U, Uint16) \
V(I32AtomicCompareExchange, Uint32) \
V(I32AtomicCompareExchange8U, Uint8) \
@@ -246,12 +252,12 @@ struct BreakDepthOperand {
template <Decoder::ValidateFlag validate>
struct CallIndirectOperand {
uint32_t table_index;
- uint32_t index;
+ uint32_t sig_index;
FunctionSig* sig = nullptr;
unsigned length = 0;
inline CallIndirectOperand(Decoder* decoder, const byte* pc) {
unsigned len = 0;
- index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
+ sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
if (!VALIDATE(decoder->ok())) return;
table_index = decoder->read_u8<validate>(pc + 1 + len, "table index");
if (!VALIDATE(table_index == 0)) {
@@ -648,7 +654,8 @@ class WasmDecoder : public Decoder {
uint32_t count = decoder->consume_u32v("local count");
if (decoder->failed()) return false;
- if ((count + type_list->size()) > kV8MaxWasmFunctionLocals) {
+ DCHECK_LE(type_list->size(), kV8MaxWasmFunctionLocals);
+ if (count > kV8MaxWasmFunctionLocals - type_list->size()) {
decoder->error(decoder->pc() - 1, "local count too large");
return false;
}
@@ -674,7 +681,7 @@ class WasmDecoder : public Decoder {
type = kWasmS128;
break;
}
- // else fall through to default.
+ V8_FALLTHROUGH;
default:
decoder->error(decoder->pc() - 1, "invalid local type");
return false;
@@ -789,10 +796,10 @@ class WasmDecoder : public Decoder {
inline bool Complete(const byte* pc, CallIndirectOperand<validate>& operand) {
if (!VALIDATE(module_ != nullptr &&
- operand.index < module_->signatures.size())) {
+ operand.sig_index < module_->signatures.size())) {
return false;
}
- operand.sig = module_->signatures[operand.index];
+ operand.sig = module_->signatures[operand.sig_index];
return true;
}
@@ -802,7 +809,7 @@ class WasmDecoder : public Decoder {
return false;
}
if (!Complete(pc, operand)) {
- errorf(pc + 1, "invalid signature index: #%u", operand.index);
+ errorf(pc + 1, "invalid signature index: #%u", operand.sig_index);
return false;
}
return true;
@@ -1097,6 +1104,7 @@ class WasmDecoder : public Decoder {
}
}
}
+ V8_FALLTHROUGH;
}
default:
V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
@@ -1534,8 +1542,10 @@ class WasmFullDecoder : public WasmDecoder<validate> {
if (!this->Validate(this->pc_, operand, control_.size())) break;
Control* c = control_at(operand.depth);
if (!TypeCheckBreak(c)) break;
- CALL_INTERFACE_IF_REACHABLE(Br, c);
- BreakTo(c);
+ if (control_.back().reachable()) {
+ CALL_INTERFACE(Br, c);
+ c->br_merge()->reached = true;
+ }
len = 1 + operand.length;
EndControl();
break;
@@ -1543,28 +1553,38 @@ class WasmFullDecoder : public WasmDecoder<validate> {
case kExprBrIf: {
BreakDepthOperand<validate> operand(this, this->pc_);
auto cond = Pop(0, kWasmI32);
+ if (this->failed()) break;
if (!this->Validate(this->pc_, operand, control_.size())) break;
Control* c = control_at(operand.depth);
if (!TypeCheckBreak(c)) break;
- CALL_INTERFACE_IF_REACHABLE(BrIf, cond, c);
- BreakTo(c);
+ if (control_.back().reachable()) {
+ CALL_INTERFACE(BrIf, cond, c);
+ c->br_merge()->reached = true;
+ }
len = 1 + operand.length;
break;
}
case kExprBrTable: {
BranchTableOperand<validate> operand(this, this->pc_);
BranchTableIterator<validate> iterator(this, operand);
- if (!this->Validate(this->pc_, operand, control_.size())) break;
auto key = Pop(0, kWasmI32);
+ if (this->failed()) break;
+ if (!this->Validate(this->pc_, operand, control_.size())) break;
uint32_t br_arity = 0;
+ std::vector<bool> br_targets(control_.size());
while (iterator.has_next()) {
const uint32_t i = iterator.cur_index();
const byte* pos = iterator.pc();
uint32_t target = iterator.next();
if (!VALIDATE(target < control_.size())) {
- this->error(pos, "improper branch in br_table");
+ this->errorf(pos,
+ "improper branch in br_table target %u (depth %u)",
+ i, target);
break;
}
+ // Avoid redundant break target checks.
+ if (br_targets[target]) continue;
+ br_targets[target] = true;
// Check that label types match up.
Control* c = control_at(target);
uint32_t arity = c->br_merge()->arity;
@@ -1572,15 +1592,22 @@ class WasmFullDecoder : public WasmDecoder<validate> {
br_arity = arity;
} else if (!VALIDATE(br_arity == arity)) {
this->errorf(pos,
- "inconsistent arity in br_table target %d"
+ "inconsistent arity in br_table target %u"
" (previous was %u, this one %u)",
i, br_arity, arity);
}
if (!TypeCheckBreak(c)) break;
- BreakTo(c);
}
+ if (this->failed()) break;
+
+ if (control_.back().reachable()) {
+ CALL_INTERFACE(BrTable, operand, key);
- CALL_INTERFACE_IF_REACHABLE(BrTable, operand, key);
+ for (uint32_t depth = control_depth(); depth-- > 0;) {
+ if (!br_targets[depth]) continue;
+ control_at(depth)->br_merge()->reached = true;
+ }
+ }
len = 1 + iterator.length();
EndControl();
@@ -2249,10 +2276,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
- inline void BreakTo(Control* c) {
- if (control_.back().reachable()) c->br_merge()->reached = true;
- }
-
void FallThruTo(Control* c) {
DCHECK_EQ(c, &control_.back());
if (!TypeCheckFallThru(c)) return;
@@ -2344,6 +2367,9 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
+ if (WasmOpcodes::IsSignExtensionOpcode(opcode)) {
+ RET_ON_PROTOTYPE_OPCODE(se);
+ }
switch (sig->parameter_count()) {
case 1: {
auto val = Pop(0, sig->GetParam(0));