Commit ac187c03 authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Refactor the non-determinism detection in the interpreter.

Apparently it happens quite easily that different NaNs are produced in
the interpreter than in the execution of the compiled code. This
non-determinism caused problems for the fuzzer which compares the
equality of the results of the interpreter and the compiled code.

I decided therefore to refactor the detection of non-determinism in the
interpreter. Instead of tracking whether potentially non-deterministic
NaNs were produced, I track now whether potentially non-deterministic
NaNs could have been observed. The only way the NaN non-determinism can
be observed is by observing the non-deterministic bit pattern of the
NaN. AFAICT the only way to observe the bit pattern is with a
I(32|64)_REINTERPRET_F(32|64) instruction or with a F(32|64)_STORE
followed by a load. Therefore I flag an execution as potentially
non-deterministic when either a NaN is reinterpreted to an int, or when
a NaN is stored to memory.

R=titzer@chromium.org, eholk@chromium.org
BUG=682180

Review-Url: https://codereview.chromium.org/2671803002
Cr-Commit-Position: refs/heads/master@{#42917}
parent 994d906e
This diff is collapsed.
......@@ -343,57 +343,59 @@ TEST(GrowMemoryInvalidSize) {
TEST(TestPossibleNondeterminism) {
{
// F32Div may produced NaN
WasmRunner<float, float, float> r(kExecuteInterpreted);
BUILD(r, WASM_F32_DIV(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
r.Call(1048575.5f, 2.5f);
WasmRunner<int32_t, float> r(kExecuteInterpreted);
BUILD(r, WASM_I32_REINTERPRET_F32(WASM_GET_LOCAL(0)));
r.Call(1048575.5f);
CHECK(!r.possible_nondeterminism());
r.Call(0.0f, 0.0f);
r.Call(std::numeric_limits<float>::quiet_NaN());
CHECK(r.possible_nondeterminism());
}
{
// F32Sqrt may produced NaN
WasmRunner<float, float> r(kExecuteInterpreted);
BUILD(r, WASM_F32_SQRT(WASM_GET_LOCAL(0)));
r.Call(16.0f);
WasmRunner<int64_t, double> r(kExecuteInterpreted);
BUILD(r, WASM_I64_REINTERPRET_F64(WASM_GET_LOCAL(0)));
r.Call(16.0);
CHECK(!r.possible_nondeterminism());
r.Call(-1048575.5f);
r.Call(std::numeric_limits<double>::quiet_NaN());
CHECK(r.possible_nondeterminism());
}
{
// F32Mul may produced NaN
WasmRunner<float, float, float> r(kExecuteInterpreted);
BUILD(r, WASM_F32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
r.Call(1048575.5f, 2.5f);
WasmRunner<float, float> r(kExecuteInterpreted);
BUILD(r, WASM_F32_COPYSIGN(WASM_F32(42.0f), WASM_GET_LOCAL(0)));
r.Call(16.0f);
CHECK(!r.possible_nondeterminism());
r.Call(std::numeric_limits<float>::infinity(), 0.0f);
r.Call(std::numeric_limits<double>::quiet_NaN());
CHECK(r.possible_nondeterminism());
}
{
// F64Div may produced NaN
WasmRunner<double, double, double> r(kExecuteInterpreted);
BUILD(r, WASM_F64_DIV(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
r.Call(1048575.5, 2.5);
WasmRunner<double, double> r(kExecuteInterpreted);
BUILD(r, WASM_F64_COPYSIGN(WASM_F64(42.0), WASM_GET_LOCAL(0)));
r.Call(16.0);
CHECK(!r.possible_nondeterminism());
r.Call(0.0, 0.0);
r.Call(std::numeric_limits<double>::quiet_NaN());
CHECK(r.possible_nondeterminism());
}
{
// F64Sqrt may produced NaN
WasmRunner<double, double> r(kExecuteInterpreted);
BUILD(r, WASM_F64_SQRT(WASM_GET_LOCAL(0)));
r.Call(1048575.5);
int32_t index = 16;
WasmRunner<int32_t, float> r(kExecuteInterpreted);
r.module().AddMemory(WasmModule::kPageSize);
BUILD(r, WASM_STORE_MEM(MachineType::Float32(), WASM_I32V(index),
WASM_GET_LOCAL(0)),
WASM_I32V(index));
r.Call(1345.3456f);
CHECK(!r.possible_nondeterminism());
r.Call(-1048575.5);
r.Call(std::numeric_limits<float>::quiet_NaN());
CHECK(r.possible_nondeterminism());
}
{
// F64Mul may produced NaN
WasmRunner<double, double, double> r(kExecuteInterpreted);
BUILD(r, WASM_F64_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
r.Call(1048575.5, 2.5);
int32_t index = 16;
WasmRunner<int32_t, double> r(kExecuteInterpreted);
r.module().AddMemory(WasmModule::kPageSize);
BUILD(r, WASM_STORE_MEM(MachineType::Float64(), WASM_I32V(index),
WASM_GET_LOCAL(0)),
WASM_I32V(index));
r.Call(1345.3456);
CHECK(!r.possible_nondeterminism());
r.Call(std::numeric_limits<double>::infinity(), 0.0);
r.Call(std::numeric_limits<double>::quiet_NaN());
CHECK(r.possible_nondeterminism());
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment