Commit 4001d55e authored by gdeepti's avatar gdeepti Committed by Commit bot

[simdjs] Update SIMD runtime functions as per spec

 - Lane indices are no longer required to be integers. Add index coersion for loads/stores
 - Give shift operators masking shift count semantics
 - Throw type/range errors instead of runtime asserts.

BUG=v8:4963
LOG=N

R=bbudge@chromium.org, bmeurer@chromium.org

Review-Url: https://codereview.chromium.org/1965443003
Cr-Commit-Position: refs/heads/master@{#36402}
parent b3ae02e8
......@@ -27,7 +27,7 @@ deps = {
Var("git_url") + "/v8/deps/third_party/benchmarks.git" + "@" + "05d7188267b4560491ff9155c5ee13e207ecd65f",
"v8/test/mozilla/data":
Var("git_url") + "/v8/deps/third_party/mozilla-tests.git" + "@" + "f6c578a10ea707b1a8ab0b88943fe5115ce2b9be",
"v8/test/simdjs/data": Var("git_url") + "/external/github.com/tc39/ecmascript_simd.git" + "@" + "c8ef63c728283debc25891123eb00482fee4b8cd",
"v8/test/simdjs/data": Var("git_url") + "/external/github.com/tc39/ecmascript_simd.git" + "@" + "baf493985cb9ea7cdbd0d68704860a8156de9556",
"v8/test/test262/data":
Var("git_url") + "/external/github.com/tc39/test262.git" + "@" + "9c45e2ac684bae64614d8eb55789cae97323a7e7",
"v8/tools/clang":
......
......@@ -339,6 +339,8 @@ class CallSite {
T(InvalidTypedArrayAlignment, "% of % should be a multiple of %") \
T(InvalidTypedArrayLength, "Invalid typed array length") \
T(InvalidTypedArrayOffset, "Start offset is too large:") \
T(InvalidSimdIndex, "Index out of bounds for SIMD operation") \
T(InvalidSimdLaneValue, "Lane value out of bounds for SIMD operation") \
T(LetInLexicalBinding, "let is disallowed as a lexically bound name") \
T(LocaleMatcher, "Illegal value for localeMatcher:%") \
T(NormalizationForm, "The normalization form should be one of %.") \
......
......@@ -26,6 +26,7 @@ static bool CanCast(F from) {
// A float can't represent 2^31 - 1 or 2^32 - 1 exactly, so promote the limits
// to double. Otherwise, the limit is truncated and numbers like 2^31 or 2^32
// get through, causing any static_cast to be undefined.
from = std::trunc(from);
return from >= static_cast<double>(std::numeric_limits<T>::min()) &&
from <= static_cast<double>(std::numeric_limits<T>::max());
}
......@@ -168,9 +169,19 @@ RUNTIME_FUNCTION(Runtime_IsSimdValue) {
// Utility macros.
#define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \
CONVERT_INT32_ARG_CHECKED(name, index); \
RUNTIME_ASSERT(name >= 0 && name < lanes);
// TODO(gdeepti): Fix to use ToNumber conversion once polyfill is updated.
#define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \
Handle<Object> name_object = args.at<Object>(index); \
if (!name_object->IsNumber()) { \
THROW_NEW_ERROR_RETURN_FAILURE( \
isolate, NewTypeError(MessageTemplate::kInvalidSimdIndex)); \
} \
double number = name_object->Number(); \
if (number < 0 || number >= lanes || !IsInt32Double(number)) { \
THROW_NEW_ERROR_RETURN_FAILURE( \
isolate, NewRangeError(MessageTemplate::kInvalidSimdIndex)); \
} \
uint32_t name = static_cast<uint32_t>(number);
#define CONVERT_SIMD_ARG_HANDLE_THROW(Type, name, index) \
Handle<Type> name; \
......@@ -217,8 +228,10 @@ RUNTIME_FUNCTION(Runtime_IsSimdValue) {
// Common functions.
#define GET_NUMERIC_ARG(lane_type, name, index) \
CONVERT_NUMBER_ARG_HANDLE_CHECKED(a, index); \
#define GET_NUMERIC_ARG(lane_type, name, index) \
Handle<Object> a; \
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \
isolate, a, Object::ToNumber(args.at<Object>(index))); \
name = ConvertNumber<lane_type>(a->Number());
#define GET_BOOLEAN_ARG(lane_type, name, index) \
......@@ -395,10 +408,14 @@ SIMD_MAXNUM_FUNCTION(Float32x4, float, 4)
FUNCTION(Uint16x8, uint16_t, 16, 8) \
FUNCTION(Uint8x16, uint8_t, 8, 16)
#define CONVERT_SHIFT_ARG_CHECKED(name, index) \
RUNTIME_ASSERT(args[index]->IsNumber()); \
int32_t signed_shift = 0; \
RUNTIME_ASSERT(args[index]->ToInt32(&signed_shift)); \
#define CONVERT_SHIFT_ARG_CHECKED(name, index) \
Handle<Object> name_object = args.at<Object>(index); \
if (!name_object->IsNumber()) { \
THROW_NEW_ERROR_RETURN_FAILURE( \
isolate, NewTypeError(MessageTemplate::kInvalidSimdOperation)); \
} \
int32_t signed_shift = 0; \
args[index]->ToInt32(&signed_shift); \
uint32_t name = bit_cast<uint32_t>(signed_shift);
#define SIMD_LSL_FUNCTION(type, lane_type, lane_bits, lane_count) \
......@@ -409,31 +426,29 @@ SIMD_MAXNUM_FUNCTION(Float32x4, float, 4)
CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0); \
CONVERT_SHIFT_ARG_CHECKED(shift, 1); \
lane_type lanes[kLaneCount] = {0}; \
if (shift < lane_bits) { \
for (int i = 0; i < kLaneCount; i++) { \
lanes[i] = a->get_lane(i) << shift; \
} \
shift &= lane_bits - 1; \
for (int i = 0; i < kLaneCount; i++) { \
lanes[i] = a->get_lane(i) << shift; \
} \
Handle<type> result = isolate->factory()->New##type(lanes); \
return *result; \
}
#define SIMD_LSR_FUNCTION(type, lane_type, lane_bits, lane_count) \
RUNTIME_FUNCTION(Runtime_##type##ShiftRightByScalar) { \
static const int kLaneCount = lane_count; \
HandleScope scope(isolate); \
DCHECK(args.length() == 2); \
CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0); \
CONVERT_SHIFT_ARG_CHECKED(shift, 1); \
lane_type lanes[kLaneCount] = {0}; \
if (shift < lane_bits) { \
for (int i = 0; i < kLaneCount; i++) { \
lanes[i] = static_cast<lane_type>( \
bit_cast<lane_type>(a->get_lane(i)) >> shift); \
} \
} \
Handle<type> result = isolate->factory()->New##type(lanes); \
return *result; \
#define SIMD_LSR_FUNCTION(type, lane_type, lane_bits, lane_count) \
RUNTIME_FUNCTION(Runtime_##type##ShiftRightByScalar) { \
static const int kLaneCount = lane_count; \
HandleScope scope(isolate); \
DCHECK(args.length() == 2); \
CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0); \
CONVERT_SHIFT_ARG_CHECKED(shift, 1); \
lane_type lanes[kLaneCount] = {0}; \
shift &= lane_bits - 1; \
for (int i = 0; i < kLaneCount; i++) { \
lanes[i] = static_cast<lane_type>(bit_cast<lane_type>(a->get_lane(i)) >> \
shift); \
} \
Handle<type> result = isolate->factory()->New##type(lanes); \
return *result; \
}
#define SIMD_ASR_FUNCTION(type, lane_type, lane_bits, lane_count) \
......@@ -443,7 +458,7 @@ SIMD_MAXNUM_FUNCTION(Float32x4, float, 4)
DCHECK(args.length() == 2); \
CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0); \
CONVERT_SHIFT_ARG_CHECKED(shift, 1); \
if (shift >= lane_bits) shift = lane_bits - 1; \
shift &= lane_bits - 1; \
lane_type lanes[kLaneCount]; \
for (int i = 0; i < kLaneCount; i++) { \
int64_t shifted = static_cast<int64_t>(a->get_lane(i)) >> shift; \
......@@ -785,8 +800,10 @@ SIMD_SIGNED_TYPES(SIMD_NEG_FUNCTION)
lane_type lanes[kLaneCount]; \
for (int i = 0; i < kLaneCount; i++) { \
from_ctype a_value = a->get_lane(i); \
if (a_value != a_value) a_value = 0; \
RUNTIME_ASSERT(CanCast<lane_type>(a_value)); \
if (a_value != a_value || !CanCast<lane_type>(a_value)) { \
THROW_NEW_ERROR_RETURN_FAILURE( \
isolate, NewRangeError(MessageTemplate::kInvalidSimdLaneValue)); \
} \
lanes[i] = static_cast<lane_type>(a_value); \
} \
Handle<type> result = isolate->factory()->New##type(lanes); \
......@@ -863,6 +880,17 @@ SIMD_FROM_BITS_TYPES(SIMD_FROM_BITS_FUNCTION)
FUNCTION(Int32x4, int32_t, 4) \
FUNCTION(Uint32x4, uint32_t, 4)
#define SIMD_COERCE_INDEX(name, i) \
Handle<Object> length_object, number_object; \
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \
isolate, length_object, Object::ToLength(isolate, args.at<Object>(i))); \
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_object, \
Object::ToNumber(args.at<Object>(i))); \
if (number_object->Number() != length_object->Number()) { \
THROW_NEW_ERROR_RETURN_FAILURE( \
isolate, NewTypeError(MessageTemplate::kInvalidSimdIndex)); \
} \
int32_t name = number_object->Number();
// Common Load and Store Functions
......@@ -870,11 +898,14 @@ SIMD_FROM_BITS_TYPES(SIMD_FROM_BITS_FUNCTION)
static const int kLaneCount = lane_count; \
DCHECK(args.length() == 2); \
CONVERT_SIMD_ARG_HANDLE_THROW(JSTypedArray, tarray, 0); \
CONVERT_INT32_ARG_CHECKED(index, 1) \
SIMD_COERCE_INDEX(index, 1); \
size_t bpe = tarray->element_size(); \
uint32_t bytes = count * sizeof(lane_type); \
size_t byte_length = NumberToSize(isolate, tarray->byte_length()); \
RUNTIME_ASSERT(index >= 0 && index * bpe + bytes <= byte_length); \
if (index < 0 || index * bpe + bytes > byte_length) { \
THROW_NEW_ERROR_RETURN_FAILURE( \
isolate, NewRangeError(MessageTemplate::kInvalidSimdIndex)); \
} \
size_t tarray_offset = NumberToSize(isolate, tarray->byte_offset()); \
uint8_t* tarray_base = \
static_cast<uint8_t*>(tarray->GetBuffer()->backing_store()) + \
......@@ -883,17 +914,19 @@ SIMD_FROM_BITS_TYPES(SIMD_FROM_BITS_FUNCTION)
memcpy(lanes, tarray_base + index * bpe, bytes); \
Handle<type> result = isolate->factory()->New##type(lanes);
#define SIMD_STORE(type, lane_type, lane_count, count, a) \
static const int kLaneCount = lane_count; \
DCHECK(args.length() == 3); \
CONVERT_SIMD_ARG_HANDLE_THROW(JSTypedArray, tarray, 0); \
CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 2); \
CONVERT_INT32_ARG_CHECKED(index, 1) \
SIMD_COERCE_INDEX(index, 1); \
size_t bpe = tarray->element_size(); \
uint32_t bytes = count * sizeof(lane_type); \
size_t byte_length = NumberToSize(isolate, tarray->byte_length()); \
RUNTIME_ASSERT(index >= 0 && index * bpe + bytes <= byte_length); \
if (index < 0 || byte_length < index * bpe + bytes) { \
THROW_NEW_ERROR_RETURN_FAILURE( \
isolate, NewRangeError(MessageTemplate::kInvalidSimdIndex)); \
} \
size_t tarray_offset = NumberToSize(isolate, tarray->byte_offset()); \
uint8_t* tarray_base = \
static_cast<uint8_t*>(tarray->GetBuffer()->backing_store()) + \
......@@ -904,7 +937,6 @@ SIMD_FROM_BITS_TYPES(SIMD_FROM_BITS_FUNCTION)
} \
memcpy(tarray_base + index * bpe, lanes, bytes);
#define SIMD_LOAD_FUNCTION(type, lane_type, lane_count) \
RUNTIME_FUNCTION(Runtime_##type##Load) { \
HandleScope scope(isolate); \
......
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