Index: src/wasm/wasm-interpreter.cc |
diff --git a/src/wasm/wasm-interpreter.cc b/src/wasm/wasm-interpreter.cc |
index d397b6d7f1b046bb1fe31f76a8e3e9b15224cd5b..f80e5947acca7c41fcb0473fcca748971ad77fc6 100644 |
--- a/src/wasm/wasm-interpreter.cc |
+++ b/src/wasm/wasm-interpreter.cc |
@@ -62,8 +62,6 @@ namespace wasm { |
V(I64GtS, int64_t, >) \ |
V(I64GeS, int64_t, >=) \ |
V(F32Add, float, +) \ |
- V(F32Mul, float, *) \ |
- V(F32Div, float, /) \ |
V(F32Eq, float, ==) \ |
V(F32Ne, float, !=) \ |
V(F32Lt, float, <) \ |
@@ -71,8 +69,6 @@ namespace wasm { |
V(F32Gt, float, >) \ |
V(F32Ge, float, >=) \ |
V(F64Add, double, +) \ |
- V(F64Mul, double, *) \ |
- V(F64Div, double, /) \ |
V(F64Eq, double, ==) \ |
V(F64Ne, double, !=) \ |
V(F64Lt, double, <) \ |
@@ -80,6 +76,12 @@ namespace wasm { |
V(F64Gt, double, >) \ |
V(F64Ge, double, >=) |
+#define FOREACH_SIMPLE_BINOP_NAN(V) \ |
+ V(F32Mul, float, *) \ |
+ V(F64Mul, double, *) \ |
+ V(F32Div, float, /) \ |
+ V(F64Div, double, /) |
+ |
#define FOREACH_OTHER_BINOP(V) \ |
V(I32DivS, int32_t) \ |
V(I32DivU, uint32_t) \ |
@@ -127,14 +129,12 @@ namespace wasm { |
V(F32Floor, float) \ |
V(F32Trunc, float) \ |
V(F32NearestInt, float) \ |
- V(F32Sqrt, float) \ |
V(F64Abs, double) \ |
V(F64Neg, double) \ |
V(F64Ceil, double) \ |
V(F64Floor, double) \ |
V(F64Trunc, double) \ |
V(F64NearestInt, double) \ |
- V(F64Sqrt, double) \ |
V(I32SConvertF32, float) \ |
V(I32SConvertF64, double) \ |
V(I32UConvertF32, float) \ |
@@ -165,6 +165,10 @@ namespace wasm { |
V(I32AsmjsSConvertF64, double) \ |
V(I32AsmjsUConvertF64, double) |
+#define FOREACH_OTHER_UNOP_NAN(V) \ |
+ V(F32Sqrt, float) \ |
+ V(F64Sqrt, double) |
+ |
static inline int32_t ExecuteI32DivS(int32_t a, int32_t b, TrapReason* trap) { |
if (b == 0) { |
*trap = kTrapDivByZero; |
@@ -460,7 +464,8 @@ static inline float ExecuteF32NearestInt(float a, TrapReason* trap) { |
} |
static inline float ExecuteF32Sqrt(float a, TrapReason* trap) { |
- return sqrtf(a); |
+ float result = sqrtf(a); |
+ return result; |
} |
static inline double ExecuteF64Abs(double a, TrapReason* trap) { |
@@ -975,7 +980,8 @@ class ThreadImpl : public WasmInterpreter::Thread { |
blocks_(zone), |
state_(WasmInterpreter::STOPPED), |
break_pc_(kInvalidPc), |
- trap_reason_(kTrapCount) {} |
+ trap_reason_(kTrapCount), |
+ possible_nondeterminism_(false) {} |
virtual ~ThreadImpl() {} |
@@ -1030,6 +1036,7 @@ class ThreadImpl : public WasmInterpreter::Thread { |
frames_.clear(); |
state_ = WasmInterpreter::STOPPED; |
trap_reason_ = kTrapCount; |
+ possible_nondeterminism_ = false; |
} |
virtual int GetFrameCount() { return static_cast<int>(frames_.size()); } |
@@ -1053,6 +1060,8 @@ class ThreadImpl : public WasmInterpreter::Thread { |
virtual pc_t GetBreakpointPc() { return break_pc_; } |
+ virtual bool PossibleNondeterminism() { return possible_nondeterminism_; } |
+ |
bool Terminated() { |
return state_ == WasmInterpreter::TRAPPED || |
state_ == WasmInterpreter::FINISHED; |
@@ -1087,6 +1096,7 @@ class ThreadImpl : public WasmInterpreter::Thread { |
WasmInterpreter::State state_; |
pc_t break_pc_; |
TrapReason trap_reason_; |
+ bool possible_nondeterminism_; |
CodeMap* codemap() { return codemap_; } |
WasmInstance* instance() { return instance_; } |
@@ -1602,6 +1612,19 @@ class ThreadImpl : public WasmInterpreter::Thread { |
FOREACH_SIMPLE_BINOP(EXECUTE_SIMPLE_BINOP) |
#undef EXECUTE_SIMPLE_BINOP |
+#define EXECUTE_SIMPLE_BINOP_NAN(name, ctype, op) \ |
+ case kExpr##name: { \ |
+ WasmVal rval = Pop(); \ |
+ WasmVal lval = Pop(); \ |
+ ctype result = lval.to<ctype>() op rval.to<ctype>(); \ |
+ possible_nondeterminism_ |= std::isnan(result); \ |
+ WasmVal result_val(result); \ |
+ Push(pc, result_val); \ |
+ break; \ |
+ } |
+ FOREACH_SIMPLE_BINOP_NAN(EXECUTE_SIMPLE_BINOP_NAN) |
+#undef EXECUTE_SIMPLE_BINOP_NAN |
+ |
#define EXECUTE_OTHER_BINOP(name, ctype) \ |
case kExpr##name: { \ |
TrapReason trap = kTrapCount; \ |
@@ -1627,6 +1650,20 @@ class ThreadImpl : public WasmInterpreter::Thread { |
FOREACH_OTHER_UNOP(EXECUTE_OTHER_UNOP) |
#undef EXECUTE_OTHER_UNOP |
+#define EXECUTE_OTHER_UNOP_NAN(name, ctype) \ |
+ case kExpr##name: { \ |
+ TrapReason trap = kTrapCount; \ |
+ volatile ctype val = Pop().to<ctype>(); \ |
+ ctype result = Execute##name(val, &trap); \ |
+ possible_nondeterminism_ |= std::isnan(result); \ |
+ WasmVal result_val(result); \ |
+ if (trap != kTrapCount) return DoTrap(trap, pc); \ |
+ Push(pc, result_val); \ |
+ break; \ |
+ } |
+ FOREACH_OTHER_UNOP_NAN(EXECUTE_OTHER_UNOP_NAN) |
+#undef EXECUTE_OTHER_UNOP_NAN |
+ |
default: |
V8_Fatal(__FILE__, __LINE__, "Unknown or unimplemented opcode #%d:%s", |
code->start[pc], OpcodeName(code->start[pc])); |