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 // Flags: --harmony-simd --harmony-tostring --harmony-reflect | |
6 // Flags: --allow-natives-syntax --expose-natives-as natives --noalways-opt | |
7 | |
8 function lanesForType(typeName) { | |
9 // The lane count follows the first 'x' in the type name, which begins with | |
10 // 'float', 'int', or 'bool'. | |
11 return Number.parseInt(typeName[typeName.indexOf('x') + 1]); | |
12 } | |
13 | |
14 | |
15 function isValidSimdString(string, value, type, lanes) { | |
16 var simdFn = SIMD[type], | |
17 parseFn = | |
18 type.indexOf('float') === 0 ? Number.parseFloat : Number.parseInt, | |
19 indexOfOpenParen = string.indexOf('('); | |
20 // Check prefix for correct type name. | |
21 if (string.substr(0, indexOfOpenParen).toUpperCase() !== type.toUpperCase()) | |
22 return false; | |
23 // Remove type name and open parenthesis. | |
24 string = string.substr(indexOfOpenParen + 1); | |
25 var laneStrings = string.split(','); | |
26 if (laneStrings.length !== lanes) | |
27 return false; | |
28 for (var i = 0; i < lanes; i++) { | |
29 var fromString = parseFn(laneStrings[i]), | |
30 fromValue = simdFn.extractLane(value, i); | |
31 if (Math.abs(fromString - fromValue) > Number.EPSILON) | |
32 return false; | |
33 } | |
34 return true; | |
35 } | |
36 | |
37 | |
38 // Test for structural equivalence. | |
39 function areEquivalent(type, lanes, a, b) { | |
40 var simdFn = SIMD[type]; | |
41 for (var i = 0; i < lanes; i++) { | |
42 if (simdFn.extractLane(a, i) !== simdFn.extractLane(b, i)) | |
43 return false; | |
44 } | |
45 return true; | |
46 } | |
47 | |
48 | |
49 var sameValue = natives.$sameValue; | |
50 var sameValueZero = natives.$sameValueZero; | |
51 | |
52 // Calls SameValue and SameValueZero and checks that their results match. Also | |
53 // checks the internal SameValue checks using Object freeze and defineProperty. | |
54 function sameValueBoth(a, b) { | |
55 var result = sameValue(a, b); | |
56 assertTrue(result === sameValueZero(a, b)); | |
57 return result; | |
58 } | |
59 | |
60 | |
61 // Calls SameValue and SameValueZero and checks that their results don't match. | |
62 function sameValueZeroOnly(a, b) { | |
63 var result = sameValueZero(a, b); | |
64 assertTrue(result && !sameValue(a, b)); | |
65 return result; | |
66 } | |
67 | |
68 | |
69 // Tests for the global SIMD object. | |
70 function TestSIMDObject() { | |
71 assertSame(typeof SIMD, 'object'); | |
72 assertSame(SIMD.constructor, Object); | |
73 assertSame(Object.getPrototypeOf(SIMD), Object.prototype); | |
74 assertSame(SIMD + "", "[object SIMD]"); | |
75 } | |
76 TestSIMDObject() | |
77 | |
78 // TestConstructor populates this with interesting values for the other tests. | |
79 var values; | |
80 | |
81 // Test different forms of constructor calls. This test populates 'values' with | |
82 // a variety of SIMD values as a side effect, which are used by other tests. | |
83 function TestConstructor(type, lanes) { | |
84 var simdFn = SIMD[type]; | |
85 assertFalse(Object === simdFn.prototype.constructor) | |
86 assertFalse(simdFn === Object.prototype.constructor) | |
87 assertSame(simdFn, simdFn.prototype.constructor) | |
88 | |
89 values = [] | |
90 | |
91 // The constructor expects values for all lanes. | |
92 switch (type) { | |
93 case 'float32x4': | |
94 // The constructor expects values for all lanes. | |
95 assertThrows(function () { simdFn() }, TypeError) | |
96 assertThrows(function () { simdFn(0) }, TypeError) | |
97 assertThrows(function () { simdFn(0, 1) }, TypeError) | |
98 assertThrows(function () { simdFn(0, 1, 2) }, TypeError) | |
99 | |
100 values.push(simdFn(1, 2, 3, 4)) | |
101 values.push(simdFn(1, 2, 3, 4)) // test structural equivalence | |
102 values.push(simdFn(-0, NaN, 0, 0.5)) | |
103 values.push(simdFn(-0, NaN, 0, 0.5)) // test structural equivalence | |
104 values.push(simdFn(3, 2, 1, 0)) | |
105 values.push(simdFn(0, 0, 0, 0)) | |
106 break | |
107 } | |
108 for (var i in values) { | |
109 assertSame(simdFn, values[i].__proto__.constructor) | |
110 assertSame(simdFn, Object(values[i]).__proto__.constructor) | |
111 assertSame(simdFn.prototype, values[i].__proto__) | |
112 assertSame(simdFn.prototype, Object(values[i]).__proto__) | |
113 } | |
114 } | |
115 | |
116 | |
117 function TestType(type, lanes) { | |
118 for (var i in values) { | |
119 assertEquals(type, typeof values[i]) | |
120 assertTrue(typeof values[i] === type) | |
121 assertTrue(typeof Object(values[i]) === 'object') | |
122 assertEquals(null, %_ClassOf(values[i])) | |
123 assertEquals("Float32x4", %_ClassOf(Object(values[i]))) | |
124 } | |
125 } | |
126 | |
127 | |
128 function TestPrototype(type, lanes) { | |
129 var simdFn = SIMD[type]; | |
130 assertSame(Object.prototype, simdFn.prototype.__proto__) | |
131 for (var i in values) { | |
132 assertSame(simdFn.prototype, values[i].__proto__) | |
133 assertSame(simdFn.prototype, Object(values[i]).__proto__) | |
134 } | |
135 } | |
136 | |
137 | |
138 function TestValueOf(type, lanes) { | |
139 var simdFn = SIMD[type]; | |
140 for (var i in values) { | |
141 assertTrue(values[i] === Object(values[i]).valueOf()) | |
142 assertTrue(values[i] === values[i].valueOf()) | |
143 assertTrue(simdFn.prototype.valueOf.call(Object(values[i])) === values[i]) | |
144 assertTrue(simdFn.prototype.valueOf.call(values[i]) === values[i]) | |
145 } | |
146 } | |
147 | |
148 | |
149 function TestGet(type, lanes) { | |
150 var simdFn = SIMD[type]; | |
151 for (var i in values) { | |
152 assertEquals(undefined, values[i].a) | |
153 assertEquals(undefined, values[i]["a" + "b"]) | |
154 assertEquals(undefined, values[i]["" + "1"]) | |
155 assertEquals(undefined, values[i][42]) | |
156 } | |
157 } | |
158 | |
159 | |
160 function TestToBoolean(type, lanes) { | |
161 for (var i in values) { | |
162 assertTrue(Boolean(Object(values[i]))) | |
163 assertFalse(!Object(values[i])) | |
164 assertTrue(Boolean(values[i]).valueOf()) | |
165 assertFalse(!values[i]) | |
166 assertTrue(!!values[i]) | |
167 assertTrue(values[i] && true) | |
168 assertFalse(!values[i] && false) | |
169 assertTrue(!values[i] || true) | |
170 assertEquals(1, values[i] ? 1 : 2) | |
171 assertEquals(2, !values[i] ? 1 : 2) | |
172 if (!values[i]) assertUnreachable(); | |
173 if (values[i]) {} else assertUnreachable(); | |
174 } | |
175 } | |
176 | |
177 | |
178 function TestToString(type, lanes) { | |
179 var simdFn = SIMD[type]; | |
180 for (var i in values) { | |
181 assertEquals(values[i].toString(), String(values[i])) | |
182 assertTrue(isValidSimdString(values[i].toString(), values[i], type, lanes)) | |
183 assertTrue( | |
184 isValidSimdString(Object(values[i]).toString(), values[i], type, lanes)) | |
185 assertTrue(isValidSimdString( | |
186 simdFn.prototype.toString.call(values[i]), values[i], type, lanes)) | |
187 } | |
188 } | |
189 | |
190 | |
191 function TestToNumber(type, lanes) { | |
192 for (var i in values) { | |
193 assertThrows(function() { Number(Object(values[i])) }, TypeError) | |
194 assertThrows(function() { +Object(values[i]) }, TypeError) | |
195 assertThrows(function() { Number(values[i]) }, TypeError) | |
196 assertThrows(function() { values[i] + 0 }, TypeError) | |
197 } | |
198 } | |
199 | |
200 | |
201 function TestEquality(type, lanes) { | |
202 // Every SIMD value should equal itself, and non-strictly equal its wrapper. | |
203 for (var i in values) { | |
204 assertSame(values[i], values[i]) | |
205 assertEquals(values[i], values[i]) | |
206 assertTrue(Object.is(values[i], values[i])) | |
207 assertTrue(values[i] === values[i]) | |
208 assertTrue(values[i] == values[i]) | |
209 assertFalse(values[i] === Object(values[i])) | |
210 assertFalse(Object(values[i]) === values[i]) | |
211 assertFalse(values[i] == Object(values[i])) | |
212 assertFalse(Object(values[i]) == values[i]) | |
213 assertTrue(values[i] === values[i].valueOf()) | |
214 assertTrue(values[i].valueOf() === values[i]) | |
215 assertTrue(values[i] == values[i].valueOf()) | |
216 assertTrue(values[i].valueOf() == values[i]) | |
217 assertFalse(Object(values[i]) === Object(values[i])) | |
218 assertEquals(Object(values[i]).valueOf(), Object(values[i]).valueOf()) | |
219 } | |
220 | |
221 // Test structural equivalence. | |
222 for (var i = 0; i < values.length; i++) { | |
223 for (var j = i + 1; j < values.length; j++) { | |
224 var a = values[i], b = values[j], | |
225 equivalent = areEquivalent(type, lanes, a, b); | |
226 assertSame(equivalent, a == b); | |
227 assertSame(equivalent, a === b); | |
228 } | |
229 } | |
230 | |
231 // SIMD values should not be equal to any other kind of object. | |
232 var others = [347, 1.275, NaN, "string", null, undefined, {}, function() {}] | |
233 for (var i in values) { | |
234 for (var j in others) { | |
235 assertFalse(values[i] === others[j]) | |
236 assertFalse(others[j] === values[i]) | |
237 assertFalse(values[i] == others[j]) | |
238 assertFalse(others[j] == values[i]) | |
239 } | |
240 } | |
241 } | |
242 | |
243 | |
244 function TestSameValue(type, lanes) { | |
245 // SIMD value types. | |
246 // All lanes checked. | |
247 // TODO(bbudge): use loops to test lanes when replaceLane is defined. | |
248 assertTrue(sameValueBoth(SIMD.float32x4(1, 2, 3, 4), | |
249 SIMD.float32x4(1, 2, 3, 4))); | |
250 assertFalse(sameValueBoth(SIMD.float32x4(1, 2, 3, 4), | |
251 SIMD.float32x4(NaN, 2, 3, 4))); | |
252 assertFalse(sameValueBoth(SIMD.float32x4(1, 2, 3, 4), | |
253 SIMD.float32x4(1, NaN, 3, 4))); | |
254 assertFalse(sameValueBoth(SIMD.float32x4(1, 2, 3, 4), | |
255 SIMD.float32x4(1, 2, NaN, 4))); | |
256 assertFalse(sameValueBoth(SIMD.float32x4(1, 2, 3, 4), | |
257 SIMD.float32x4(1, 2, 3, NaN))); | |
258 // Special values. | |
259 // TODO(bbudge): use loops to test lanes when replaceLane is defined. | |
260 assertTrue(sameValueBoth(SIMD.float32x4(NaN, 2, 3, 4), | |
261 SIMD.float32x4(NaN, 2, 3, 4))); | |
262 assertTrue(sameValueBoth(SIMD.float32x4(+0, 2, 3, 4), | |
263 SIMD.float32x4(+0, 2, 3, 4))); | |
264 assertTrue(sameValueBoth(SIMD.float32x4(-0, 2, 3, 4), | |
265 SIMD.float32x4(-0, 2, 3, 4))); | |
266 assertTrue(sameValueZeroOnly(SIMD.float32x4(+0, 2, 3, 4), | |
267 SIMD.float32x4(-0, 2, 3, 4))); | |
268 assertTrue(sameValueZeroOnly(SIMD.float32x4(-0, 2, 3, 4), | |
269 SIMD.float32x4(+0, 2, 3, 4))); | |
270 } | |
271 | |
272 | |
273 function TestComparison(type, lanes) { | |
274 var a = values[0], b = values[1]; | |
275 | |
276 function lt() { a < b; } | |
277 function gt() { a > b; } | |
278 function le() { a <= b; } | |
279 function ge() { a >= b; } | |
280 function lt_same() { a < a; } | |
281 function gt_same() { a > a; } | |
282 function le_same() { a <= a; } | |
283 function ge_same() { a >= a; } | |
284 | |
285 var throwFuncs = [lt, gt, le, ge, lt_same, gt_same, le_same, ge_same]; | |
286 | |
287 for (var f of throwFuncs) { | |
288 assertThrows(f, TypeError); | |
289 %OptimizeFunctionOnNextCall(f); | |
290 assertThrows(f, TypeError); | |
291 assertThrows(f, TypeError); | |
292 } | |
293 } | |
294 | |
295 | |
296 // Test SIMD value wrapping/boxing over non-builtins. | |
297 function TestCall(type, lanes) { | |
298 var simdFn = SIMD[type]; | |
299 simdFn.prototype.getThisProto = function () { | |
300 return Object.getPrototypeOf(this); | |
301 } | |
302 for (var i in values) { | |
303 assertTrue(values[i].getThisProto() === simdFn.prototype) | |
304 } | |
305 } | |
306 | |
307 | |
308 function TestAsSetKey(type, lanes, set) { | |
309 function test(set, key) { | |
310 assertFalse(set.has(key)); | |
311 assertFalse(set.delete(key)); | |
312 if (!(set instanceof WeakSet)) { | |
313 assertSame(set, set.add(key)); | |
314 assertTrue(set.has(key)); | |
315 assertTrue(set.delete(key)); | |
316 } else { | |
317 // SIMD values can't be used as keys in WeakSets. | |
318 assertThrows(function() { set.add(key) }); | |
319 } | |
320 assertFalse(set.has(key)); | |
321 assertFalse(set.delete(key)); | |
322 assertFalse(set.has(key)); | |
323 } | |
324 | |
325 for (var i in values) { | |
326 test(set, values[i]); | |
327 } | |
328 } | |
329 | |
330 | |
331 function TestAsMapKey(type, lanes, map) { | |
332 function test(map, key, value) { | |
333 assertFalse(map.has(key)); | |
334 assertSame(undefined, map.get(key)); | |
335 assertFalse(map.delete(key)); | |
336 if (!(map instanceof WeakMap)) { | |
337 assertSame(map, map.set(key, value)); | |
338 assertSame(value, map.get(key)); | |
339 assertTrue(map.has(key)); | |
340 assertTrue(map.delete(key)); | |
341 } else { | |
342 // SIMD values can't be used as keys in WeakMaps. | |
343 assertThrows(function() { map.set(key, value) }); | |
344 } | |
345 assertFalse(map.has(key)); | |
346 assertSame(undefined, map.get(key)); | |
347 assertFalse(map.delete(key)); | |
348 assertFalse(map.has(key)); | |
349 assertSame(undefined, map.get(key)); | |
350 } | |
351 | |
352 for (var i in values) { | |
353 test(map, values[i], {}); | |
354 } | |
355 } | |
356 | |
357 | |
358 // Test SIMD type with Harmony reflect-apply. | |
359 function TestReflectApply(type) { | |
360 function returnThis() { return this; } | |
361 function returnThisStrict() { 'use strict'; return this; } | |
362 function noop() {} | |
363 function noopStrict() { 'use strict'; } | |
364 var R = void 0; | |
365 | |
366 for (var i in values) { | |
367 assertSame(SIMD[type].prototype, | |
368 Object.getPrototypeOf( | |
369 Reflect.apply(returnThis, values[i], []))); | |
370 assertSame(values[i], Reflect.apply(returnThisStrict, values[i], [])); | |
371 | |
372 assertThrows( | |
373 function() { 'use strict'; Reflect.apply(values[i]); }, TypeError); | |
374 assertThrows( | |
375 function() { Reflect.apply(values[i]); }, TypeError); | |
376 assertThrows( | |
377 function() { Reflect.apply(noopStrict, R, values[i]); }, TypeError); | |
378 assertThrows( | |
379 function() { Reflect.apply(noop, R, values[i]); }, TypeError); | |
380 } | |
381 } | |
382 | |
383 | |
384 function TestSIMDTypes() { | |
385 var types = [ 'float32x4' ]; | |
386 for (var i = 0; i < types.length; ++i) { | |
387 var type = types[i], | |
388 lanes = lanesForType(type); | |
389 TestConstructor(type, lanes); | |
390 TestType(type, lanes); | |
391 TestPrototype(type, lanes); | |
392 TestValueOf(type, lanes); | |
393 TestGet(type, lanes); | |
394 TestToBoolean(type, lanes); | |
395 TestToString(type, lanes); | |
396 TestToNumber(type, lanes); | |
397 TestEquality(type, lanes); | |
398 TestSameValue(type, lanes); | |
399 TestComparison(type, lanes); | |
400 TestCall(type, lanes); | |
401 TestAsSetKey(type, lanes, new Set); | |
402 TestAsSetKey(type, lanes, new WeakSet); | |
403 TestAsMapKey(type, lanes, new Map); | |
404 TestAsMapKey(type, lanes, new WeakMap); | |
405 TestReflectApply(type); | |
406 } | |
407 } | |
408 TestSIMDTypes(); | |
OLD | NEW |