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 // Flags: --harmony-simd --harmony-tostring --harmony-reflect | 5 // Flags: --harmony-simd --harmony-tostring --harmony-reflect |
6 // Flags: --allow-natives-syntax --expose-natives-as natives --noalways-opt | 6 // Flags: --allow-natives-syntax --expose-natives-as natives --noalways-opt |
7 | 7 |
8 function lanesForType(typeName) { | 8 function lanesForType(typeName) { |
9 // The lane count follows the first 'x' in the type name, which begins with | 9 // The lane count follows the first 'x' in the type name, which begins with |
10 // 'float', 'int', or 'bool'. | 10 // 'float', 'int', or 'bool'. |
11 return Number.parseInt(typeName[typeName.indexOf('x') + 1]); | 11 return Number.parseInt(typeName.substr(typeName.indexOf('x') + 1)); |
12 } | 12 } |
13 | 13 |
14 | 14 |
| 15 // Creates an instance that has been zeroed, so it can be used for equality |
| 16 // testing. |
| 17 function createInstance(type) { |
| 18 // Provide enough parameters for the longest type (currently 16). It's |
| 19 // important that instances be consistent to better test that different SIMD |
| 20 // types can't be compared and are never equal or the same in any sense. |
| 21 return SIMD[type](0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); |
| 22 } |
| 23 |
| 24 |
15 function isValidSimdString(string, value, type, lanes) { | 25 function isValidSimdString(string, value, type, lanes) { |
16 var simdFn = SIMD[type], | 26 var simdFn = SIMD[type], |
17 parseFn = | 27 parseFn = |
18 type.indexOf('Float') === 0 ? Number.parseFloat : Number.parseInt, | 28 type.indexOf('Float') === 0 ? Number.parseFloat : Number.parseInt, |
19 indexOfOpenParen = string.indexOf('('); | 29 indexOfOpenParen = string.indexOf('('); |
20 // Check prefix (e.g. SIMD.Float32x4.) | 30 // Check prefix (e.g. SIMD.Float32x4.) |
21 if (string.substr(0, indexOfOpenParen) !== 'SIMD.' + type) | 31 if (string.substr(0, indexOfOpenParen) !== 'SIMD.' + type) |
22 return false; | 32 return false; |
23 // Remove type name (e.g. SIMD.Float32x4) and open parenthesis. | 33 // Remove type name (e.g. SIMD.Float32x4) and open parenthesis. |
24 string = string.substr(indexOfOpenParen + 1); | 34 string = string.substr(indexOfOpenParen + 1); |
25 var laneStrings = string.split(','); | 35 var laneStrings = string.split(','); |
26 if (laneStrings.length !== lanes) | 36 if (laneStrings.length !== lanes) |
27 return false; | 37 return false; |
28 for (var i = 0; i < lanes; i++) { | 38 for (var i = 0; i < lanes; i++) { |
29 var fromString = parseFn(laneStrings[i]), | 39 var fromString = parseFn(laneStrings[i]), |
30 fromValue = simdFn.extractLane(value, i); | 40 fromValue = simdFn.extractLane(value, i); |
31 if (Math.abs(fromString - fromValue) > Number.EPSILON) | 41 if (Math.abs(fromString - fromValue) > Number.EPSILON) |
32 return false; | 42 return false; |
33 } | 43 } |
34 return true; | 44 return true; |
35 } | 45 } |
36 | 46 |
37 | 47 |
38 // Test for structural equivalence. | 48 var simdTypeNames = ['Float32x4', 'Int32x4', 'Bool32x4', |
39 function areEquivalent(type, lanes, a, b) { | 49 'Int16x8', 'Bool16x8', |
40 var simdFn = SIMD[type]; | 50 'Int8x16', 'Bool8x16']; |
41 for (var i = 0; i < lanes; i++) { | 51 |
42 if (simdFn.extractLane(a, i) !== simdFn.extractLane(b, i)) | 52 var nonSimdValues = [347, 1.275, NaN, "string", null, undefined, {}, |
43 return false; | 53 function() {}]; |
44 } | 54 |
45 return true; | 55 function checkTypeMatrix(type, fn) { |
46 } | 56 // Check against non-SIMD types. |
47 | 57 nonSimdValues.forEach(fn); |
48 | 58 // Check against SIMD values of a different type. |
49 var sameValue = natives.$sameValue; | 59 for (var i = 0; i < simdTypeNames.length; i++) { |
50 var sameValueZero = natives.$sameValueZero; | 60 var otherType = simdTypeNames[i]; |
51 | 61 if (type != otherType) fn(createInstance(otherType)); |
52 // Calls SameValue and SameValueZero and checks that their results match. Also | 62 } |
53 // checks the internal SameValue checks using Object freeze and defineProperty. | 63 } |
54 function sameValueBoth(a, b) { | 64 |
55 var result = sameValue(a, b); | 65 |
56 assertTrue(result === sameValueZero(a, b)); | 66 // Test different forms of constructor calls. |
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) { | 67 function TestConstructor(type, lanes) { |
84 var simdFn = SIMD[type]; | 68 var simdFn = SIMD[type]; |
| 69 var instance = createInstance(type); |
| 70 |
85 assertFalse(Object === simdFn.prototype.constructor) | 71 assertFalse(Object === simdFn.prototype.constructor) |
86 assertFalse(simdFn === Object.prototype.constructor) | 72 assertFalse(simdFn === Object.prototype.constructor) |
87 assertSame(simdFn, simdFn.prototype.constructor) | 73 assertSame(simdFn, simdFn.prototype.constructor) |
88 | 74 |
89 values = [] | 75 assertSame(simdFn, instance.__proto__.constructor) |
90 | 76 assertSame(simdFn, Object(instance).__proto__.constructor) |
91 // The constructor expects values for all lanes. | 77 assertSame(simdFn.prototype, instance.__proto__) |
| 78 assertSame(simdFn.prototype, Object(instance).__proto__) |
| 79 } |
| 80 |
| 81 |
| 82 function TestType(type, lanes) { |
| 83 var simdFn = SIMD[type]; |
| 84 var instance = createInstance(type); |
| 85 var typeofString = type.charAt(0).toLowerCase() + type.slice(1); |
| 86 |
| 87 assertEquals(typeofString, typeof instance) |
| 88 assertTrue(typeof instance === typeofString) |
| 89 assertTrue(typeof Object(instance) === 'object') |
| 90 assertEquals(null, %_ClassOf(instance)) |
| 91 assertEquals(type, %_ClassOf(Object(instance))) |
| 92 } |
| 93 |
| 94 |
| 95 function TestPrototype(type, lanes) { |
| 96 var simdFn = SIMD[type]; |
| 97 var instance = createInstance(type); |
| 98 |
| 99 assertSame(Object.prototype, simdFn.prototype.__proto__) |
| 100 assertSame(simdFn.prototype, instance.__proto__) |
| 101 assertSame(simdFn.prototype, Object(instance).__proto__) |
| 102 } |
| 103 |
| 104 |
| 105 function TestValueOf(type, lanes) { |
| 106 var simdFn = SIMD[type]; |
| 107 var instance = createInstance(type); |
| 108 |
| 109 assertTrue(instance === Object(instance).valueOf()) |
| 110 assertTrue(instance === instance.valueOf()) |
| 111 assertTrue(simdFn.prototype.valueOf.call(Object(instance)) === instance) |
| 112 assertTrue(simdFn.prototype.valueOf.call(instance) === instance) |
| 113 } |
| 114 |
| 115 |
| 116 function TestGet(type, lanes) { |
| 117 var simdFn = SIMD[type]; |
| 118 var instance = createInstance(type); |
| 119 |
| 120 assertEquals(undefined, instance.a) |
| 121 assertEquals(undefined, instance["a" + "b"]) |
| 122 assertEquals(undefined, instance["" + "1"]) |
| 123 assertEquals(undefined, instance[42]) |
| 124 } |
| 125 |
| 126 |
| 127 function TestToBoolean(type, lanes) { |
| 128 var simdFn = SIMD[type]; |
| 129 var instance = createInstance(type); |
| 130 |
| 131 assertTrue(Boolean(Object(instance))) |
| 132 assertFalse(!Object(instance)) |
| 133 assertTrue(Boolean(instance).valueOf()) |
| 134 assertFalse(!instance) |
| 135 assertTrue(!!instance) |
| 136 assertTrue(instance && true) |
| 137 assertFalse(!instance && false) |
| 138 assertTrue(!instance || true) |
| 139 assertEquals(1, instance ? 1 : 2) |
| 140 assertEquals(2, !instance ? 1 : 2) |
| 141 if (!instance) assertUnreachable(); |
| 142 if (instance) {} else assertUnreachable(); |
| 143 } |
| 144 |
| 145 |
| 146 function TestToString(type, lanes) { |
| 147 var simdFn = SIMD[type]; |
| 148 var instance = createInstance(type); |
| 149 |
| 150 assertEquals(instance.toString(), String(instance)) |
| 151 assertTrue(isValidSimdString(instance.toString(), instance, type, lanes)) |
| 152 assertTrue( |
| 153 isValidSimdString(Object(instance).toString(), instance, type, lanes)) |
| 154 assertTrue(isValidSimdString( |
| 155 simdFn.prototype.toString.call(instance), instance, type, lanes)) |
| 156 } |
| 157 |
| 158 |
| 159 function TestToNumber(type, lanes) { |
| 160 var simdFn = SIMD[type]; |
| 161 var instance = createInstance(type); |
| 162 |
| 163 assertThrows(function() { Number(Object(instance)) }, TypeError) |
| 164 assertThrows(function() { +Object(instance) }, TypeError) |
| 165 assertThrows(function() { Number(instance) }, TypeError) |
| 166 assertThrows(function() { instance + 0 }, TypeError) |
| 167 } |
| 168 |
| 169 |
| 170 function TestCoercions(type, lanes) { |
| 171 var simdFn = SIMD[type]; |
| 172 var instance = createInstance(type); |
| 173 // Test that setting a lane to value 'a' results in a lane with value 'b'. |
| 174 function test(a, b) { |
| 175 for (var i = 0; i < lanes; i++) { |
| 176 var ainstance = simdFn.replaceLane(instance, i, a); |
| 177 var lane_value = simdFn.extractLane(ainstance, i); |
| 178 assertSame(b, lane_value); |
| 179 } |
| 180 } |
| 181 |
92 switch (type) { | 182 switch (type) { |
93 case 'Float32x4': | 183 case 'Float32x4': |
94 // The constructor expects values for all lanes. | 184 test(0, 0); |
95 assertThrows(function () { simdFn() }, TypeError) | 185 test(-0, -0); |
96 assertThrows(function () { simdFn(0) }, TypeError) | 186 test(NaN, NaN); |
97 assertThrows(function () { simdFn(0, 1) }, TypeError) | 187 test(null, 0); |
98 assertThrows(function () { simdFn(0, 1, 2) }, TypeError) | 188 test(undefined, NaN); |
99 | 189 test("5.25", 5.25); |
100 values.push(simdFn(1, 2, 3, 4)) | 190 test(Number.MAX_VALUE, Infinity); |
101 values.push(simdFn(1, 2, 3, 4)) // test structural equivalence | 191 test(-Number.MAX_VALUE, -Infinity); |
102 values.push(simdFn(-0, NaN, 0, 0.5)) | 192 test(Number.MIN_VALUE, 0); |
103 values.push(simdFn(-0, NaN, 0, 0.5)) // test structural equivalence | 193 break; |
104 values.push(simdFn(3, 2, 1, 0)) | 194 case 'Int32x4': |
105 values.push(simdFn(0, 0, 0, 0)) | 195 test(Infinity, 0); |
106 break | 196 test(-Infinity, 0); |
107 } | 197 test(NaN, 0); |
108 for (var i in values) { | 198 test(0, 0); |
109 assertSame(simdFn, values[i].__proto__.constructor) | 199 test(-0, 0); |
110 assertSame(simdFn, Object(values[i]).__proto__.constructor) | 200 test(Number.MIN_VALUE, 0); |
111 assertSame(simdFn.prototype, values[i].__proto__) | 201 test(-Number.MIN_VALUE, 0); |
112 assertSame(simdFn.prototype, Object(values[i]).__proto__) | 202 test(0.1, 0); |
113 } | 203 test(-0.1, 0); |
114 } | 204 test(1, 1); |
115 | 205 test(1.1, 1); |
116 | 206 test(-1, -1); |
117 function TestType(type, lanes) { | 207 test(-1.6, -1); |
118 var typeofString = type.charAt(0).toLowerCase() + type.slice(1); | 208 test(2147483647, 2147483647); |
119 for (var i in values) { | 209 test(2147483648, -2147483648); |
120 assertEquals(typeofString, typeof values[i]) | 210 test(2147483649, -2147483647); |
121 assertTrue(typeof values[i] === typeofString) | 211 test(4294967295, -1); |
122 assertTrue(typeof Object(values[i]) === 'object') | 212 test(4294967296, 0); |
123 assertEquals(null, %_ClassOf(values[i])) | 213 test(4294967297, 1); |
124 assertEquals(type, %_ClassOf(Object(values[i]))) | 214 break; |
125 } | 215 case 'Int16x8': |
126 } | 216 test(Infinity, 0); |
127 | 217 test(-Infinity, 0); |
128 | 218 test(NaN, 0); |
129 function TestPrototype(type, lanes) { | 219 test(0, 0); |
130 var simdFn = SIMD[type]; | 220 test(-0, 0); |
131 assertSame(Object.prototype, simdFn.prototype.__proto__) | 221 test(Number.MIN_VALUE, 0); |
132 for (var i in values) { | 222 test(-Number.MIN_VALUE, 0); |
133 assertSame(simdFn.prototype, values[i].__proto__) | 223 test(0.1, 0); |
134 assertSame(simdFn.prototype, Object(values[i]).__proto__) | 224 test(-0.1, 0); |
135 } | 225 test(1, 1); |
136 } | 226 test(1.1, 1); |
137 | 227 test(-1, -1); |
138 | 228 test(-1.6, -1); |
139 function TestValueOf(type, lanes) { | 229 test(32767, 32767); |
140 var simdFn = SIMD[type]; | 230 test(32768, -32768); |
141 for (var i in values) { | 231 test(32769, -32767); |
142 assertTrue(values[i] === Object(values[i]).valueOf()) | 232 test(65535, -1); |
143 assertTrue(values[i] === values[i].valueOf()) | 233 test(65536, 0); |
144 assertTrue(simdFn.prototype.valueOf.call(Object(values[i])) === values[i]) | 234 test(65537, 1); |
145 assertTrue(simdFn.prototype.valueOf.call(values[i]) === values[i]) | 235 break; |
146 } | 236 case 'Int8x16': |
147 } | 237 test(Infinity, 0); |
148 | 238 test(-Infinity, 0); |
149 | 239 test(NaN, 0); |
150 function TestGet(type, lanes) { | 240 test(0, 0); |
151 var simdFn = SIMD[type]; | 241 test(-0, 0); |
152 for (var i in values) { | 242 test(Number.MIN_VALUE, 0); |
153 assertEquals(undefined, values[i].a) | 243 test(-Number.MIN_VALUE, 0); |
154 assertEquals(undefined, values[i]["a" + "b"]) | 244 test(0.1, 0); |
155 assertEquals(undefined, values[i]["" + "1"]) | 245 test(-0.1, 0); |
156 assertEquals(undefined, values[i][42]) | 246 test(1, 1); |
157 } | 247 test(1.1, 1); |
158 } | 248 test(-1, -1); |
159 | 249 test(-1.6, -1); |
160 | 250 test(127, 127); |
161 function TestToBoolean(type, lanes) { | 251 test(128, -128); |
162 for (var i in values) { | 252 test(129, -127); |
163 assertTrue(Boolean(Object(values[i]))) | 253 test(255, -1); |
164 assertFalse(!Object(values[i])) | 254 test(256, 0); |
165 assertTrue(Boolean(values[i]).valueOf()) | 255 test(257, 1); |
166 assertFalse(!values[i]) | 256 break; |
167 assertTrue(!!values[i]) | 257 case 'Bool32x4': |
168 assertTrue(values[i] && true) | 258 case 'Bool16x8': |
169 assertFalse(!values[i] && false) | 259 case 'Bool8x16': |
170 assertTrue(!values[i] || true) | 260 test(true, true); |
171 assertEquals(1, values[i] ? 1 : 2) | 261 test(false, false); |
172 assertEquals(2, !values[i] ? 1 : 2) | 262 test(0, false); |
173 if (!values[i]) assertUnreachable(); | 263 test(1, true); |
174 if (values[i]) {} else assertUnreachable(); | 264 test(0.1, true); |
175 } | 265 test(NaN, false); |
176 } | 266 test(null, false); |
177 | 267 test("", false); |
178 | 268 test("false", true); |
179 function TestToString(type, lanes) { | 269 break; |
180 var simdFn = SIMD[type]; | |
181 for (var i in values) { | |
182 assertEquals(values[i].toString(), String(values[i])) | |
183 assertTrue(isValidSimdString(values[i].toString(), values[i], type, lanes)) | |
184 assertTrue( | |
185 isValidSimdString(Object(values[i]).toString(), values[i], type, lanes)) | |
186 assertTrue(isValidSimdString( | |
187 simdFn.prototype.toString.call(values[i]), values[i], type, lanes)) | |
188 } | |
189 } | |
190 | |
191 | |
192 function TestToNumber(type, lanes) { | |
193 for (var i in values) { | |
194 assertThrows(function() { Number(Object(values[i])) }, TypeError) | |
195 assertThrows(function() { +Object(values[i]) }, TypeError) | |
196 assertThrows(function() { Number(values[i]) }, TypeError) | |
197 assertThrows(function() { values[i] + 0 }, TypeError) | |
198 } | 270 } |
199 } | 271 } |
200 | 272 |
201 | 273 |
202 function TestEquality(type, lanes) { | 274 function TestEquality(type, lanes) { |
| 275 var simdFn = SIMD[type]; |
| 276 var instance = createInstance(type); |
| 277 |
203 // Every SIMD value should equal itself, and non-strictly equal its wrapper. | 278 // Every SIMD value should equal itself, and non-strictly equal its wrapper. |
204 for (var i in values) { | 279 assertSame(instance, instance) |
205 assertSame(values[i], values[i]) | 280 assertEquals(instance, instance) |
206 assertEquals(values[i], values[i]) | 281 assertTrue(Object.is(instance, instance)) |
207 assertTrue(Object.is(values[i], values[i])) | 282 assertTrue(instance === instance) |
208 assertTrue(values[i] === values[i]) | 283 assertTrue(instance == instance) |
209 assertTrue(values[i] == values[i]) | 284 assertFalse(instance === Object(instance)) |
210 assertFalse(values[i] === Object(values[i])) | 285 assertFalse(Object(instance) === instance) |
211 assertFalse(Object(values[i]) === values[i]) | 286 assertFalse(instance == Object(instance)) |
212 assertFalse(values[i] == Object(values[i])) | 287 assertFalse(Object(instance) == instance) |
213 assertFalse(Object(values[i]) == values[i]) | 288 assertTrue(instance === instance.valueOf()) |
214 assertTrue(values[i] === values[i].valueOf()) | 289 assertTrue(instance.valueOf() === instance) |
215 assertTrue(values[i].valueOf() === values[i]) | 290 assertTrue(instance == instance.valueOf()) |
216 assertTrue(values[i] == values[i].valueOf()) | 291 assertTrue(instance.valueOf() == instance) |
217 assertTrue(values[i].valueOf() == values[i]) | 292 assertFalse(Object(instance) === Object(instance)) |
218 assertFalse(Object(values[i]) === Object(values[i])) | 293 assertEquals(Object(instance).valueOf(), Object(instance).valueOf()) |
219 assertEquals(Object(values[i]).valueOf(), Object(values[i]).valueOf()) | 294 |
220 } | 295 function notEqual(other) { |
221 | 296 assertFalse(instance === other) |
222 // Test structural equivalence. | 297 assertFalse(other === instance) |
223 for (var i = 0; i < values.length; i++) { | 298 assertFalse(instance == other) |
224 for (var j = i + 1; j < values.length; j++) { | 299 assertFalse(other == instance) |
225 var a = values[i], b = values[j], | 300 } |
226 equivalent = areEquivalent(type, lanes, a, b); | 301 |
227 assertSame(equivalent, a == b); | 302 // SIMD values should not be equal to instances of different types. |
228 assertSame(equivalent, a === b); | 303 checkTypeMatrix(type, function(other) { |
| 304 assertFalse(instance === other) |
| 305 assertFalse(other === instance) |
| 306 assertFalse(instance == other) |
| 307 assertFalse(other == instance) |
| 308 }); |
| 309 |
| 310 // Test that f(a, b) is the same as f(SIMD(a), SIMD(b)) for equality and |
| 311 // strict equality, at every lane. |
| 312 function test(a, b) { |
| 313 for (var i = 0; i < lanes; i++) { |
| 314 var aval = simdFn.replaceLane(instance, i, a); |
| 315 var bval = simdFn.replaceLane(instance, i, b); |
| 316 assertSame(a == b, aval == bval); |
| 317 assertSame(a === b, aval === bval); |
229 } | 318 } |
230 } | 319 } |
231 | 320 |
232 // SIMD values should not be equal to any other kind of object. | 321 switch (type) { |
233 var others = [347, 1.275, NaN, "string", null, undefined, {}, function() {}] | 322 case 'Float32x4': |
234 for (var i in values) { | 323 test(1, 2.5); |
235 for (var j in others) { | 324 test(1, 1); |
236 assertFalse(values[i] === others[j]) | 325 test(0, 0); |
237 assertFalse(others[j] === values[i]) | 326 test(-0, +0); |
238 assertFalse(values[i] == others[j]) | 327 test(+0, -0); |
239 assertFalse(others[j] == values[i]) | 328 test(-0, -0); |
| 329 test(0, NaN); |
| 330 test(NaN, NaN); |
| 331 break; |
| 332 case 'Int32x4': |
| 333 case 'Int16x8': |
| 334 case 'Int8x16': |
| 335 test(1, 2); |
| 336 test(1, 1); |
| 337 test(1, -1); |
| 338 break; |
| 339 case 'Bool32x4': |
| 340 case 'Bool16x8': |
| 341 case 'Bool8x16': |
| 342 test(true, false); |
| 343 test(false, true); |
| 344 break; |
| 345 } |
| 346 } |
| 347 |
| 348 |
| 349 function TestSameValue(type, lanes) { |
| 350 var simdFn = SIMD[type]; |
| 351 var instance = createInstance(type); |
| 352 var sameValue = natives.$sameValue; |
| 353 var sameValueZero = natives.$sameValueZero; |
| 354 |
| 355 // SIMD values should not be the same as instances of different types. |
| 356 checkTypeMatrix(type, function(other) { |
| 357 assertFalse(sameValue(instance, other)); |
| 358 assertFalse(sameValueZero(instance, other)); |
| 359 }); |
| 360 |
| 361 // Test that f(a, b) is the same as f(SIMD(a), SIMD(b)) for sameValue and |
| 362 // sameValueZero, at every lane. |
| 363 function test(a, b) { |
| 364 for (var i = 0; i < lanes; i++) { |
| 365 var aval = simdFn.replaceLane(instance, i, a); |
| 366 var bval = simdFn.replaceLane(instance, i, b); |
| 367 assertSame(sameValue(a, b), sameValue(aval, bval)); |
| 368 assertSame(sameValueZero(a, b), sameValueZero(aval, bval)); |
240 } | 369 } |
241 } | 370 } |
242 } | 371 |
243 | 372 switch (type) { |
244 | 373 case 'Float32x4': |
245 function TestSameValue(type, lanes) { | 374 test(1, 2.5); |
246 // SIMD value types. | 375 test(1, 1); |
247 // All lanes checked. | 376 test(0, 0); |
248 // TODO(bbudge): use loops to test lanes when replaceLane is defined. | 377 test(-0, +0); |
249 assertTrue(sameValueBoth(SIMD.Float32x4(1, 2, 3, 4), | 378 test(+0, -0); |
250 SIMD.Float32x4(1, 2, 3, 4))); | 379 test(-0, -0); |
251 assertFalse(sameValueBoth(SIMD.Float32x4(1, 2, 3, 4), | 380 test(0, NaN); |
252 SIMD.Float32x4(NaN, 2, 3, 4))); | 381 test(NaN, NaN); |
253 assertFalse(sameValueBoth(SIMD.Float32x4(1, 2, 3, 4), | 382 break; |
254 SIMD.Float32x4(1, NaN, 3, 4))); | 383 case 'Int32x4': |
255 assertFalse(sameValueBoth(SIMD.Float32x4(1, 2, 3, 4), | 384 case 'Int16x8': |
256 SIMD.Float32x4(1, 2, NaN, 4))); | 385 case 'Int8x16': |
257 assertFalse(sameValueBoth(SIMD.Float32x4(1, 2, 3, 4), | 386 test(1, 2); |
258 SIMD.Float32x4(1, 2, 3, NaN))); | 387 test(1, 1); |
259 // Special values. | 388 test(1, -1); |
260 // TODO(bbudge): use loops to test lanes when replaceLane is defined. | 389 break; |
261 assertTrue(sameValueBoth(SIMD.Float32x4(NaN, 2, 3, 4), | 390 case 'Bool32x4': |
262 SIMD.Float32x4(NaN, 2, 3, 4))); | 391 case 'Bool16x8': |
263 assertTrue(sameValueBoth(SIMD.Float32x4(+0, 2, 3, 4), | 392 case 'Bool8x16': |
264 SIMD.Float32x4(+0, 2, 3, 4))); | 393 test(true, false); |
265 assertTrue(sameValueBoth(SIMD.Float32x4(-0, 2, 3, 4), | 394 test(false, true); |
266 SIMD.Float32x4(-0, 2, 3, 4))); | 395 break; |
267 assertTrue(sameValueZeroOnly(SIMD.Float32x4(+0, 2, 3, 4), | 396 } |
268 SIMD.Float32x4(-0, 2, 3, 4))); | |
269 assertTrue(sameValueZeroOnly(SIMD.Float32x4(-0, 2, 3, 4), | |
270 SIMD.Float32x4(+0, 2, 3, 4))); | |
271 } | 397 } |
272 | 398 |
273 | 399 |
274 function TestComparison(type, lanes) { | 400 function TestComparison(type, lanes) { |
275 var a = values[0], b = values[1]; | 401 var simdFn = SIMD[type]; |
276 | 402 var a = createInstance(type), b = createInstance(type); |
277 function lt() { a < b; } | 403 |
278 function gt() { a > b; } | 404 function compare(other) { |
279 function le() { a <= b; } | 405 var throwFuncs = [ |
280 function ge() { a >= b; } | 406 function lt() { a < b; }, |
281 function lt_same() { a < a; } | 407 function gt() { a > b; }, |
282 function gt_same() { a > a; } | 408 function le() { a <= b; }, |
283 function le_same() { a <= a; } | 409 function ge() { a >= b; }, |
284 function ge_same() { a >= a; } | 410 function lt_same() { a < a; }, |
285 | 411 function gt_same() { a > a; }, |
286 var throwFuncs = [lt, gt, le, ge, lt_same, gt_same, le_same, ge_same]; | 412 function le_same() { a <= a; }, |
287 | 413 function ge_same() { a >= a; }, |
288 for (var f of throwFuncs) { | 414 ]; |
289 assertThrows(f, TypeError); | 415 |
290 %OptimizeFunctionOnNextCall(f); | 416 for (var f of throwFuncs) { |
291 assertThrows(f, TypeError); | 417 assertThrows(f, TypeError); |
292 assertThrows(f, TypeError); | 418 %OptimizeFunctionOnNextCall(f); |
293 } | 419 assertThrows(f, TypeError); |
| 420 assertThrows(f, TypeError); |
| 421 } |
| 422 } |
| 423 |
| 424 // Test comparison against the same SIMD type. |
| 425 compare(b); |
| 426 // Test comparison against other types. |
| 427 checkTypeMatrix(type, compare); |
294 } | 428 } |
295 | 429 |
296 | 430 |
297 // Test SIMD value wrapping/boxing over non-builtins. | 431 // Test SIMD value wrapping/boxing over non-builtins. |
298 function TestCall(type, lanes) { | 432 function TestCall(type, lanes) { |
299 var simdFn = SIMD[type]; | 433 var simdFn = SIMD[type]; |
| 434 var instance = createInstance(type); |
300 simdFn.prototype.getThisProto = function () { | 435 simdFn.prototype.getThisProto = function () { |
301 return Object.getPrototypeOf(this); | 436 return Object.getPrototypeOf(this); |
302 } | 437 } |
303 for (var i in values) { | 438 assertTrue(instance.getThisProto() === simdFn.prototype) |
304 assertTrue(values[i].getThisProto() === simdFn.prototype) | |
305 } | |
306 } | 439 } |
307 | 440 |
308 | 441 |
309 function TestAsSetKey(type, lanes, set) { | 442 function TestAsSetKey(type, lanes, set) { |
| 443 var simdFn = SIMD[type]; |
| 444 var instance = createInstance(type); |
| 445 |
310 function test(set, key) { | 446 function test(set, key) { |
311 assertFalse(set.has(key)); | 447 assertFalse(set.has(key)); |
312 assertFalse(set.delete(key)); | 448 assertFalse(set.delete(key)); |
313 if (!(set instanceof WeakSet)) { | 449 if (!(set instanceof WeakSet)) { |
314 assertSame(set, set.add(key)); | 450 assertSame(set, set.add(key)); |
315 assertTrue(set.has(key)); | 451 assertTrue(set.has(key)); |
316 assertTrue(set.delete(key)); | 452 assertTrue(set.delete(key)); |
317 } else { | 453 } else { |
318 // SIMD values can't be used as keys in WeakSets. | 454 // SIMD values can't be used as keys in WeakSets. |
319 assertThrows(function() { set.add(key) }); | 455 assertThrows(function() { set.add(key) }); |
320 } | 456 } |
321 assertFalse(set.has(key)); | 457 assertFalse(set.has(key)); |
322 assertFalse(set.delete(key)); | 458 assertFalse(set.delete(key)); |
323 assertFalse(set.has(key)); | 459 assertFalse(set.has(key)); |
324 } | 460 } |
325 | 461 |
326 for (var i in values) { | 462 test(set, instance); |
327 test(set, values[i]); | |
328 } | |
329 } | 463 } |
330 | 464 |
331 | 465 |
332 function TestAsMapKey(type, lanes, map) { | 466 function TestAsMapKey(type, lanes, map) { |
| 467 var simdFn = SIMD[type]; |
| 468 var instance = createInstance(type); |
| 469 |
333 function test(map, key, value) { | 470 function test(map, key, value) { |
334 assertFalse(map.has(key)); | 471 assertFalse(map.has(key)); |
335 assertSame(undefined, map.get(key)); | 472 assertSame(undefined, map.get(key)); |
336 assertFalse(map.delete(key)); | 473 assertFalse(map.delete(key)); |
337 if (!(map instanceof WeakMap)) { | 474 if (!(map instanceof WeakMap)) { |
338 assertSame(map, map.set(key, value)); | 475 assertSame(map, map.set(key, value)); |
339 assertSame(value, map.get(key)); | 476 assertSame(value, map.get(key)); |
340 assertTrue(map.has(key)); | 477 assertTrue(map.has(key)); |
341 assertTrue(map.delete(key)); | 478 assertTrue(map.delete(key)); |
342 } else { | 479 } else { |
343 // SIMD values can't be used as keys in WeakMaps. | 480 // SIMD values can't be used as keys in WeakMaps. |
344 assertThrows(function() { map.set(key, value) }); | 481 assertThrows(function() { map.set(key, value) }); |
345 } | 482 } |
346 assertFalse(map.has(key)); | 483 assertFalse(map.has(key)); |
347 assertSame(undefined, map.get(key)); | 484 assertSame(undefined, map.get(key)); |
348 assertFalse(map.delete(key)); | 485 assertFalse(map.delete(key)); |
349 assertFalse(map.has(key)); | 486 assertFalse(map.has(key)); |
350 assertSame(undefined, map.get(key)); | 487 assertSame(undefined, map.get(key)); |
351 } | 488 } |
352 | 489 |
353 for (var i in values) { | 490 test(map, instance, {}); |
354 test(map, values[i], {}); | |
355 } | |
356 } | 491 } |
357 | 492 |
358 | 493 |
359 // Test SIMD type with Harmony reflect-apply. | 494 // Test SIMD type with Harmony reflect-apply. |
360 function TestReflectApply(type) { | 495 function TestReflectApply(type) { |
| 496 var simdFn = SIMD[type]; |
| 497 var instance = createInstance(type); |
| 498 |
361 function returnThis() { return this; } | 499 function returnThis() { return this; } |
362 function returnThisStrict() { 'use strict'; return this; } | 500 function returnThisStrict() { 'use strict'; return this; } |
363 function noop() {} | 501 function noop() {} |
364 function noopStrict() { 'use strict'; } | 502 function noopStrict() { 'use strict'; } |
365 var R = void 0; | 503 var R = void 0; |
366 | 504 |
367 for (var i in values) { | 505 assertSame(SIMD[type].prototype, |
368 assertSame(SIMD[type].prototype, | 506 Object.getPrototypeOf( |
369 Object.getPrototypeOf( | 507 Reflect.apply(returnThis, instance, []))); |
370 Reflect.apply(returnThis, values[i], []))); | 508 assertSame(instance, Reflect.apply(returnThisStrict, instance, [])); |
371 assertSame(values[i], Reflect.apply(returnThisStrict, values[i], [])); | |
372 | 509 |
373 assertThrows( | 510 assertThrows( |
374 function() { 'use strict'; Reflect.apply(values[i]); }, TypeError); | 511 function() { 'use strict'; Reflect.apply(instance); }, TypeError); |
375 assertThrows( | 512 assertThrows( |
376 function() { Reflect.apply(values[i]); }, TypeError); | 513 function() { Reflect.apply(instance); }, TypeError); |
377 assertThrows( | 514 assertThrows( |
378 function() { Reflect.apply(noopStrict, R, values[i]); }, TypeError); | 515 function() { Reflect.apply(noopStrict, R, instance); }, TypeError); |
379 assertThrows( | 516 assertThrows( |
380 function() { Reflect.apply(noop, R, values[i]); }, TypeError); | 517 function() { Reflect.apply(noop, R, instance); }, TypeError); |
381 } | |
382 } | 518 } |
383 | 519 |
384 | 520 |
385 function TestSIMDTypes() { | 521 function TestSIMDTypes() { |
386 var types = [ 'Float32x4' ]; | 522 for (var i = 0; i < simdTypeNames.length; ++i) { |
387 for (var i = 0; i < types.length; ++i) { | 523 var type = simdTypeNames[i], |
388 var type = types[i], | |
389 lanes = lanesForType(type); | 524 lanes = lanesForType(type); |
390 TestConstructor(type, lanes); | 525 TestConstructor(type, lanes); |
391 TestType(type, lanes); | 526 TestType(type, lanes); |
392 TestPrototype(type, lanes); | 527 TestPrototype(type, lanes); |
393 TestValueOf(type, lanes); | 528 TestValueOf(type, lanes); |
394 TestGet(type, lanes); | 529 TestGet(type, lanes); |
395 TestToBoolean(type, lanes); | 530 TestToBoolean(type, lanes); |
396 TestToString(type, lanes); | 531 TestToString(type, lanes); |
397 TestToNumber(type, lanes); | 532 TestToNumber(type, lanes); |
| 533 TestCoercions(type, lanes); |
398 TestEquality(type, lanes); | 534 TestEquality(type, lanes); |
399 TestSameValue(type, lanes); | 535 TestSameValue(type, lanes); |
400 TestComparison(type, lanes); | 536 TestComparison(type, lanes); |
401 TestCall(type, lanes); | 537 TestCall(type, lanes); |
402 TestAsSetKey(type, lanes, new Set); | 538 TestAsSetKey(type, lanes, new Set); |
403 TestAsSetKey(type, lanes, new WeakSet); | 539 TestAsSetKey(type, lanes, new WeakSet); |
404 TestAsMapKey(type, lanes, new Map); | 540 TestAsMapKey(type, lanes, new Map); |
405 TestAsMapKey(type, lanes, new WeakMap); | 541 TestAsMapKey(type, lanes, new WeakMap); |
406 TestReflectApply(type); | 542 TestReflectApply(type); |
407 } | 543 } |
408 } | 544 } |
409 TestSIMDTypes(); | 545 TestSIMDTypes(); |
| 546 |
| 547 // Tests for the global SIMD object. |
| 548 function TestSIMDObject() { |
| 549 assertSame(typeof SIMD, 'object'); |
| 550 assertSame(SIMD.constructor, Object); |
| 551 assertSame(Object.getPrototypeOf(SIMD), Object.prototype); |
| 552 assertSame(SIMD + "", "[object SIMD]"); |
| 553 // The SIMD object is mutable. |
| 554 SIMD.foo = "foo"; |
| 555 assertSame(SIMD.foo, "foo"); |
| 556 delete SIMD.foo; |
| 557 delete SIMD.Bool8x16; |
| 558 assertSame(SIMD.Bool8x16, undefined); |
| 559 } |
| 560 TestSIMDObject() |
OLD | NEW |