| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "src/v8.h" |
| 6 |
| 7 #include "src/arguments.h" |
| 8 #include "src/base/macros.h" |
| 9 #include "src/conversions.h" |
| 10 #include "src/runtime/runtime-utils.h" |
| 11 |
| 12 // Implement Single Instruction Multiple Data (SIMD) operations as defined in |
| 13 // the SIMD.js draft spec: |
| 14 // http://littledan.github.io/simd.html |
| 15 |
| 16 #define NumberToFloat32x4Component NumberToFloat |
| 17 |
| 18 #define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \ |
| 19 RUNTIME_ASSERT(args[index]->IsSmi()); \ |
| 20 int name = args.smi_at(index); \ |
| 21 RUNTIME_ASSERT(name >= 0 && name < lanes); |
| 22 |
| 23 #define SIMD_CHECK_FUNCTION(type) \ |
| 24 RUNTIME_FUNCTION(Runtime_##type##Check) { \ |
| 25 HandleScope scope(isolate); \ |
| 26 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ |
| 27 return *a; \ |
| 28 } |
| 29 |
| 30 #define SIMD4_CHECK_FUNCTION SIMD_CHECK_FUNCTION |
| 31 |
| 32 #define SIMD_EXTRACT_LANE_FUNCTION(type, lanes) \ |
| 33 RUNTIME_FUNCTION(Runtime_##type##ExtractLane) { \ |
| 34 HandleScope scope(isolate); \ |
| 35 DCHECK(args.length() == 2); \ |
| 36 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ |
| 37 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, lanes); \ |
| 38 return *isolate->factory()->NewNumber(a->get_lane(lane)); \ |
| 39 } |
| 40 |
| 41 #define SIMD4_EXTRACT_LANE_FUNCTION(type) SIMD_EXTRACT_LANE_FUNCTION(type, 4) |
| 42 |
| 43 #define SIMD4_CREATE_FUNCTION(type) \ |
| 44 RUNTIME_FUNCTION(Runtime_Create##type) { \ |
| 45 HandleScope scope(isolate); \ |
| 46 DCHECK(args.length() == 4); \ |
| 47 CONVERT_NUMBER_ARG_HANDLE_CHECKED(w, 0); \ |
| 48 CONVERT_NUMBER_ARG_HANDLE_CHECKED(x, 1); \ |
| 49 CONVERT_NUMBER_ARG_HANDLE_CHECKED(y, 2); \ |
| 50 CONVERT_NUMBER_ARG_HANDLE_CHECKED(z, 3); \ |
| 51 return *isolate->factory()->NewFloat32x4( \ |
| 52 NumberTo##type##Component(*w), NumberTo##type##Component(*x), \ |
| 53 NumberTo##type##Component(*y), NumberTo##type##Component(*z)); \ |
| 54 } |
| 55 |
| 56 #define SIMD4_REPLACE_LANE_FUNCTION(type) \ |
| 57 RUNTIME_FUNCTION(Runtime_##type##ReplaceLane) { \ |
| 58 HandleScope scope(isolate); \ |
| 59 DCHECK(args.length() == 3); \ |
| 60 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ |
| 61 CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, 4); \ |
| 62 CONVERT_NUMBER_ARG_HANDLE_CHECKED(replacement, 2); \ |
| 63 Handle<type> result = isolate->factory()->New##type( \ |
| 64 a->get_lane(0), a->get_lane(1), a->get_lane(2), a->get_lane(3)); \ |
| 65 result->set_lane(lane, NumberTo##type##Component(*replacement)); \ |
| 66 return *result; \ |
| 67 } |
| 68 |
| 69 #define SIMD4_UNARY_OP(type, a, op, result) \ |
| 70 DCHECK(args.length() == 1); \ |
| 71 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ |
| 72 Handle<type> result = \ |
| 73 isolate->factory()->New##type(op(a->get_lane(0)), op(a->get_lane(1)), \ |
| 74 op(a->get_lane(2)), op(a->get_lane(3))); |
| 75 |
| 76 #define SIMD4_ABS_FUNCTION(type) \ |
| 77 RUNTIME_FUNCTION(Runtime_##type##Abs) { \ |
| 78 HandleScope scope(isolate); \ |
| 79 SIMD4_UNARY_OP(type, a, std::abs, result); \ |
| 80 return *result; \ |
| 81 } |
| 82 |
| 83 #define SIMD4_NEG_FUNCTION(type) \ |
| 84 RUNTIME_FUNCTION(Runtime_##type##Neg) { \ |
| 85 HandleScope scope(isolate); \ |
| 86 SIMD4_UNARY_OP(type, a, -, result); \ |
| 87 return *result; \ |
| 88 } |
| 89 |
| 90 #define SIMD4_SQRT_FUNCTION(type) \ |
| 91 RUNTIME_FUNCTION(Runtime_##type##Sqrt) { \ |
| 92 HandleScope scope(isolate); \ |
| 93 SIMD4_UNARY_OP(type, a, std::sqrt, result); \ |
| 94 return *result; \ |
| 95 } |
| 96 |
| 97 #define SIMD4_RECIP_APPROX_FUNCTION(type) \ |
| 98 RUNTIME_FUNCTION(Runtime_##type##RecipApprox) { \ |
| 99 HandleScope scope(isolate); \ |
| 100 SIMD4_UNARY_OP(type, a, RecipApprox, result); \ |
| 101 return *result; \ |
| 102 } |
| 103 |
| 104 #define SIMD4_RECIP_SQRT_APPROX_FUNCTION(type) \ |
| 105 RUNTIME_FUNCTION(Runtime_##type##RecipSqrtApprox) { \ |
| 106 HandleScope scope(isolate); \ |
| 107 SIMD4_UNARY_OP(type, a, RecipSqrtApprox, result); \ |
| 108 return *result; \ |
| 109 } |
| 110 |
| 111 #define SIMD4_BINARY_OP(type, a, b, op, result) \ |
| 112 DCHECK(args.length() == 2); \ |
| 113 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ |
| 114 CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ |
| 115 Handle<type> result = isolate->factory()->New##type( \ |
| 116 op(a->get_lane(0), b->get_lane(0)), op(a->get_lane(1), b->get_lane(1)), \ |
| 117 op(a->get_lane(2), b->get_lane(2)), op(a->get_lane(3), b->get_lane(3))); |
| 118 |
| 119 // Macros to make infix arithmetic operators look like f(a, b). |
| 120 #define BINARY_ADD(a, b) (a) + (b) |
| 121 #define BINARY_SUB(a, b) (a) - (b) |
| 122 #define BINARY_MUL(a, b) (a) * (b) |
| 123 #define BINARY_DIV(a, b) (a) / (b) |
| 124 |
| 125 #define SIMD4_ADD_FUNCTION(type) \ |
| 126 RUNTIME_FUNCTION(Runtime_##type##Add) { \ |
| 127 HandleScope scope(isolate); \ |
| 128 SIMD4_BINARY_OP(type, a, b, BINARY_ADD, result); \ |
| 129 return *result; \ |
| 130 } |
| 131 |
| 132 #define SIMD4_SUB_FUNCTION(type) \ |
| 133 RUNTIME_FUNCTION(Runtime_##type##Sub) { \ |
| 134 HandleScope scope(isolate); \ |
| 135 SIMD4_BINARY_OP(type, a, b, BINARY_SUB, result); \ |
| 136 return *result; \ |
| 137 } |
| 138 |
| 139 #define SIMD4_MUL_FUNCTION(type) \ |
| 140 RUNTIME_FUNCTION(Runtime_##type##Mul) { \ |
| 141 HandleScope scope(isolate); \ |
| 142 SIMD4_BINARY_OP(type, a, b, BINARY_MUL, result); \ |
| 143 return *result; \ |
| 144 } |
| 145 |
| 146 #define SIMD4_DIV_FUNCTION(type) \ |
| 147 RUNTIME_FUNCTION(Runtime_##type##Div) { \ |
| 148 HandleScope scope(isolate); \ |
| 149 SIMD4_BINARY_OP(type, a, b, BINARY_DIV, result); \ |
| 150 return *result; \ |
| 151 } |
| 152 |
| 153 #define SIMD4_MIN_FUNCTION(type) \ |
| 154 RUNTIME_FUNCTION(Runtime_##type##Min) { \ |
| 155 HandleScope scope(isolate); \ |
| 156 SIMD4_BINARY_OP(type, a, b, Min, result); \ |
| 157 return *result; \ |
| 158 } |
| 159 |
| 160 #define SIMD4_MAX_FUNCTION(type) \ |
| 161 RUNTIME_FUNCTION(Runtime_##type##Max) { \ |
| 162 HandleScope scope(isolate); \ |
| 163 SIMD4_BINARY_OP(type, a, b, Max, result); \ |
| 164 return *result; \ |
| 165 } |
| 166 |
| 167 #define SIMD4_MINNUM_FUNCTION(type) \ |
| 168 RUNTIME_FUNCTION(Runtime_##type##MinNum) { \ |
| 169 HandleScope scope(isolate); \ |
| 170 SIMD4_BINARY_OP(type, a, b, MinNumber, result); \ |
| 171 return *result; \ |
| 172 } |
| 173 |
| 174 #define SIMD4_MAXNUM_FUNCTION(type) \ |
| 175 RUNTIME_FUNCTION(Runtime_##type##MaxNum) { \ |
| 176 HandleScope scope(isolate); \ |
| 177 SIMD4_BINARY_OP(type, a, b, MaxNumber, result); \ |
| 178 return *result; \ |
| 179 } |
| 180 |
| 181 #define SIMD4_SWIZZLE_FUNCTION(type) \ |
| 182 RUNTIME_FUNCTION(Runtime_##type##Swizzle) { \ |
| 183 HandleScope scope(isolate); \ |
| 184 DCHECK(args.length() == 5); \ |
| 185 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ |
| 186 CONVERT_SIMD_LANE_ARG_CHECKED(w, 1, 4); \ |
| 187 CONVERT_SIMD_LANE_ARG_CHECKED(x, 2, 4); \ |
| 188 CONVERT_SIMD_LANE_ARG_CHECKED(y, 3, 4); \ |
| 189 CONVERT_SIMD_LANE_ARG_CHECKED(z, 4, 4); \ |
| 190 Handle<type> result = isolate->factory()->New##type( \ |
| 191 a->get_lane(w), a->get_lane(x), a->get_lane(y), a->get_lane(z)); \ |
| 192 return *result; \ |
| 193 } |
| 194 |
| 195 #define SIMD4_SHUFFLE_FUNCTION(type) \ |
| 196 RUNTIME_FUNCTION(Runtime_##type##Shuffle) { \ |
| 197 HandleScope scope(isolate); \ |
| 198 DCHECK(args.length() == 6); \ |
| 199 CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ |
| 200 CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ |
| 201 CONVERT_SIMD_LANE_ARG_CHECKED(w, 2, 8); \ |
| 202 CONVERT_SIMD_LANE_ARG_CHECKED(x, 3, 8); \ |
| 203 CONVERT_SIMD_LANE_ARG_CHECKED(y, 4, 8); \ |
| 204 CONVERT_SIMD_LANE_ARG_CHECKED(z, 5, 8); \ |
| 205 float values[8]; \ |
| 206 values[0] = a->get_lane(0); \ |
| 207 values[1] = a->get_lane(1); \ |
| 208 values[2] = a->get_lane(2); \ |
| 209 values[3] = a->get_lane(3); \ |
| 210 values[4] = b->get_lane(0); \ |
| 211 values[5] = b->get_lane(1); \ |
| 212 values[6] = b->get_lane(2); \ |
| 213 values[7] = b->get_lane(3); \ |
| 214 Handle<type> result = isolate->factory()->New##type(values[w], values[x], \ |
| 215 values[y], values[z]); \ |
| 216 return *result; \ |
| 217 } |
| 218 |
| 219 #define SIMD4_FUNCTIONS(type) \ |
| 220 SIMD4_CREATE_FUNCTION(type) \ |
| 221 SIMD4_CHECK_FUNCTION(type) \ |
| 222 SIMD4_EXTRACT_LANE_FUNCTION(type) \ |
| 223 SIMD4_REPLACE_LANE_FUNCTION(type) \ |
| 224 SIMD4_ABS_FUNCTION(type) \ |
| 225 SIMD4_NEG_FUNCTION(type) \ |
| 226 SIMD4_SQRT_FUNCTION(type) \ |
| 227 SIMD4_RECIP_APPROX_FUNCTION(type) \ |
| 228 SIMD4_RECIP_SQRT_APPROX_FUNCTION(type) \ |
| 229 SIMD4_ADD_FUNCTION(type) \ |
| 230 SIMD4_SUB_FUNCTION(type) \ |
| 231 SIMD4_MUL_FUNCTION(type) \ |
| 232 SIMD4_DIV_FUNCTION(type) \ |
| 233 SIMD4_MIN_FUNCTION(type) \ |
| 234 SIMD4_MAX_FUNCTION(type) \ |
| 235 SIMD4_MINNUM_FUNCTION(type) \ |
| 236 SIMD4_MAXNUM_FUNCTION(type) \ |
| 237 SIMD4_SWIZZLE_FUNCTION(type) \ |
| 238 SIMD4_SHUFFLE_FUNCTION(type) |
| 239 |
| 240 |
| 241 namespace v8 { |
| 242 namespace internal { |
| 243 |
| 244 namespace { |
| 245 |
| 246 // Convert from Number object to float. |
| 247 inline float NumberToFloat(Object* number) { |
| 248 // Don't bother checking for Smi, we might still overflow a float. |
| 249 return DoubleToFloat32(number->Number()); |
| 250 } |
| 251 |
| 252 |
| 253 inline float RecipApprox(float a) { return 1.0f / a; } |
| 254 |
| 255 |
| 256 inline float RecipSqrtApprox(float a) { return 1.0f / std::sqrt(a); } |
| 257 |
| 258 |
| 259 inline float Min(float a, float b) { |
| 260 if (a < b) return a; |
| 261 if (a > b) return b; |
| 262 if (a == b) return std::signbit(a) ? a : b; |
| 263 return std::numeric_limits<float>::quiet_NaN(); |
| 264 } |
| 265 |
| 266 |
| 267 inline float Max(float a, float b) { |
| 268 if (a > b) return a; |
| 269 if (a < b) return b; |
| 270 if (a == b) return std::signbit(b) ? a : b; |
| 271 return std::numeric_limits<float>::quiet_NaN(); |
| 272 } |
| 273 |
| 274 |
| 275 inline float MinNumber(float a, float b) { |
| 276 if (a != a) return b; |
| 277 if (b != b) return a; |
| 278 return Min(a, b); |
| 279 } |
| 280 |
| 281 |
| 282 inline float MaxNumber(float a, float b) { |
| 283 if (a != a) return b; |
| 284 if (b != b) return a; |
| 285 return Max(a, b); |
| 286 } |
| 287 } // namespace |
| 288 |
| 289 SIMD4_FUNCTIONS(Float32x4) |
| 290 } |
| 291 } // namespace v8::internal |
| OLD | NEW |