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