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