Commit 0cdf348c authored by Karl Schimpf's avatar Karl Schimpf Committed by Commit Bot

[wasm] Remove some WASM conversion magic constants

This CL removes some magic numbers used to convert floating values into
integer values, and the corresponding comments describing how they were
computed. It replaces these tests with template function is_inbounds()
that makes the compiler automatically generate the appropriate constants
and tests.

Note: This CL only changes the WASM interpreter to use is_inbounds(). Tests
have not yet been updated to guarantee that this change did not break anything.

Note: This change was initialed by a comment by @clemensh in
CL https://chromium-review.googlesource.com/c/v8/v8/+/834670.

Bug: v8:7226
Change-Id: I14c0962eb6ae20cf6647787c006924a208f7ce4a
Reviewed-on: https://chromium-review.googlesource.com/846280
Commit-Queue: Karl Schimpf <kschimpf@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50383}
parent 0ac7a48a
......@@ -5,6 +5,8 @@
#ifndef V8_BASE_MACROS_H_
#define V8_BASE_MACROS_H_
#include <limits>
#include "src/base/compiler-specific.h"
#include "src/base/format-macros.h"
#include "src/base/logging.h"
......@@ -311,4 +313,24 @@ inline void* AlignedAddress(void* address, size_t alignment) {
~static_cast<uintptr_t>(alignment - 1));
}
// Bounds checks for float to integer conversions, which does truncation. Hence,
// the range of legal values is (min - 1, max + 1).
template <typename int_t, typename float_t, typename biggest_int_t = int64_t>
bool is_inbounds(float_t v) {
static_assert(sizeof(int_t) < sizeof(biggest_int_t),
"int_t can't be bounds checked by the compiler");
constexpr float_t kLowerBound =
static_cast<float_t>(std::numeric_limits<int_t>::min()) - 1;
constexpr float_t kUpperBound =
static_cast<float_t>(std::numeric_limits<int_t>::max()) + 1;
constexpr bool kLowerBoundIsMin =
static_cast<biggest_int_t>(kLowerBound) ==
static_cast<biggest_int_t>(std::numeric_limits<int_t>::min());
constexpr bool kUpperBoundIsMax =
static_cast<biggest_int_t>(kUpperBound) ==
static_cast<biggest_int_t>(std::numeric_limits<int_t>::max());
return (kLowerBoundIsMin ? (kLowerBound <= v) : (kLowerBound < v)) &&
(kUpperBoundIsMax ? (v <= kUpperBound) : (v < kUpperBound));
}
#endif // V8_BASE_MACROS_H_
......@@ -442,14 +442,7 @@ inline double ExecuteF64NearestInt(double a, TrapReason* trap) {
inline double ExecuteF64Sqrt(double a, TrapReason* trap) { return sqrt(a); }
int32_t ExecuteI32SConvertF32(float a, TrapReason* trap) {
// The upper bound is (INT32_MAX + 1), which is the lowest float-representable
// number above INT32_MAX which cannot be represented as int32.
float upper_bound = 2147483648.0f;
// We use INT32_MIN as a lower bound because (INT32_MIN - 1) is not
// representable as float, and no number between (INT32_MIN - 1) and INT32_MIN
// is.
float lower_bound = static_cast<float>(INT32_MIN);
if (a < upper_bound && a >= lower_bound) {
if (is_inbounds<int32_t>(a)) {
return static_cast<int32_t>(a);
}
*trap = kTrapFloatUnrepresentable;
......@@ -468,13 +461,7 @@ int32_t ExecuteI32SConvertSatF32(float a) {
}
int32_t ExecuteI32SConvertF64(double a, TrapReason* trap) {
// The upper bound is (INT32_MAX + 1), which is the lowest double-
// representable number above INT32_MAX which cannot be represented as int32.
double upper_bound = 2147483648.0;
// The lower bound is (INT32_MIN - 1), which is the greatest double-
// representable number below INT32_MIN which cannot be represented as int32.
double lower_bound = -2147483649.0;
if (a < upper_bound && a > lower_bound) {
if (is_inbounds<int32_t>(a)) {
return static_cast<int32_t>(a);
}
*trap = kTrapFloatUnrepresentable;
......@@ -482,12 +469,7 @@ int32_t ExecuteI32SConvertF64(double a, TrapReason* trap) {
}
uint32_t ExecuteI32UConvertF32(float a, TrapReason* trap) {
// The upper bound is (UINT32_MAX + 1), which is the lowest
// float-representable number above UINT32_MAX which cannot be represented as
// uint32.
double upper_bound = 4294967296.0f;
double lower_bound = -1.0f;
if (a < upper_bound && a > lower_bound) {
if (is_inbounds<uint32_t>(a)) {
return static_cast<uint32_t>(a);
}
*trap = kTrapFloatUnrepresentable;
......@@ -495,12 +477,7 @@ uint32_t ExecuteI32UConvertF32(float a, TrapReason* trap) {
}
uint32_t ExecuteI32UConvertF64(double a, TrapReason* trap) {
// The upper bound is (UINT32_MAX + 1), which is the lowest
// double-representable number above UINT32_MAX which cannot be represented as
// uint32.
double upper_bound = 4294967296.0;
double lower_bound = -1.0;
if (a < upper_bound && a > lower_bound) {
if (is_inbounds<uint32_t>(a)) {
return static_cast<uint32_t>(a);
}
*trap = kTrapFloatUnrepresentable;
......
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