[wasm] [interpreter] Box floats and double on loads/stores

Otherwise, the quiet NaN bit might flip already when loading the
float/double from memory or storing it.
This fixes another NaN bit flip which happened on a single bot only.

R=titzer@chromium.org

Bug: v8:6954
Change-Id: Ica9be71db9c5b505302686e9c0a4b1cae020a7e4
Reviewed-on: https://chromium-review.googlesource.com/735320
Reviewed-by: Ben Titzer <titzer@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48900}
This commit is contained in:
Clemens Hammacher 2017-10-24 14:28:30 +02:00 committed by Commit Bot
parent 7cb5a75263
commit f7263d7265

View File

@ -1107,6 +1107,28 @@ WasmValue ToWebAssemblyValue(Isolate* isolate, Handle<Object> value,
} }
} }
// Like a static_cast from src to dst, but specialized for boxed floats.
template <typename dst, typename src>
struct converter {
dst operator()(src val) const { return static_cast<dst>(val); }
};
template <>
struct converter<Float64, uint64_t> {
Float64 operator()(uint64_t val) const { return Float64::FromBits(val); }
};
template <>
struct converter<Float32, uint32_t> {
Float32 operator()(uint32_t val) const { return Float32::FromBits(val); }
};
template <>
struct converter<uint64_t, Float64> {
uint64_t operator()(Float64 val) const { return val.get_bits(); }
};
template <>
struct converter<uint32_t, Float32> {
uint32_t operator()(Float32 val) const { return val.get_bits(); }
};
// Responsible for executing code directly. // Responsible for executing code directly.
class ThreadImpl { class ThreadImpl {
struct Activation { struct Activation {
@ -1450,7 +1472,8 @@ class ThreadImpl {
return false; return false;
} }
byte* addr = wasm_context_->mem_start + operand.offset + index; byte* addr = wasm_context_->mem_start + operand.offset + index;
WasmValue result(static_cast<ctype>(ReadLittleEndianValue<mtype>(addr))); WasmValue result(
converter<ctype, mtype>{}(ReadLittleEndianValue<mtype>(addr)));
Push(result); Push(result);
len = 1 + operand.length; len = 1 + operand.length;
@ -1478,12 +1501,15 @@ class ThreadImpl {
return false; return false;
} }
byte* addr = wasm_context_->mem_start + operand.offset + index; byte* addr = wasm_context_->mem_start + operand.offset + index;
WriteLittleEndianValue<mtype>(addr, static_cast<mtype>(val.to<ctype>())); WriteLittleEndianValue<mtype>(addr,
converter<mtype, ctype>{}(val.to<ctype>()));
len = 1 + operand.length; len = 1 + operand.length;
if (std::is_same<float, ctype>::value) { if (std::is_same<float, ctype>::value ||
std::is_same<Float32, ctype>::value) {
possible_nondeterminism_ |= std::isnan(val.to<float>()); possible_nondeterminism_ |= std::isnan(val.to<float>());
} else if (std::is_same<double, ctype>::value) { } else if (std::is_same<double, ctype>::value ||
std::is_same<Float64, ctype>::value) {
possible_nondeterminism_ |= std::isnan(val.to<double>()); possible_nondeterminism_ |= std::isnan(val.to<double>());
} }
@ -1848,8 +1874,8 @@ class ThreadImpl {
LOAD_CASE(I64LoadMem32U, int64_t, uint32_t, kWord32); LOAD_CASE(I64LoadMem32U, int64_t, uint32_t, kWord32);
LOAD_CASE(I32LoadMem, int32_t, int32_t, kWord32); LOAD_CASE(I32LoadMem, int32_t, int32_t, kWord32);
LOAD_CASE(I64LoadMem, int64_t, int64_t, kWord64); LOAD_CASE(I64LoadMem, int64_t, int64_t, kWord64);
LOAD_CASE(F32LoadMem, float, float, kFloat32); LOAD_CASE(F32LoadMem, Float32, uint32_t, kFloat32);
LOAD_CASE(F64LoadMem, double, double, kFloat64); LOAD_CASE(F64LoadMem, Float64, uint64_t, kFloat64);
#undef LOAD_CASE #undef LOAD_CASE
#define STORE_CASE(name, ctype, mtype, rep) \ #define STORE_CASE(name, ctype, mtype, rep) \
@ -1867,8 +1893,8 @@ class ThreadImpl {
STORE_CASE(I64StoreMem32, int64_t, int32_t, kWord32); STORE_CASE(I64StoreMem32, int64_t, int32_t, kWord32);
STORE_CASE(I32StoreMem, int32_t, int32_t, kWord32); STORE_CASE(I32StoreMem, int32_t, int32_t, kWord32);
STORE_CASE(I64StoreMem, int64_t, int64_t, kWord64); STORE_CASE(I64StoreMem, int64_t, int64_t, kWord64);
STORE_CASE(F32StoreMem, float, float, kFloat32); STORE_CASE(F32StoreMem, Float32, uint32_t, kFloat32);
STORE_CASE(F64StoreMem, double, double, kFloat64); STORE_CASE(F64StoreMem, Float64, uint64_t, kFloat64);
#undef STORE_CASE #undef STORE_CASE
#define ASMJS_LOAD_CASE(name, ctype, mtype, defval) \ #define ASMJS_LOAD_CASE(name, ctype, mtype, defval) \