| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/base/macros.h" | 8 #include "src/base/macros.h" |
| 9 #include "src/conversions.h" | 9 #include "src/conversions.h" |
| 10 #include "src/factory.h" | 10 #include "src/factory.h" |
| 11 #include "src/objects-inl.h" | 11 #include "src/objects-inl.h" |
| 12 | 12 |
| 13 // Implement Single Instruction Multiple Data (SIMD) operations as defined in | 13 // Implement Single Instruction Multiple Data (SIMD) operations as defined in |
| 14 // the SIMD.js draft spec: | 14 // the SIMD.js draft spec: |
| 15 // http://littledan.github.io/simd.html | 15 // http://littledan.github.io/simd.html |
| 16 | 16 |
| 17 namespace v8 { | 17 namespace v8 { |
| 18 namespace internal { | 18 namespace internal { |
| 19 | 19 |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 // Functions to convert Numbers to SIMD component types. | 22 // Functions to convert Numbers to SIMD component types. |
| 23 | 23 |
| 24 template <typename T, typename F> | 24 template <typename T, typename F> |
| 25 static bool CanCast(F from) { | 25 static bool CanCast(F from) { |
| 26 // A float can't represent 2^31 - 1 or 2^32 - 1 exactly, so promote the limits | 26 // A float can't represent 2^31 - 1 or 2^32 - 1 exactly, so promote the limits |
| 27 // to double. Otherwise, the limit is truncated and numbers like 2^31 or 2^32 | 27 // to double. Otherwise, the limit is truncated and numbers like 2^31 or 2^32 |
| 28 // get through, causing any static_cast to be undefined. | 28 // get through, causing any static_cast to be undefined. |
| 29 from = std::trunc(from); |
| 29 return from >= static_cast<double>(std::numeric_limits<T>::min()) && | 30 return from >= static_cast<double>(std::numeric_limits<T>::min()) && |
| 30 from <= static_cast<double>(std::numeric_limits<T>::max()); | 31 from <= static_cast<double>(std::numeric_limits<T>::max()); |
| 31 } | 32 } |
| 32 | 33 |
| 33 | 34 |
| 34 // Explicitly specialize for conversions to float, which always succeed. | 35 // Explicitly specialize for conversions to float, which always succeed. |
| 35 template <> | 36 template <> |
| 36 bool CanCast<float>(int32_t from) { | 37 bool CanCast<float>(int32_t from) { |
| 37 return true; | 38 return true; |
| 38 } | 39 } |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 HandleScope scope(isolate); | 162 HandleScope scope(isolate); |
| 162 DCHECK(args.length() == 1); | 163 DCHECK(args.length() == 1); |
| 163 return isolate->heap()->ToBoolean(args[0]->IsSimd128Value()); | 164 return isolate->heap()->ToBoolean(args[0]->IsSimd128Value()); |
| 164 } | 165 } |
| 165 | 166 |
| 166 | 167 |
| 167 //------------------------------------------------------------------- | 168 //------------------------------------------------------------------- |
| 168 | 169 |
| 169 // Utility macros. | 170 // Utility macros. |
| 170 | 171 |
| 171 #define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \ | 172 // TODO(gdeepti): Fix to use ToNumber conversion once polyfill is updated. |
| 172 CONVERT_INT32_ARG_CHECKED(name, index); \ | 173 #define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \ |
| 173 RUNTIME_ASSERT(name >= 0 && name < lanes); | 174 Handle<Object> name_object = args.at<Object>(index); \ |
| 175 if (!name_object->IsNumber()) { \ |
| 176 THROW_NEW_ERROR_RETURN_FAILURE( \ |
| 177 isolate, NewTypeError(MessageTemplate::kInvalidSimdIndex)); \ |
| 178 } \ |
| 179 double number = name_object->Number(); \ |
| 180 if (number < 0 || number >= lanes || !IsInt32Double(number)) { \ |
| 181 THROW_NEW_ERROR_RETURN_FAILURE( \ |
| 182 isolate, NewRangeError(MessageTemplate::kInvalidSimdIndex)); \ |
| 183 } \ |
| 184 uint32_t name = static_cast<uint32_t>(number); |
| 174 | 185 |
| 175 #define CONVERT_SIMD_ARG_HANDLE_THROW(Type, name, index) \ | 186 #define CONVERT_SIMD_ARG_HANDLE_THROW(Type, name, index) \ |
| 176 Handle<Type> name; \ | 187 Handle<Type> name; \ |
| 177 if (args[index]->Is##Type()) { \ | 188 if (args[index]->Is##Type()) { \ |
| 178 name = args.at<Type>(index); \ | 189 name = args.at<Type>(index); \ |
| 179 } else { \ | 190 } else { \ |
| 180 THROW_NEW_ERROR_RETURN_FAILURE( \ | 191 THROW_NEW_ERROR_RETURN_FAILURE( \ |
| 181 isolate, NewTypeError(MessageTemplate::kInvalidSimdOperation)); \ | 192 isolate, NewTypeError(MessageTemplate::kInvalidSimdOperation)); \ |
| 182 } | 193 } |
| 183 | 194 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 210 bool lanes[kLaneCount]; \ | 221 bool lanes[kLaneCount]; \ |
| 211 for (int i = 0; i < kLaneCount; i++) { \ | 222 for (int i = 0; i < kLaneCount; i++) { \ |
| 212 lanes[i] = a->get_lane(i) op b->get_lane(i); \ | 223 lanes[i] = a->get_lane(i) op b->get_lane(i); \ |
| 213 } \ | 224 } \ |
| 214 Handle<bool_type> result = isolate->factory()->New##bool_type(lanes); | 225 Handle<bool_type> result = isolate->factory()->New##bool_type(lanes); |
| 215 | 226 |
| 216 //------------------------------------------------------------------- | 227 //------------------------------------------------------------------- |
| 217 | 228 |
| 218 // Common functions. | 229 // Common functions. |
| 219 | 230 |
| 220 #define GET_NUMERIC_ARG(lane_type, name, index) \ | 231 #define GET_NUMERIC_ARG(lane_type, name, index) \ |
| 221 CONVERT_NUMBER_ARG_HANDLE_CHECKED(a, index); \ | 232 Handle<Object> a; \ |
| 233 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \ |
| 234 isolate, a, Object::ToNumber(args.at<Object>(index))); \ |
| 222 name = ConvertNumber<lane_type>(a->Number()); | 235 name = ConvertNumber<lane_type>(a->Number()); |
| 223 | 236 |
| 224 #define GET_BOOLEAN_ARG(lane_type, name, index) \ | 237 #define GET_BOOLEAN_ARG(lane_type, name, index) \ |
| 225 name = args[index]->BooleanValue(); | 238 name = args[index]->BooleanValue(); |
| 226 | 239 |
| 227 #define SIMD_ALL_TYPES(FUNCTION) \ | 240 #define SIMD_ALL_TYPES(FUNCTION) \ |
| 228 FUNCTION(Float32x4, float, 4, NewNumber, GET_NUMERIC_ARG) \ | 241 FUNCTION(Float32x4, float, 4, NewNumber, GET_NUMERIC_ARG) \ |
| 229 FUNCTION(Int32x4, int32_t, 4, NewNumber, GET_NUMERIC_ARG) \ | 242 FUNCTION(Int32x4, int32_t, 4, NewNumber, GET_NUMERIC_ARG) \ |
| 230 FUNCTION(Uint32x4, uint32_t, 4, NewNumber, GET_NUMERIC_ARG) \ | 243 FUNCTION(Uint32x4, uint32_t, 4, NewNumber, GET_NUMERIC_ARG) \ |
| 231 FUNCTION(Bool32x4, bool, 4, ToBoolean, GET_BOOLEAN_ARG) \ | 244 FUNCTION(Bool32x4, bool, 4, ToBoolean, GET_BOOLEAN_ARG) \ |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 #define SIMD_INT_TYPES(FUNCTION) \ | 401 #define SIMD_INT_TYPES(FUNCTION) \ |
| 389 FUNCTION(Int32x4, int32_t, 32, 4) \ | 402 FUNCTION(Int32x4, int32_t, 32, 4) \ |
| 390 FUNCTION(Int16x8, int16_t, 16, 8) \ | 403 FUNCTION(Int16x8, int16_t, 16, 8) \ |
| 391 FUNCTION(Int8x16, int8_t, 8, 16) | 404 FUNCTION(Int8x16, int8_t, 8, 16) |
| 392 | 405 |
| 393 #define SIMD_UINT_TYPES(FUNCTION) \ | 406 #define SIMD_UINT_TYPES(FUNCTION) \ |
| 394 FUNCTION(Uint32x4, uint32_t, 32, 4) \ | 407 FUNCTION(Uint32x4, uint32_t, 32, 4) \ |
| 395 FUNCTION(Uint16x8, uint16_t, 16, 8) \ | 408 FUNCTION(Uint16x8, uint16_t, 16, 8) \ |
| 396 FUNCTION(Uint8x16, uint8_t, 8, 16) | 409 FUNCTION(Uint8x16, uint8_t, 8, 16) |
| 397 | 410 |
| 398 #define CONVERT_SHIFT_ARG_CHECKED(name, index) \ | 411 #define CONVERT_SHIFT_ARG_CHECKED(name, index) \ |
| 399 RUNTIME_ASSERT(args[index]->IsNumber()); \ | 412 Handle<Object> name_object = args.at<Object>(index); \ |
| 400 int32_t signed_shift = 0; \ | 413 if (!name_object->IsNumber()) { \ |
| 401 RUNTIME_ASSERT(args[index]->ToInt32(&signed_shift)); \ | 414 THROW_NEW_ERROR_RETURN_FAILURE( \ |
| 415 isolate, NewTypeError(MessageTemplate::kInvalidSimdOperation)); \ |
| 416 } \ |
| 417 int32_t signed_shift = 0; \ |
| 418 args[index]->ToInt32(&signed_shift); \ |
| 402 uint32_t name = bit_cast<uint32_t>(signed_shift); | 419 uint32_t name = bit_cast<uint32_t>(signed_shift); |
| 403 | 420 |
| 404 #define SIMD_LSL_FUNCTION(type, lane_type, lane_bits, lane_count) \ | 421 #define SIMD_LSL_FUNCTION(type, lane_type, lane_bits, lane_count) \ |
| 405 RUNTIME_FUNCTION(Runtime_##type##ShiftLeftByScalar) { \ | 422 RUNTIME_FUNCTION(Runtime_##type##ShiftLeftByScalar) { \ |
| 406 static const int kLaneCount = lane_count; \ | 423 static const int kLaneCount = lane_count; \ |
| 407 HandleScope scope(isolate); \ | 424 HandleScope scope(isolate); \ |
| 408 DCHECK(args.length() == 2); \ | 425 DCHECK(args.length() == 2); \ |
| 409 CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0); \ | 426 CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0); \ |
| 410 CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ | 427 CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ |
| 411 lane_type lanes[kLaneCount] = {0}; \ | 428 lane_type lanes[kLaneCount] = {0}; \ |
| 412 if (shift < lane_bits) { \ | 429 shift &= lane_bits - 1; \ |
| 413 for (int i = 0; i < kLaneCount; i++) { \ | 430 for (int i = 0; i < kLaneCount; i++) { \ |
| 414 lanes[i] = a->get_lane(i) << shift; \ | 431 lanes[i] = a->get_lane(i) << shift; \ |
| 415 } \ | |
| 416 } \ | 432 } \ |
| 417 Handle<type> result = isolate->factory()->New##type(lanes); \ | 433 Handle<type> result = isolate->factory()->New##type(lanes); \ |
| 418 return *result; \ | 434 return *result; \ |
| 419 } | 435 } |
| 420 | 436 |
| 421 #define SIMD_LSR_FUNCTION(type, lane_type, lane_bits, lane_count) \ | 437 #define SIMD_LSR_FUNCTION(type, lane_type, lane_bits, lane_count) \ |
| 422 RUNTIME_FUNCTION(Runtime_##type##ShiftRightByScalar) { \ | 438 RUNTIME_FUNCTION(Runtime_##type##ShiftRightByScalar) { \ |
| 423 static const int kLaneCount = lane_count; \ | 439 static const int kLaneCount = lane_count; \ |
| 424 HandleScope scope(isolate); \ | 440 HandleScope scope(isolate); \ |
| 425 DCHECK(args.length() == 2); \ | 441 DCHECK(args.length() == 2); \ |
| 426 CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0); \ | 442 CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0); \ |
| 427 CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ | 443 CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ |
| 428 lane_type lanes[kLaneCount] = {0}; \ | 444 lane_type lanes[kLaneCount] = {0}; \ |
| 429 if (shift < lane_bits) { \ | 445 shift &= lane_bits - 1; \ |
| 430 for (int i = 0; i < kLaneCount; i++) { \ | 446 for (int i = 0; i < kLaneCount; i++) { \ |
| 431 lanes[i] = static_cast<lane_type>( \ | 447 lanes[i] = static_cast<lane_type>(bit_cast<lane_type>(a->get_lane(i)) >> \ |
| 432 bit_cast<lane_type>(a->get_lane(i)) >> shift); \ | 448 shift); \ |
| 433 } \ | 449 } \ |
| 434 } \ | 450 Handle<type> result = isolate->factory()->New##type(lanes); \ |
| 435 Handle<type> result = isolate->factory()->New##type(lanes); \ | 451 return *result; \ |
| 436 return *result; \ | |
| 437 } | 452 } |
| 438 | 453 |
| 439 #define SIMD_ASR_FUNCTION(type, lane_type, lane_bits, lane_count) \ | 454 #define SIMD_ASR_FUNCTION(type, lane_type, lane_bits, lane_count) \ |
| 440 RUNTIME_FUNCTION(Runtime_##type##ShiftRightByScalar) { \ | 455 RUNTIME_FUNCTION(Runtime_##type##ShiftRightByScalar) { \ |
| 441 static const int kLaneCount = lane_count; \ | 456 static const int kLaneCount = lane_count; \ |
| 442 HandleScope scope(isolate); \ | 457 HandleScope scope(isolate); \ |
| 443 DCHECK(args.length() == 2); \ | 458 DCHECK(args.length() == 2); \ |
| 444 CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0); \ | 459 CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0); \ |
| 445 CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ | 460 CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ |
| 446 if (shift >= lane_bits) shift = lane_bits - 1; \ | 461 shift &= lane_bits - 1; \ |
| 447 lane_type lanes[kLaneCount]; \ | 462 lane_type lanes[kLaneCount]; \ |
| 448 for (int i = 0; i < kLaneCount; i++) { \ | 463 for (int i = 0; i < kLaneCount; i++) { \ |
| 449 int64_t shifted = static_cast<int64_t>(a->get_lane(i)) >> shift; \ | 464 int64_t shifted = static_cast<int64_t>(a->get_lane(i)) >> shift; \ |
| 450 lanes[i] = static_cast<lane_type>(shifted); \ | 465 lanes[i] = static_cast<lane_type>(shifted); \ |
| 451 } \ | 466 } \ |
| 452 Handle<type> result = isolate->factory()->New##type(lanes); \ | 467 Handle<type> result = isolate->factory()->New##type(lanes); \ |
| 453 return *result; \ | 468 return *result; \ |
| 454 } | 469 } |
| 455 | 470 |
| 456 SIMD_INT_TYPES(SIMD_LSL_FUNCTION) | 471 SIMD_INT_TYPES(SIMD_LSL_FUNCTION) |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 | 793 |
| 779 #define SIMD_FROM_FUNCTION(type, lane_type, lane_count, from_type, from_ctype) \ | 794 #define SIMD_FROM_FUNCTION(type, lane_type, lane_count, from_type, from_ctype) \ |
| 780 RUNTIME_FUNCTION(Runtime_##type##From##from_type) { \ | 795 RUNTIME_FUNCTION(Runtime_##type##From##from_type) { \ |
| 781 static const int kLaneCount = lane_count; \ | 796 static const int kLaneCount = lane_count; \ |
| 782 HandleScope scope(isolate); \ | 797 HandleScope scope(isolate); \ |
| 783 DCHECK(args.length() == 1); \ | 798 DCHECK(args.length() == 1); \ |
| 784 CONVERT_SIMD_ARG_HANDLE_THROW(from_type, a, 0); \ | 799 CONVERT_SIMD_ARG_HANDLE_THROW(from_type, a, 0); \ |
| 785 lane_type lanes[kLaneCount]; \ | 800 lane_type lanes[kLaneCount]; \ |
| 786 for (int i = 0; i < kLaneCount; i++) { \ | 801 for (int i = 0; i < kLaneCount; i++) { \ |
| 787 from_ctype a_value = a->get_lane(i); \ | 802 from_ctype a_value = a->get_lane(i); \ |
| 788 if (a_value != a_value) a_value = 0; \ | 803 if (a_value != a_value || !CanCast<lane_type>(a_value)) { \ |
| 789 RUNTIME_ASSERT(CanCast<lane_type>(a_value)); \ | 804 THROW_NEW_ERROR_RETURN_FAILURE( \ |
| 805 isolate, NewRangeError(MessageTemplate::kInvalidSimdLaneValue)); \ |
| 806 } \ |
| 790 lanes[i] = static_cast<lane_type>(a_value); \ | 807 lanes[i] = static_cast<lane_type>(a_value); \ |
| 791 } \ | 808 } \ |
| 792 Handle<type> result = isolate->factory()->New##type(lanes); \ | 809 Handle<type> result = isolate->factory()->New##type(lanes); \ |
| 793 return *result; \ | 810 return *result; \ |
| 794 } | 811 } |
| 795 | 812 |
| 796 SIMD_FROM_TYPES(SIMD_FROM_FUNCTION) | 813 SIMD_FROM_TYPES(SIMD_FROM_FUNCTION) |
| 797 | 814 |
| 798 #define SIMD_FROM_BITS_TYPES(FUNCTION) \ | 815 #define SIMD_FROM_BITS_TYPES(FUNCTION) \ |
| 799 FUNCTION(Float32x4, float, 4, Int32x4) \ | 816 FUNCTION(Float32x4, float, 4, Int32x4) \ |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 | 873 |
| 857 //------------------------------------------------------------------- | 874 //------------------------------------------------------------------- |
| 858 | 875 |
| 859 // Load and Store functions. | 876 // Load and Store functions. |
| 860 | 877 |
| 861 #define SIMD_LOADN_STOREN_TYPES(FUNCTION) \ | 878 #define SIMD_LOADN_STOREN_TYPES(FUNCTION) \ |
| 862 FUNCTION(Float32x4, float, 4) \ | 879 FUNCTION(Float32x4, float, 4) \ |
| 863 FUNCTION(Int32x4, int32_t, 4) \ | 880 FUNCTION(Int32x4, int32_t, 4) \ |
| 864 FUNCTION(Uint32x4, uint32_t, 4) | 881 FUNCTION(Uint32x4, uint32_t, 4) |
| 865 | 882 |
| 883 #define SIMD_COERCE_INDEX(name, i) \ |
| 884 Handle<Object> length_object, number_object; \ |
| 885 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \ |
| 886 isolate, length_object, Object::ToLength(isolate, args.at<Object>(i))); \ |
| 887 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_object, \ |
| 888 Object::ToNumber(args.at<Object>(i))); \ |
| 889 if (number_object->Number() != length_object->Number()) { \ |
| 890 THROW_NEW_ERROR_RETURN_FAILURE( \ |
| 891 isolate, NewTypeError(MessageTemplate::kInvalidSimdIndex)); \ |
| 892 } \ |
| 893 int32_t name = number_object->Number(); |
| 866 | 894 |
| 867 // Common Load and Store Functions | 895 // Common Load and Store Functions |
| 868 | 896 |
| 869 #define SIMD_LOAD(type, lane_type, lane_count, count, result) \ | 897 #define SIMD_LOAD(type, lane_type, lane_count, count, result) \ |
| 870 static const int kLaneCount = lane_count; \ | 898 static const int kLaneCount = lane_count; \ |
| 871 DCHECK(args.length() == 2); \ | 899 DCHECK(args.length() == 2); \ |
| 872 CONVERT_SIMD_ARG_HANDLE_THROW(JSTypedArray, tarray, 0); \ | 900 CONVERT_SIMD_ARG_HANDLE_THROW(JSTypedArray, tarray, 0); \ |
| 873 CONVERT_INT32_ARG_CHECKED(index, 1) \ | 901 SIMD_COERCE_INDEX(index, 1); \ |
| 874 size_t bpe = tarray->element_size(); \ | 902 size_t bpe = tarray->element_size(); \ |
| 875 uint32_t bytes = count * sizeof(lane_type); \ | 903 uint32_t bytes = count * sizeof(lane_type); \ |
| 876 size_t byte_length = NumberToSize(isolate, tarray->byte_length()); \ | 904 size_t byte_length = NumberToSize(isolate, tarray->byte_length()); \ |
| 877 RUNTIME_ASSERT(index >= 0 && index * bpe + bytes <= byte_length); \ | 905 if (index < 0 || index * bpe + bytes > byte_length) { \ |
| 906 THROW_NEW_ERROR_RETURN_FAILURE( \ |
| 907 isolate, NewRangeError(MessageTemplate::kInvalidSimdIndex)); \ |
| 908 } \ |
| 878 size_t tarray_offset = NumberToSize(isolate, tarray->byte_offset()); \ | 909 size_t tarray_offset = NumberToSize(isolate, tarray->byte_offset()); \ |
| 879 uint8_t* tarray_base = \ | 910 uint8_t* tarray_base = \ |
| 880 static_cast<uint8_t*>(tarray->GetBuffer()->backing_store()) + \ | 911 static_cast<uint8_t*>(tarray->GetBuffer()->backing_store()) + \ |
| 881 tarray_offset; \ | 912 tarray_offset; \ |
| 882 lane_type lanes[kLaneCount] = {0}; \ | 913 lane_type lanes[kLaneCount] = {0}; \ |
| 883 memcpy(lanes, tarray_base + index * bpe, bytes); \ | 914 memcpy(lanes, tarray_base + index * bpe, bytes); \ |
| 884 Handle<type> result = isolate->factory()->New##type(lanes); | 915 Handle<type> result = isolate->factory()->New##type(lanes); |
| 885 | 916 |
| 886 | |
| 887 #define SIMD_STORE(type, lane_type, lane_count, count, a) \ | 917 #define SIMD_STORE(type, lane_type, lane_count, count, a) \ |
| 888 static const int kLaneCount = lane_count; \ | 918 static const int kLaneCount = lane_count; \ |
| 889 DCHECK(args.length() == 3); \ | 919 DCHECK(args.length() == 3); \ |
| 890 CONVERT_SIMD_ARG_HANDLE_THROW(JSTypedArray, tarray, 0); \ | 920 CONVERT_SIMD_ARG_HANDLE_THROW(JSTypedArray, tarray, 0); \ |
| 891 CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 2); \ | 921 CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 2); \ |
| 892 CONVERT_INT32_ARG_CHECKED(index, 1) \ | 922 SIMD_COERCE_INDEX(index, 1); \ |
| 893 size_t bpe = tarray->element_size(); \ | 923 size_t bpe = tarray->element_size(); \ |
| 894 uint32_t bytes = count * sizeof(lane_type); \ | 924 uint32_t bytes = count * sizeof(lane_type); \ |
| 895 size_t byte_length = NumberToSize(isolate, tarray->byte_length()); \ | 925 size_t byte_length = NumberToSize(isolate, tarray->byte_length()); \ |
| 896 RUNTIME_ASSERT(index >= 0 && index * bpe + bytes <= byte_length); \ | 926 if (index < 0 || byte_length < index * bpe + bytes) { \ |
| 927 THROW_NEW_ERROR_RETURN_FAILURE( \ |
| 928 isolate, NewRangeError(MessageTemplate::kInvalidSimdIndex)); \ |
| 929 } \ |
| 897 size_t tarray_offset = NumberToSize(isolate, tarray->byte_offset()); \ | 930 size_t tarray_offset = NumberToSize(isolate, tarray->byte_offset()); \ |
| 898 uint8_t* tarray_base = \ | 931 uint8_t* tarray_base = \ |
| 899 static_cast<uint8_t*>(tarray->GetBuffer()->backing_store()) + \ | 932 static_cast<uint8_t*>(tarray->GetBuffer()->backing_store()) + \ |
| 900 tarray_offset; \ | 933 tarray_offset; \ |
| 901 lane_type lanes[kLaneCount]; \ | 934 lane_type lanes[kLaneCount]; \ |
| 902 for (int i = 0; i < kLaneCount; i++) { \ | 935 for (int i = 0; i < kLaneCount; i++) { \ |
| 903 lanes[i] = a->get_lane(i); \ | 936 lanes[i] = a->get_lane(i); \ |
| 904 } \ | 937 } \ |
| 905 memcpy(tarray_base + index * bpe, lanes, bytes); | 938 memcpy(tarray_base + index * bpe, lanes, bytes); |
| 906 | 939 |
| 907 | |
| 908 #define SIMD_LOAD_FUNCTION(type, lane_type, lane_count) \ | 940 #define SIMD_LOAD_FUNCTION(type, lane_type, lane_count) \ |
| 909 RUNTIME_FUNCTION(Runtime_##type##Load) { \ | 941 RUNTIME_FUNCTION(Runtime_##type##Load) { \ |
| 910 HandleScope scope(isolate); \ | 942 HandleScope scope(isolate); \ |
| 911 SIMD_LOAD(type, lane_type, lane_count, lane_count, result); \ | 943 SIMD_LOAD(type, lane_type, lane_count, lane_count, result); \ |
| 912 return *result; \ | 944 return *result; \ |
| 913 } | 945 } |
| 914 | 946 |
| 915 | 947 |
| 916 #define SIMD_LOAD1_FUNCTION(type, lane_type, lane_count) \ | 948 #define SIMD_LOAD1_FUNCTION(type, lane_type, lane_count) \ |
| 917 RUNTIME_FUNCTION(Runtime_##type##Load1) { \ | 949 RUNTIME_FUNCTION(Runtime_##type##Load1) { \ |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 975 SIMD_LOADN_STOREN_TYPES(SIMD_LOAD3_FUNCTION) | 1007 SIMD_LOADN_STOREN_TYPES(SIMD_LOAD3_FUNCTION) |
| 976 SIMD_NUMERIC_TYPES(SIMD_STORE_FUNCTION) | 1008 SIMD_NUMERIC_TYPES(SIMD_STORE_FUNCTION) |
| 977 SIMD_LOADN_STOREN_TYPES(SIMD_STORE1_FUNCTION) | 1009 SIMD_LOADN_STOREN_TYPES(SIMD_STORE1_FUNCTION) |
| 978 SIMD_LOADN_STOREN_TYPES(SIMD_STORE2_FUNCTION) | 1010 SIMD_LOADN_STOREN_TYPES(SIMD_STORE2_FUNCTION) |
| 979 SIMD_LOADN_STOREN_TYPES(SIMD_STORE3_FUNCTION) | 1011 SIMD_LOADN_STOREN_TYPES(SIMD_STORE3_FUNCTION) |
| 980 | 1012 |
| 981 //------------------------------------------------------------------- | 1013 //------------------------------------------------------------------- |
| 982 | 1014 |
| 983 } // namespace internal | 1015 } // namespace internal |
| 984 } // namespace v8 | 1016 } // namespace v8 |
| OLD | NEW |