}
+template<typename T, int Bytes>
+inline static bool SimdTypeLoadValue(
+ Isolate* isolate,
+ Handle<JSArrayBuffer> buffer,
+ Handle<Object> byte_offset_obj,
+ T* result) {
+ size_t byte_offset = 0;
+ if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
+ return false;
+ }
+
+ size_t buffer_byte_length =
+ NumberToSize(isolate, buffer->byte_length());
+ if (byte_offset + Bytes > buffer_byte_length) { // overflow
+ return false;
+ }
+
+ union Value {
+ T data;
+ uint8_t bytes[sizeof(T)];
+ };
+
+ Value value;
+ memset(value.bytes, 0, sizeof(T));
+ uint8_t* source =
+ static_cast<uint8_t*>(buffer->backing_store()) + byte_offset;
+ DCHECK(Bytes <= sizeof(T));
+ CopyBytes<Bytes>(value.bytes, source);
+ *result = value.data;
+ return true;
+}
+
+
+template<typename T, int Bytes>
+static bool SimdTypeStoreValue(
+ Isolate* isolate,
+ Handle<JSArrayBuffer> buffer,
+ Handle<Object> byte_offset_obj,
+ T data) {
+ size_t byte_offset = 0;
+ if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
+ return false;
+ }
+
+ size_t buffer_byte_length =
+ NumberToSize(isolate, buffer->byte_length());
+ if (byte_offset + Bytes > buffer_byte_length) { // overflow
+ return false;
+ }
+
+ union Value {
+ T data;
+ uint8_t bytes[sizeof(T)];
+ };
+
+ Value value;
+ value.data = data;
+
+ uint8_t* target =
+ static_cast<uint8_t*>(buffer->backing_store()) + byte_offset;
+ DCHECK(Bytes <= sizeof(T));
+ CopyBytes<Bytes>(target, value.bytes);
+ return true;
+}
+
+
+#define SIMD128_LOAD_RUNTIME_FUNCTION(Type, ValueType, Lanes, Bytes) \
+RUNTIME_FUNCTION(Runtime_##Type##Load##Lanes) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 2); \
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 0); \
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \
+ ValueType result; \
+ if (SimdTypeLoadValue<ValueType, Bytes>( \
+ isolate, buffer, offset, &result)) { \
+ return *isolate->factory()->New##Type(result); \
+ } else { \
+ THROW_NEW_ERROR_RETURN_FAILURE( \
+ isolate, NewRangeError("invalid_offset", \
+ HandleVector<Object>(NULL, 0))); \
+ } \
+}
+
+
+SIMD128_LOAD_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XYZW, 16)
+SIMD128_LOAD_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XYZ, 12)
+SIMD128_LOAD_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XY, 8)
+SIMD128_LOAD_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, X, 4)
+SIMD128_LOAD_RUNTIME_FUNCTION(Float64x2, float64x2_value_t, XY, 16)
+SIMD128_LOAD_RUNTIME_FUNCTION(Float64x2, float64x2_value_t, X, 8)
+SIMD128_LOAD_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XYZW, 16)
+SIMD128_LOAD_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XYZ, 12)
+SIMD128_LOAD_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XY, 8)
+SIMD128_LOAD_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, X, 4)
+
+
+#define SIMD128_STORE_RUNTIME_FUNCTION(Type, ValueType, Lanes, Bytes) \
+RUNTIME_FUNCTION(Runtime_##Type##Store##Lanes) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 3); \
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 0); \
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \
+ CONVERT_ARG_CHECKED(Type, value, 2); \
+ ValueType v = value->get(); \
+ if (SimdTypeStoreValue<ValueType, Bytes>(isolate, buffer, offset, v)) { \
+ return isolate->heap()->undefined_value(); \
+ } else { \
+ THROW_NEW_ERROR_RETURN_FAILURE( \
+ isolate, NewRangeError("invalid_offset", \
+ HandleVector<Object>(NULL, 0))); \
+ } \
+}
+
+
+SIMD128_STORE_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XYZW, 16)
+SIMD128_STORE_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XYZ, 12)
+SIMD128_STORE_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XY, 8)
+SIMD128_STORE_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, X, 4)
+SIMD128_STORE_RUNTIME_FUNCTION(Float64x2, float64x2_value_t, XY, 16)
+SIMD128_STORE_RUNTIME_FUNCTION(Float64x2, float64x2_value_t, X, 8)
+SIMD128_STORE_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XYZW, 16)
+SIMD128_STORE_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XYZ, 12)
+SIMD128_STORE_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XY, 8)
+SIMD128_STORE_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, X, 4)
+
+
#define RETURN_Float32x4_RESULT(value) \
return *isolate->factory()->NewFloat32x4(value);