| Index: src/runtime/runtime-simd.cc
|
| diff --git a/src/runtime/runtime-simd.cc b/src/runtime/runtime-simd.cc
|
| index 9e5614242a656d882f31856c84519eb12d715d8b..2de703968f42cde442122f41515cc712e4f58f51 100644
|
| --- a/src/runtime/runtime-simd.cc
|
| +++ b/src/runtime/runtime-simd.cc
|
| @@ -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); \
|
|
|