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/v8.h" | 5 #include "src/v8.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/runtime/runtime-utils.h" | 10 #include "src/runtime/runtime-utils.h" |
11 | 11 |
12 // Implement Single Instruction Multiple Data (SIMD) operations as defined in | 12 // Implement Single Instruction Multiple Data (SIMD) operations as defined in |
13 // the SIMD.js draft spec: | 13 // the SIMD.js draft spec: |
14 // http://littledan.github.io/simd.html | 14 // http://littledan.github.io/simd.html |
15 | 15 |
16 #define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \ | |
17 CONVERT_INT32_ARG_CHECKED(name, index); \ | |
18 RUNTIME_ASSERT(name >= 0 && name < lanes); | |
19 | |
20 #define SIMD_CREATE_NUMERIC_FUNCTION(type, lane_type, lane_count) \ | |
21 RUNTIME_FUNCTION(Runtime_Create##type) { \ | |
22 static const int kLaneCount = lane_count; \ | |
23 HandleScope scope(isolate); \ | |
24 DCHECK(args.length() == kLaneCount); \ | |
25 lane_type lanes[kLaneCount]; \ | |
26 for (int i = 0; i < kLaneCount; i++) { \ | |
27 CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, i); \ | |
28 lanes[i] = ConvertNumber<lane_type>(number->Number()); \ | |
29 } \ | |
30 return *isolate->factory()->New##type(lanes); \ | |
31 } | |
32 | |
33 #define SIMD_CREATE_BOOLEAN_FUNCTION(type, lane_count) \ | |
34 RUNTIME_FUNCTION(Runtime_Create##type) { \ | |
35 static const int kLaneCount = lane_count; \ | |
36 HandleScope scope(isolate); \ | |
37 DCHECK(args.length() == kLaneCount); \ | |
38 bool lanes[kLaneCount]; \ | |
39 for (int i = 0; i < kLaneCount; i++) { \ | |
40 lanes[i] = args[i]->BooleanValue(); \ | |
41 } \ | |
42 return *isolate->factory()->New##type(lanes); \ | |
43 } | |
44 | |
45 #define SIMD_CHECK_FUNCTION(type) \ | |
46 RUNTIME_FUNCTION(Runtime_##type##Check) { \ | |
47 HandleScope scope(isolate); \ | |
48 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
49 return *a; \ | |
50 } | |
51 | |
52 #define SIMD_EXTRACT_LANE_FUNCTION(type, lanes, extract_fn) \ | |
53 RUNTIME_FUNCTION(Runtime_##type##ExtractLane) { \ | |
54 HandleScope scope(isolate); \ | |
55 DCHECK(args.length() == 2); \ | |
56 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
57 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, lanes); \ | |
58 return *isolate->factory()->extract_fn(a->get_lane(lane)); \ | |
59 } | |
60 | |
61 #define SIMD_REPLACE_NUMERIC_LANE_FUNCTION(type, lane_type, lane_count) \ | |
62 RUNTIME_FUNCTION(Runtime_##type##ReplaceLane) { \ | |
63 static const int kLaneCount = lane_count; \ | |
64 HandleScope scope(isolate); \ | |
65 DCHECK(args.length() == 3); \ | |
66 CONVERT_ARG_HANDLE_CHECKED(type, simd, 0); \ | |
67 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, kLaneCount); \ | |
68 CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 2); \ | |
69 lane_type lanes[kLaneCount]; \ | |
70 for (int i = 0; i < kLaneCount; i++) { \ | |
71 lanes[i] = simd->get_lane(i); \ | |
72 } \ | |
73 lanes[lane] = ConvertNumber<lane_type>(number->Number()); \ | |
74 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
75 return *result; \ | |
76 } | |
77 | |
78 #define SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(type, lane_count) \ | |
79 RUNTIME_FUNCTION(Runtime_##type##ReplaceLane) { \ | |
80 static const int kLaneCount = lane_count; \ | |
81 HandleScope scope(isolate); \ | |
82 DCHECK(args.length() == 3); \ | |
83 CONVERT_ARG_HANDLE_CHECKED(type, simd, 0); \ | |
84 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, kLaneCount); \ | |
85 bool lanes[kLaneCount]; \ | |
86 for (int i = 0; i < kLaneCount; i++) { \ | |
87 lanes[i] = simd->get_lane(i); \ | |
88 } \ | |
89 lanes[lane] = args[2]->BooleanValue(); \ | |
90 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
91 return *result; \ | |
92 } | |
93 | |
94 | |
95 namespace v8 { | 16 namespace v8 { |
96 namespace internal { | 17 namespace internal { |
97 | 18 |
98 namespace { | 19 namespace { |
99 | 20 |
100 // Functions to convert Numbers to SIMD component types. | 21 // Functions to convert Numbers to SIMD component types. |
101 | 22 |
102 template <typename T> | 23 template <typename T> |
103 static T ConvertNumber(double number); | 24 static T ConvertNumber(double number); |
104 | 25 |
(...skipping 22 matching lines...) Expand all Loading... | |
127 } | 48 } |
128 | 49 |
129 | 50 |
130 bool Equals(Float32x4* a, Float32x4* b) { | 51 bool Equals(Float32x4* a, Float32x4* b) { |
131 for (int i = 0; i < 4; i++) { | 52 for (int i = 0; i < 4; i++) { |
132 if (a->get_lane(i) != b->get_lane(i)) return false; | 53 if (a->get_lane(i) != b->get_lane(i)) return false; |
133 } | 54 } |
134 return true; | 55 return true; |
135 } | 56 } |
136 | 57 |
58 | |
59 inline float RecipApprox(float a) { return 1.0f / a; } | |
60 | |
61 | |
62 inline float RecipSqrtApprox(float a) { return 1.0f / std::sqrt(a); } | |
Dan Ehrenberg
2015/08/06 00:12:25
We may have to revisit these at some point, to cre
bbudge
2015/08/06 14:07:32
I'll add a TODO.
| |
63 | |
64 | |
65 // Saturating addition for int16_t and int8_t. | |
66 template <typename T> | |
67 inline T AddSaturate(T a, T b) { | |
68 const T max = std::numeric_limits<T>::max(); | |
69 const T min = std::numeric_limits<T>::min(); | |
70 int32_t result = a + b; | |
71 if (result > max) return max; | |
72 if (result < min) return min; | |
73 return result; | |
74 } | |
75 | |
76 | |
77 // Saturating subtraction for int16_t and int8_t. | |
78 template <typename T> | |
79 inline T SubSaturate(T a, T b) { | |
80 const T max = std::numeric_limits<T>::max(); | |
81 const T min = std::numeric_limits<T>::min(); | |
82 int32_t result = a - b; | |
83 if (result > max) return max; | |
84 if (result < min) return min; | |
85 return result; | |
86 } | |
87 | |
88 | |
89 inline float Min(float a, float b) { | |
90 if (a < b) return a; | |
91 if (a > b) return b; | |
92 if (a == b) return std::signbit(a) ? a : b; | |
93 return std::numeric_limits<float>::quiet_NaN(); | |
94 } | |
95 | |
96 | |
97 inline float Max(float a, float b) { | |
98 if (a > b) return a; | |
99 if (a < b) return b; | |
100 if (a == b) return std::signbit(b) ? a : b; | |
101 return std::numeric_limits<float>::quiet_NaN(); | |
102 } | |
103 | |
104 | |
105 inline float MinNumber(float a, float b) { | |
106 if (std::isnan(a)) return b; | |
107 if (std::isnan(b)) return a; | |
108 return Min(a, b); | |
109 } | |
110 | |
111 | |
112 inline float MaxNumber(float a, float b) { | |
113 if (std::isnan(a)) return b; | |
114 if (std::isnan(b)) return a; | |
115 return Max(a, b); | |
116 } | |
117 | |
118 | |
119 inline bool CanCast(int32_t a) { return true; } | |
120 | |
121 | |
122 inline bool CanCast(float a) { | |
123 return a > std::numeric_limits<int32_t>::min() && | |
124 a < std::numeric_limits<int32_t>::max(); | |
125 } | |
126 | |
137 } // namespace | 127 } // namespace |
138 | 128 |
129 //------------------------------------------------------------------- | |
130 | |
131 // SIMD helper functions. | |
139 | 132 |
140 RUNTIME_FUNCTION(Runtime_IsSimdObject) { | 133 RUNTIME_FUNCTION(Runtime_IsSimdObject) { |
141 HandleScope scope(isolate); | 134 HandleScope scope(isolate); |
142 DCHECK(args.length() == 1); | 135 DCHECK(args.length() == 1); |
143 return isolate->heap()->ToBoolean(args[0]->IsSimd128Value()); | 136 return isolate->heap()->ToBoolean(args[0]->IsSimd128Value()); |
144 } | 137 } |
145 | 138 |
146 | 139 |
147 RUNTIME_FUNCTION(Runtime_SimdToObject) { | 140 RUNTIME_FUNCTION(Runtime_SimdToObject) { |
148 HandleScope scope(isolate); | 141 HandleScope scope(isolate); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
205 result = Float32x4::cast(*a)->SameValueZero(Float32x4::cast(b)); | 198 result = Float32x4::cast(*a)->SameValueZero(Float32x4::cast(b)); |
206 } else { | 199 } else { |
207 result = a->BitwiseEquals(b); | 200 result = a->BitwiseEquals(b); |
208 } | 201 } |
209 } | 202 } |
210 } | 203 } |
211 return isolate->heap()->ToBoolean(result); | 204 return isolate->heap()->ToBoolean(result); |
212 } | 205 } |
213 | 206 |
214 | 207 |
215 SIMD_CREATE_NUMERIC_FUNCTION(Float32x4, float, 4) | 208 //------------------------------------------------------------------- |
216 SIMD_CREATE_NUMERIC_FUNCTION(Int32x4, int32_t, 4) | 209 |
217 SIMD_CREATE_BOOLEAN_FUNCTION(Bool32x4, 4) | 210 // Utility macros. |
218 SIMD_CREATE_NUMERIC_FUNCTION(Int16x8, int16_t, 8) | 211 |
219 SIMD_CREATE_BOOLEAN_FUNCTION(Bool16x8, 8) | 212 #define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \ |
220 SIMD_CREATE_NUMERIC_FUNCTION(Int8x16, int8_t, 16) | 213 CONVERT_INT32_ARG_CHECKED(name, index); \ |
221 SIMD_CREATE_BOOLEAN_FUNCTION(Bool8x16, 16) | 214 RUNTIME_ASSERT(name >= 0 && name < lanes); |
222 | 215 |
223 | 216 #define SIMD_UNARY_OP(type, lane_type, lane_count, op, result) \ |
224 SIMD_CHECK_FUNCTION(Float32x4) | 217 static const int kLaneCount = lane_count; \ |
225 SIMD_CHECK_FUNCTION(Int32x4) | 218 DCHECK(args.length() == 1); \ |
226 SIMD_CHECK_FUNCTION(Bool32x4) | 219 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ |
227 SIMD_CHECK_FUNCTION(Int16x8) | 220 lane_type lanes[kLaneCount]; \ |
228 SIMD_CHECK_FUNCTION(Bool16x8) | 221 for (int i = 0; i < kLaneCount; i++) { \ |
229 SIMD_CHECK_FUNCTION(Int8x16) | 222 lanes[i] = op(a->get_lane(i)); \ |
230 SIMD_CHECK_FUNCTION(Bool8x16) | 223 } \ |
231 | 224 Handle<type> result = isolate->factory()->New##type(lanes); |
232 | 225 |
233 SIMD_EXTRACT_LANE_FUNCTION(Float32x4, 4, NewNumber) | 226 #define SIMD_BINARY_OP(type, lane_type, lane_count, op, result) \ |
234 SIMD_EXTRACT_LANE_FUNCTION(Int32x4, 4, NewNumber) | 227 static const int kLaneCount = lane_count; \ |
235 SIMD_EXTRACT_LANE_FUNCTION(Bool32x4, 4, ToBoolean) | 228 DCHECK(args.length() == 2); \ |
236 SIMD_EXTRACT_LANE_FUNCTION(Int16x8, 8, NewNumber) | 229 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ |
237 SIMD_EXTRACT_LANE_FUNCTION(Bool16x8, 8, ToBoolean) | 230 CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ |
238 SIMD_EXTRACT_LANE_FUNCTION(Int8x16, 16, NewNumber) | 231 lane_type lanes[kLaneCount]; \ |
239 SIMD_EXTRACT_LANE_FUNCTION(Bool8x16, 16, ToBoolean) | 232 for (int i = 0; i < kLaneCount; i++) { \ |
240 | 233 lanes[i] = op(a->get_lane(i), b->get_lane(i)); \ |
234 } \ | |
235 Handle<type> result = isolate->factory()->New##type(lanes); | |
236 | |
237 #define SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, op, result) \ | |
238 static const int kLaneCount = lane_count; \ | |
239 DCHECK(args.length() == 2); \ | |
240 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
241 CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ | |
242 bool lanes[kLaneCount]; \ | |
243 for (int i = 0; i < kLaneCount; i++) { \ | |
244 lanes[i] = a->get_lane(i) op b->get_lane(i); \ | |
245 } \ | |
246 Handle<bool_type> result = isolate->factory()->New##bool_type(lanes); | |
247 | |
248 //------------------------------------------------------------------- | |
249 | |
250 // Common functions. | |
251 | |
252 #define GET_NUMERIC_ARG(lane_type, name, index) \ | |
253 CONVERT_NUMBER_ARG_HANDLE_CHECKED(a, index); \ | |
254 name = ConvertNumber<lane_type>(a->Number()); | |
255 | |
256 #define GET_BOOLEAN_ARG(lane_type, name, index) \ | |
257 name = args[index]->BooleanValue(); | |
258 | |
259 #define SIMD_ALL_TYPES(FUNCTION) \ | |
260 FUNCTION(Float32x4, float, 4, NewNumber, GET_NUMERIC_ARG) \ | |
261 FUNCTION(Int32x4, int32_t, 4, NewNumber, GET_NUMERIC_ARG) \ | |
262 FUNCTION(Bool32x4, bool, 4, ToBoolean, GET_BOOLEAN_ARG) \ | |
263 FUNCTION(Int16x8, int16_t, 8, NewNumber, GET_NUMERIC_ARG) \ | |
264 FUNCTION(Bool16x8, bool, 8, ToBoolean, GET_BOOLEAN_ARG) \ | |
265 FUNCTION(Int8x16, int8_t, 16, NewNumber, GET_NUMERIC_ARG) \ | |
266 FUNCTION(Bool8x16, bool, 16, ToBoolean, GET_BOOLEAN_ARG) | |
267 | |
268 #define SIMD_CREATE_FUNCTION(type, lane_type, lane_count, extract, replace) \ | |
269 RUNTIME_FUNCTION(Runtime_Create##type) { \ | |
270 static const int kLaneCount = lane_count; \ | |
271 HandleScope scope(isolate); \ | |
272 DCHECK(args.length() == kLaneCount); \ | |
273 lane_type lanes[kLaneCount]; \ | |
274 for (int i = 0; i < kLaneCount; i++) { \ | |
275 replace(lane_type, lanes[i], i) \ | |
276 } \ | |
277 return *isolate->factory()->New##type(lanes); \ | |
278 } | |
279 | |
280 #define SIMD_EXTRACT_FUNCTION(type, lane_type, lane_count, extract, replace) \ | |
281 RUNTIME_FUNCTION(Runtime_##type##ExtractLane) { \ | |
282 HandleScope scope(isolate); \ | |
283 DCHECK(args.length() == 2); \ | |
284 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
285 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, lane_count); \ | |
286 return *isolate->factory()->extract(a->get_lane(lane)); \ | |
287 } | |
288 | |
289 #define SIMD_REPLACE_FUNCTION(type, lane_type, lane_count, extract, replace) \ | |
290 RUNTIME_FUNCTION(Runtime_##type##ReplaceLane) { \ | |
291 static const int kLaneCount = lane_count; \ | |
292 HandleScope scope(isolate); \ | |
293 DCHECK(args.length() == 3); \ | |
294 CONVERT_ARG_HANDLE_CHECKED(type, simd, 0); \ | |
295 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, kLaneCount); \ | |
296 lane_type lanes[kLaneCount]; \ | |
297 for (int i = 0; i < kLaneCount; i++) { \ | |
298 lanes[i] = simd->get_lane(i); \ | |
299 } \ | |
300 replace(lane_type, lanes[lane], 2); \ | |
301 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
302 return *result; \ | |
303 } | |
304 | |
305 #define SIMD_CHECK_FUNCTION(type, lane_type, lane_count, extract, replace) \ | |
306 RUNTIME_FUNCTION(Runtime_##type##Check) { \ | |
307 HandleScope scope(isolate); \ | |
308 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
309 return *a; \ | |
310 } | |
311 | |
312 #define SIMD_SWIZZLE_FUNCTION(type, lane_type, lane_count, extract, replace) \ | |
313 RUNTIME_FUNCTION(Runtime_##type##Swizzle) { \ | |
314 static const int kLaneCount = lane_count; \ | |
315 HandleScope scope(isolate); \ | |
316 DCHECK(args.length() == 1 + kLaneCount); \ | |
317 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
318 lane_type lanes[kLaneCount]; \ | |
319 for (int i = 0; i < kLaneCount; i++) { \ | |
320 CONVERT_SIMD_LANE_ARG_CHECKED(index, i + 1, kLaneCount); \ | |
321 lanes[i] = a->get_lane(index); \ | |
322 } \ | |
323 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
324 return *result; \ | |
325 } | |
326 | |
327 #define SIMD_SHUFFLE_FUNCTION(type, lane_type, lane_count, extract, replace) \ | |
328 RUNTIME_FUNCTION(Runtime_##type##Shuffle) { \ | |
329 static const int kLaneCount = lane_count; \ | |
330 HandleScope scope(isolate); \ | |
331 DCHECK(args.length() == 2 + kLaneCount); \ | |
332 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
333 CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ | |
334 lane_type lanes[kLaneCount]; \ | |
335 for (int i = 0; i < kLaneCount; i++) { \ | |
336 CONVERT_SIMD_LANE_ARG_CHECKED(index, i + 2, kLaneCount * 2); \ | |
337 lanes[i] = index < kLaneCount ? a->get_lane(index) \ | |
338 : b->get_lane(index - kLaneCount); \ | |
339 } \ | |
340 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
341 return *result; \ | |
342 } | |
343 | |
344 SIMD_ALL_TYPES(SIMD_CREATE_FUNCTION) | |
345 SIMD_ALL_TYPES(SIMD_EXTRACT_FUNCTION) | |
346 SIMD_ALL_TYPES(SIMD_REPLACE_FUNCTION) | |
347 SIMD_ALL_TYPES(SIMD_CHECK_FUNCTION) | |
348 SIMD_ALL_TYPES(SIMD_SWIZZLE_FUNCTION) | |
349 SIMD_ALL_TYPES(SIMD_SHUFFLE_FUNCTION) | |
350 | |
351 //------------------------------------------------------------------- | |
352 | |
353 // Float-only functions. | |
354 | |
355 #define SIMD_ABS_FUNCTION(type, lane_type, lane_count) \ | |
356 RUNTIME_FUNCTION(Runtime_##type##Abs) { \ | |
357 HandleScope scope(isolate); \ | |
358 SIMD_UNARY_OP(type, lane_type, lane_count, std::abs, result); \ | |
359 return *result; \ | |
360 } | |
361 | |
362 #define SIMD_SQRT_FUNCTION(type, lane_type, lane_count) \ | |
363 RUNTIME_FUNCTION(Runtime_##type##Sqrt) { \ | |
364 HandleScope scope(isolate); \ | |
365 SIMD_UNARY_OP(type, lane_type, lane_count, std::sqrt, result); \ | |
366 return *result; \ | |
367 } | |
368 | |
369 #define SIMD_RECIP_APPROX_FUNCTION(type, lane_type, lane_count) \ | |
370 RUNTIME_FUNCTION(Runtime_##type##RecipApprox) { \ | |
371 HandleScope scope(isolate); \ | |
372 SIMD_UNARY_OP(type, lane_type, lane_count, RecipApprox, result); \ | |
373 return *result; \ | |
374 } | |
375 | |
376 #define SIMD_RECIP_SQRT_APPROX_FUNCTION(type, lane_type, lane_count) \ | |
377 RUNTIME_FUNCTION(Runtime_##type##RecipSqrtApprox) { \ | |
378 HandleScope scope(isolate); \ | |
379 SIMD_UNARY_OP(type, lane_type, lane_count, RecipSqrtApprox, result); \ | |
380 return *result; \ | |
381 } | |
382 | |
383 #define BINARY_DIV(a, b) (a) / (b) | |
384 #define SIMD_DIV_FUNCTION(type, lane_type, lane_count) \ | |
385 RUNTIME_FUNCTION(Runtime_##type##Div) { \ | |
386 HandleScope scope(isolate); \ | |
387 SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_DIV, result); \ | |
388 return *result; \ | |
389 } | |
390 | |
391 #define SIMD_MINNUM_FUNCTION(type, lane_type, lane_count) \ | |
392 RUNTIME_FUNCTION(Runtime_##type##MinNum) { \ | |
393 HandleScope scope(isolate); \ | |
394 SIMD_BINARY_OP(type, lane_type, lane_count, MinNumber, result); \ | |
395 return *result; \ | |
396 } | |
397 | |
398 #define SIMD_MAXNUM_FUNCTION(type, lane_type, lane_count) \ | |
399 RUNTIME_FUNCTION(Runtime_##type##MaxNum) { \ | |
400 HandleScope scope(isolate); \ | |
401 SIMD_BINARY_OP(type, lane_type, lane_count, MaxNumber, result); \ | |
402 return *result; \ | |
403 } | |
404 | |
405 SIMD_ABS_FUNCTION(Float32x4, float, 4) | |
406 SIMD_SQRT_FUNCTION(Float32x4, float, 4) | |
407 SIMD_RECIP_APPROX_FUNCTION(Float32x4, float, 4) | |
408 SIMD_RECIP_SQRT_APPROX_FUNCTION(Float32x4, float, 4) | |
409 SIMD_DIV_FUNCTION(Float32x4, float, 4) | |
410 SIMD_MINNUM_FUNCTION(Float32x4, float, 4) | |
411 SIMD_MAXNUM_FUNCTION(Float32x4, float, 4) | |
412 | |
413 //------------------------------------------------------------------- | |
414 | |
415 // Int-only functions. | |
416 | |
417 #define SIMD_INT_TYPES(FUNCTION) \ | |
418 FUNCTION(Int32x4, int32_t, 0xffffffff, 4) \ | |
419 FUNCTION(Int16x8, int16_t, 0xffff, 8) \ | |
420 FUNCTION(Int8x16, int8_t, 0xff, 16) | |
421 | |
422 #define SIMD_SHIFT_LEFT_FUNCTION(type, lane_type, mask, lane_count) \ | |
423 RUNTIME_FUNCTION(Runtime_##type##ShiftLeftByScalar) { \ | |
424 static const int kLaneCount = lane_count; \ | |
425 HandleScope scope(isolate); \ | |
426 DCHECK(args.length() == 2); \ | |
427 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
428 CONVERT_INT32_ARG_CHECKED(shift, 1); \ | |
429 shift = shift & 0x3f; \ | |
Dan Ehrenberg
2015/08/06 00:12:25
Looks like you're implementing wrap-around behavio
bbudge
2015/08/06 14:07:32
Done.
| |
430 lane_type lanes[kLaneCount]; \ | |
431 for (int i = 0; i < kLaneCount; i++) { \ | |
432 int64_t shifted = static_cast<int64_t>(a->get_lane(i)) << shift; \ | |
433 lanes[i] = static_cast<lane_type>(shifted); \ | |
434 } \ | |
435 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
436 return *result; \ | |
437 } | |
438 | |
439 #define SIMD_SHIFT_RIGHT_LOGICAL_FUNCTION(type, lane_type, mask, lane_count) \ | |
440 RUNTIME_FUNCTION(Runtime_##type##ShiftRightLogicalByScalar) { \ | |
441 static const int kLaneCount = lane_count; \ | |
442 HandleScope scope(isolate); \ | |
443 DCHECK(args.length() == 2); \ | |
444 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
445 CONVERT_INT32_ARG_CHECKED(shift, 1); \ | |
446 shift = shift & 0x3f; \ | |
447 lane_type lanes[kLaneCount]; \ | |
448 for (int i = 0; i < kLaneCount; i++) { \ | |
449 int64_t shifted = \ | |
450 (static_cast<int64_t>(a->get_lane(i)) & mask) >> shift; \ | |
451 lanes[i] = static_cast<lane_type>(shifted); \ | |
452 } \ | |
453 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
454 return *result; \ | |
455 } | |
456 | |
457 #define SIMD_SHIFT_RIGHT_ARITHMETIC_FUNCTION(type, lane_type, mask, \ | |
458 lane_count) \ | |
459 RUNTIME_FUNCTION(Runtime_##type##ShiftRightArithmeticByScalar) { \ | |
460 static const int kLaneCount = lane_count; \ | |
461 HandleScope scope(isolate); \ | |
462 DCHECK(args.length() == 2); \ | |
463 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
464 CONVERT_INT32_ARG_CHECKED(shift, 1); \ | |
465 shift = shift & 0x3f; \ | |
466 lane_type lanes[kLaneCount]; \ | |
467 for (int i = 0; i < kLaneCount; i++) { \ | |
468 int64_t shifted = static_cast<int64_t>(a->get_lane(i)) >> shift; \ | |
469 lanes[i] = static_cast<lane_type>(shifted); \ | |
470 } \ | |
471 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
472 return *result; \ | |
473 } | |
474 | |
475 SIMD_INT_TYPES(SIMD_SHIFT_LEFT_FUNCTION) | |
476 SIMD_INT_TYPES(SIMD_SHIFT_RIGHT_LOGICAL_FUNCTION) | |
477 SIMD_INT_TYPES(SIMD_SHIFT_RIGHT_ARITHMETIC_FUNCTION) | |
478 | |
479 //------------------------------------------------------------------- | |
480 | |
481 // Bool-only functions. | |
482 | |
483 #define SIMD_BOOL_TYPES(FUNCTION) \ | |
484 FUNCTION(Bool32x4, 4) \ | |
485 FUNCTION(Bool16x8, 8) \ | |
486 FUNCTION(Bool8x16, 16) | |
487 | |
488 #define SIMD_ANY_FUNCTION(type, lane_count) \ | |
489 RUNTIME_FUNCTION(Runtime_##type##AnyTrue) { \ | |
490 HandleScope scope(isolate); \ | |
491 DCHECK(args.length() == 1); \ | |
492 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
493 bool result = false; \ | |
494 for (int i = 0; i < lane_count; i++) { \ | |
495 if (a->get_lane(i)) { \ | |
496 result = true; \ | |
497 break; \ | |
498 } \ | |
499 } \ | |
500 return isolate->heap()->ToBoolean(result); \ | |
501 } | |
502 | |
503 #define SIMD_ALL_FUNCTION(type, lane_count) \ | |
504 RUNTIME_FUNCTION(Runtime_##type##AllTrue) { \ | |
505 HandleScope scope(isolate); \ | |
506 DCHECK(args.length() == 1); \ | |
507 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ | |
508 bool result = true; \ | |
509 for (int i = 0; i < lane_count; i++) { \ | |
510 if (!a->get_lane(i)) { \ | |
511 result = false; \ | |
512 break; \ | |
513 } \ | |
514 } \ | |
515 return isolate->heap()->ToBoolean(result); \ | |
516 } | |
517 | |
518 SIMD_BOOL_TYPES(SIMD_ANY_FUNCTION) | |
519 SIMD_BOOL_TYPES(SIMD_ALL_FUNCTION) | |
520 | |
521 //------------------------------------------------------------------- | |
522 | |
523 // Small Int-only functions. | |
524 | |
525 #define SIMD_SMALL_INT_TYPES(FUNCTION) \ | |
526 FUNCTION(Int16x8, int16_t, 8) \ | |
527 FUNCTION(Int8x16, int8_t, 16) | |
528 | |
529 #define SIMD_ADD_SATURATE_FUNCTION(type, lane_type, lane_count) \ | |
530 RUNTIME_FUNCTION(Runtime_##type##AddSaturate) { \ | |
531 HandleScope scope(isolate); \ | |
532 SIMD_BINARY_OP(type, lane_type, lane_count, AddSaturate, result); \ | |
533 return *result; \ | |
534 } | |
535 | |
536 #define BINARY_SUB(a, b) (a) - (b) | |
537 #define SIMD_SUB_SATURATE_FUNCTION(type, lane_type, lane_count) \ | |
538 RUNTIME_FUNCTION(Runtime_##type##SubSaturate) { \ | |
539 HandleScope scope(isolate); \ | |
540 SIMD_BINARY_OP(type, lane_type, lane_count, SubSaturate, result); \ | |
541 return *result; \ | |
542 } | |
543 | |
544 SIMD_SMALL_INT_TYPES(SIMD_ADD_SATURATE_FUNCTION) | |
545 SIMD_SMALL_INT_TYPES(SIMD_SUB_SATURATE_FUNCTION) | |
546 | |
547 //------------------------------------------------------------------- | |
548 | |
549 // Numeric functions. | |
550 | |
551 #define SIMD_NUMERIC_TYPES(FUNCTION) \ | |
552 FUNCTION(Float32x4, float, 4) \ | |
553 FUNCTION(Int32x4, int32_t, 4) \ | |
554 FUNCTION(Int16x8, int16_t, 8) \ | |
555 FUNCTION(Int8x16, int8_t, 16) | |
556 | |
557 #define SIMD_NEG_FUNCTION(type, lane_type, lane_count) \ | |
558 RUNTIME_FUNCTION(Runtime_##type##Neg) { \ | |
559 HandleScope scope(isolate); \ | |
560 SIMD_UNARY_OP(type, lane_type, lane_count, -, result); \ | |
561 return *result; \ | |
562 } | |
563 | |
564 #define BINARY_ADD(a, b) (a) + (b) | |
Dan Ehrenberg
2015/08/06 00:12:25
We'll have to revisit ops like this for proper den
| |
565 #define SIMD_ADD_FUNCTION(type, lane_type, lane_count) \ | |
566 RUNTIME_FUNCTION(Runtime_##type##Add) { \ | |
567 HandleScope scope(isolate); \ | |
568 SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_ADD, result); \ | |
569 return *result; \ | |
570 } | |
571 | |
572 #define BINARY_SUB(a, b) (a) - (b) | |
573 #define SIMD_SUB_FUNCTION(type, lane_type, lane_count) \ | |
574 RUNTIME_FUNCTION(Runtime_##type##Sub) { \ | |
575 HandleScope scope(isolate); \ | |
576 SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_SUB, result); \ | |
577 return *result; \ | |
578 } | |
579 | |
580 #define BINARY_MUL(a, b) (a) * (b) | |
581 #define SIMD_MUL_FUNCTION(type, lane_type, lane_count) \ | |
582 RUNTIME_FUNCTION(Runtime_##type##Mul) { \ | |
583 HandleScope scope(isolate); \ | |
584 SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_MUL, result); \ | |
585 return *result; \ | |
586 } | |
587 | |
588 #define SIMD_MIN_FUNCTION(type, lane_type, lane_count) \ | |
589 RUNTIME_FUNCTION(Runtime_##type##Min) { \ | |
590 HandleScope scope(isolate); \ | |
591 SIMD_BINARY_OP(type, lane_type, lane_count, Min, result); \ | |
592 return *result; \ | |
593 } | |
594 | |
595 #define SIMD_MAX_FUNCTION(type, lane_type, lane_count) \ | |
596 RUNTIME_FUNCTION(Runtime_##type##Max) { \ | |
597 HandleScope scope(isolate); \ | |
598 SIMD_BINARY_OP(type, lane_type, lane_count, Max, result); \ | |
599 return *result; \ | |
600 } | |
601 | |
602 SIMD_NUMERIC_TYPES(SIMD_NEG_FUNCTION) | |
603 SIMD_NUMERIC_TYPES(SIMD_ADD_FUNCTION) | |
604 SIMD_NUMERIC_TYPES(SIMD_SUB_FUNCTION) | |
605 SIMD_NUMERIC_TYPES(SIMD_MUL_FUNCTION) | |
606 SIMD_NUMERIC_TYPES(SIMD_MIN_FUNCTION) | |
607 SIMD_NUMERIC_TYPES(SIMD_MAX_FUNCTION) | |
608 | |
609 //------------------------------------------------------------------- | |
610 | |
611 // Relational functions. | |
612 | |
613 #define SIMD_RELATIONAL_TYPES(FUNCTION) \ | |
614 FUNCTION(Float32x4, Bool32x4, 4) \ | |
615 FUNCTION(Int32x4, Bool32x4, 4) \ | |
616 FUNCTION(Int16x8, Bool16x8, 8) \ | |
617 FUNCTION(Int8x16, Bool8x16, 16) | |
618 | |
619 #define SIMD_EQUALITY_TYPES(FUNCTION) \ | |
620 SIMD_RELATIONAL_TYPES(FUNCTION) \ | |
621 FUNCTION(Bool32x4, Bool32x4, 4) \ | |
622 FUNCTION(Bool16x8, Bool16x8, 8) \ | |
623 FUNCTION(Bool8x16, Bool8x16, 16) | |
624 | |
625 #define SIMD_EQUAL_FUNCTION(type, bool_type, lane_count) \ | |
626 RUNTIME_FUNCTION(Runtime_##type##Equal) { \ | |
627 HandleScope scope(isolate); \ | |
628 SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, ==, result); \ | |
629 return *result; \ | |
630 } | |
631 | |
632 #define SIMD_NOT_EQUAL_FUNCTION(type, bool_type, lane_count) \ | |
633 RUNTIME_FUNCTION(Runtime_##type##NotEqual) { \ | |
634 HandleScope scope(isolate); \ | |
635 SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, !=, result); \ | |
636 return *result; \ | |
637 } | |
638 | |
639 SIMD_EQUALITY_TYPES(SIMD_EQUAL_FUNCTION) | |
640 SIMD_EQUALITY_TYPES(SIMD_NOT_EQUAL_FUNCTION) | |
641 | |
642 #define SIMD_LESS_THAN_FUNCTION(type, bool_type, lane_count) \ | |
643 RUNTIME_FUNCTION(Runtime_##type##LessThan) { \ | |
644 HandleScope scope(isolate); \ | |
645 SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, <, result); \ | |
646 return *result; \ | |
647 } | |
648 | |
649 #define SIMD_LESS_THAN_OR_EQUAL_FUNCTION(type, bool_type, lane_count) \ | |
650 RUNTIME_FUNCTION(Runtime_##type##LessThanOrEqual) { \ | |
651 HandleScope scope(isolate); \ | |
652 SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, <=, result); \ | |
653 return *result; \ | |
654 } | |
655 | |
656 #define SIMD_GREATER_THAN_FUNCTION(type, bool_type, lane_count) \ | |
657 RUNTIME_FUNCTION(Runtime_##type##GreaterThan) { \ | |
658 HandleScope scope(isolate); \ | |
659 SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, >, result); \ | |
660 return *result; \ | |
661 } | |
662 | |
663 #define SIMD_GREATER_THAN_OR_EQUAL_FUNCTION(type, bool_type, lane_count) \ | |
664 RUNTIME_FUNCTION(Runtime_##type##GreaterThanOrEqual) { \ | |
665 HandleScope scope(isolate); \ | |
666 SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, >=, result); \ | |
667 return *result; \ | |
668 } | |
669 | |
670 SIMD_RELATIONAL_TYPES(SIMD_LESS_THAN_FUNCTION) | |
671 SIMD_RELATIONAL_TYPES(SIMD_LESS_THAN_OR_EQUAL_FUNCTION) | |
672 SIMD_RELATIONAL_TYPES(SIMD_GREATER_THAN_FUNCTION) | |
673 SIMD_RELATIONAL_TYPES(SIMD_GREATER_THAN_OR_EQUAL_FUNCTION) | |
674 | |
675 //------------------------------------------------------------------- | |
676 | |
677 // Logical functions. | |
678 | |
679 #define SIMD_LOGICAL_TYPES(FUNCTION) \ | |
680 FUNCTION(Int32x4, int32_t, 4, _INT) \ | |
681 FUNCTION(Int16x8, int16_t, 8, _INT) \ | |
682 FUNCTION(Int8x16, int8_t, 16, _INT) \ | |
683 FUNCTION(Bool32x4, bool, 4, _BOOL) \ | |
684 FUNCTION(Bool16x8, bool, 8, _BOOL) \ | |
685 FUNCTION(Bool8x16, bool, 16, _BOOL) | |
686 | |
687 #define BINARY_AND_INT(a, b) (a) & (b) | |
688 #define BINARY_AND_BOOL(a, b) (a) && (b) | |
689 #define SIMD_AND_FUNCTION(type, lane_type, lane_count, op) \ | |
690 RUNTIME_FUNCTION(Runtime_##type##And) { \ | |
691 HandleScope scope(isolate); \ | |
692 SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_AND##op, result); \ | |
693 return *result; \ | |
694 } | |
695 | |
696 #define BINARY_OR_INT(a, b) (a) | (b) | |
697 #define BINARY_OR_BOOL(a, b) (a) || (b) | |
698 #define SIMD_OR_FUNCTION(type, lane_type, lane_count, op) \ | |
699 RUNTIME_FUNCTION(Runtime_##type##Or) { \ | |
700 HandleScope scope(isolate); \ | |
701 SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_OR##op, result); \ | |
702 return *result; \ | |
703 } | |
704 | |
705 #define BINARY_XOR_INT(a, b) (a) ^ (b) | |
706 #define BINARY_XOR_BOOL(a, b) (a) != (b) | |
707 #define SIMD_XOR_FUNCTION(type, lane_type, lane_count, op) \ | |
708 RUNTIME_FUNCTION(Runtime_##type##Xor) { \ | |
709 HandleScope scope(isolate); \ | |
710 SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_XOR##op, result); \ | |
711 return *result; \ | |
712 } | |
713 | |
714 #define UNARY_NOT_INT ~ | |
715 #define UNARY_NOT_BOOL ! | |
716 #define SIMD_NOT_FUNCTION(type, lane_type, lane_count, op) \ | |
717 RUNTIME_FUNCTION(Runtime_##type##Not) { \ | |
718 HandleScope scope(isolate); \ | |
719 SIMD_UNARY_OP(type, lane_type, lane_count, UNARY_NOT##op, result); \ | |
720 return *result; \ | |
721 } | |
722 | |
723 SIMD_LOGICAL_TYPES(SIMD_AND_FUNCTION) | |
724 SIMD_LOGICAL_TYPES(SIMD_OR_FUNCTION) | |
725 SIMD_LOGICAL_TYPES(SIMD_XOR_FUNCTION) | |
726 SIMD_LOGICAL_TYPES(SIMD_NOT_FUNCTION) | |
727 | |
728 //------------------------------------------------------------------- | |
729 | |
730 // Select functions. | |
731 | |
732 #define SIMD_SELECT_TYPES(FUNCTION) \ | |
733 FUNCTION(Float32x4, float, Bool32x4, 4) \ | |
734 FUNCTION(Int32x4, int32_t, Bool32x4, 4) \ | |
735 FUNCTION(Int16x8, int16_t, Bool16x8, 8) \ | |
736 FUNCTION(Int8x16, int8_t, Bool8x16, 16) \ | |
737 FUNCTION(Bool32x4, bool, Bool32x4, 4) \ | |
738 FUNCTION(Bool16x8, bool, Bool16x8, 8) \ | |
739 FUNCTION(Bool8x16, bool, Bool8x16, 16) | |
740 | |
741 #define SIMD_SELECT_FUNCTION(type, lane_type, bool_type, lane_count) \ | |
742 RUNTIME_FUNCTION(Runtime_##type##Select) { \ | |
743 static const int kLaneCount = lane_count; \ | |
744 HandleScope scope(isolate); \ | |
745 DCHECK(args.length() == 3); \ | |
746 CONVERT_ARG_HANDLE_CHECKED(bool_type, mask, 0); \ | |
747 CONVERT_ARG_HANDLE_CHECKED(type, a, 1); \ | |
748 CONVERT_ARG_HANDLE_CHECKED(type, b, 2); \ | |
749 lane_type lanes[kLaneCount]; \ | |
750 for (int i = 0; i < kLaneCount; i++) { \ | |
751 lanes[i] = mask->get_lane(i) ? a->get_lane(i) : b->get_lane(i); \ | |
752 } \ | |
753 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
754 return *result; \ | |
755 } | |
756 | |
757 SIMD_SELECT_TYPES(SIMD_SELECT_FUNCTION) | |
758 | |
759 //------------------------------------------------------------------- | |
760 | |
761 // Casting functions. | |
762 | |
763 #define SIMD_FROM_TYPES(FUNCTION) \ | |
764 FUNCTION(Float32x4, float, 4, Int32x4, int32_t) \ | |
765 FUNCTION(Int32x4, int32_t, 4, Float32x4, float) | |
766 | |
767 #define SIMD_FROM_FUNCTION(type, lane_type, lane_count, from_type, from_ctype) \ | |
768 RUNTIME_FUNCTION(Runtime_##type##From##from_type) { \ | |
769 static const int kLaneCount = lane_count; \ | |
770 HandleScope scope(isolate); \ | |
771 DCHECK(args.length() == 1); \ | |
772 CONVERT_ARG_HANDLE_CHECKED(from_type, a, 0); \ | |
773 lane_type lanes[kLaneCount]; \ | |
774 for (int i = 0; i < kLaneCount; i++) { \ | |
775 from_ctype a_value = a->get_lane(i); \ | |
776 RUNTIME_ASSERT(CanCast(a_value)); \ | |
777 lanes[i] = static_cast<lane_type>(a_value); \ | |
778 } \ | |
779 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
780 return *result; \ | |
781 } | |
782 | |
783 SIMD_FROM_TYPES(SIMD_FROM_FUNCTION) | |
784 | |
785 #define SIMD_FROM_BITS_TYPES(FUNCTION) \ | |
786 FUNCTION(Float32x4, float, 4, Int32x4) \ | |
787 FUNCTION(Float32x4, float, 4, Int16x8) \ | |
788 FUNCTION(Float32x4, float, 4, Int8x16) \ | |
789 FUNCTION(Int32x4, int32_t, 4, Float32x4) \ | |
790 FUNCTION(Int32x4, int32_t, 4, Int16x8) \ | |
791 FUNCTION(Int32x4, int32_t, 4, Int8x16) \ | |
792 FUNCTION(Int16x8, int16_t, 8, Float32x4) \ | |
793 FUNCTION(Int16x8, int16_t, 8, Int32x4) \ | |
794 FUNCTION(Int16x8, int16_t, 8, Int8x16) \ | |
795 FUNCTION(Int8x16, int8_t, 16, Float32x4) \ | |
796 FUNCTION(Int8x16, int8_t, 16, Int32x4) \ | |
797 FUNCTION(Int8x16, int8_t, 16, Int16x8) | |
798 | |
799 #define SIMD_FROM_BITS_FUNCTION(type, lane_type, lane_count, from_type) \ | |
800 RUNTIME_FUNCTION(Runtime_##type##From##from_type##Bits) { \ | |
801 static const int kLaneCount = lane_count; \ | |
802 HandleScope scope(isolate); \ | |
803 DCHECK(args.length() == 1); \ | |
804 CONVERT_ARG_HANDLE_CHECKED(from_type, a, 0); \ | |
805 lane_type lanes[kLaneCount]; \ | |
806 a->CopyBits(lanes); \ | |
807 Handle<type> result = isolate->factory()->New##type(lanes); \ | |
808 return *result; \ | |
809 } | |
810 | |
811 SIMD_FROM_BITS_TYPES(SIMD_FROM_BITS_FUNCTION) | |
812 | |
813 //------------------------------------------------------------------- | |
814 | |
815 // Unsigned extract functions. | |
816 // TODO(bbudge): remove when spec changes to include unsigned int types. | |
241 | 817 |
242 RUNTIME_FUNCTION(Runtime_Int16x8UnsignedExtractLane) { | 818 RUNTIME_FUNCTION(Runtime_Int16x8UnsignedExtractLane) { |
243 HandleScope scope(isolate); | 819 HandleScope scope(isolate); |
244 DCHECK(args.length() == 2); | 820 DCHECK(args.length() == 2); |
245 CONVERT_ARG_HANDLE_CHECKED(Int16x8, a, 0); | 821 CONVERT_ARG_HANDLE_CHECKED(Int16x8, a, 0); |
246 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, 8); | 822 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, 8); |
247 return *isolate->factory()->NewNumber(bit_cast<uint16_t>(a->get_lane(lane))); | 823 return *isolate->factory()->NewNumber(bit_cast<uint16_t>(a->get_lane(lane))); |
248 } | 824 } |
249 | 825 |
250 | 826 |
251 RUNTIME_FUNCTION(Runtime_Int8x16UnsignedExtractLane) { | 827 RUNTIME_FUNCTION(Runtime_Int8x16UnsignedExtractLane) { |
252 HandleScope scope(isolate); | 828 HandleScope scope(isolate); |
253 DCHECK(args.length() == 2); | 829 DCHECK(args.length() == 2); |
254 CONVERT_ARG_HANDLE_CHECKED(Int8x16, a, 0); | 830 CONVERT_ARG_HANDLE_CHECKED(Int8x16, a, 0); |
255 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, 16); | 831 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, 16); |
256 return *isolate->factory()->NewNumber(bit_cast<uint8_t>(a->get_lane(lane))); | 832 return *isolate->factory()->NewNumber(bit_cast<uint8_t>(a->get_lane(lane))); |
257 } | 833 } |
258 | |
259 | |
260 SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Float32x4, float, 4) | |
261 SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Int32x4, int32_t, 4) | |
262 SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(Bool32x4, 4) | |
263 SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Int16x8, int16_t, 8) | |
264 SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(Bool16x8, 8) | |
265 SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Int8x16, int8_t, 16) | |
266 SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(Bool8x16, 16) | |
267 } // namespace internal | 834 } // namespace internal |
268 } // namespace v8 | 835 } // namespace v8 |
OLD | NEW |