diff --git a/implementation-contributed/curation_logs/javascriptcore.json b/implementation-contributed/curation_logs/javascriptcore.json index 7d84a9695c..8acbf0162d 100644 --- a/implementation-contributed/curation_logs/javascriptcore.json +++ b/implementation-contributed/curation_logs/javascriptcore.json @@ -1,6 +1,6 @@ { - "sourceRevisionAtLastExport": "ffc7368147", - "targetRevisionAtLastExport": "ac84caea5", + "sourceRevisionAtLastExport": "93457d631e", + "targetRevisionAtLastExport": "04c056b95", "curatedFiles": { "/stress/Number-isNaN-basics.js": "DELETED_IN_TARGET", "/stress/Object_static_methods_Object.getOwnPropertyDescriptors-proxy.js": "DELETED_IN_TARGET", diff --git a/implementation-contributed/javascriptcore/stress/characters-regexp-ignore-case.js b/implementation-contributed/javascriptcore/stress/characters-regexp-ignore-case.js new file mode 100644 index 0000000000..a587f95871 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/characters-regexp-ignore-case.js @@ -0,0 +1,77 @@ +function shouldBe(actual, expected) { + if (actual !== expected) + throw new Error('bad value: ' + actual); +} + +function testH(string) { + return string.match(/h/i); +} +noInline(testH); + +function testHe(string) { + return string.match(/he/i); +} +noInline(testHe); + +function testHel(string) { + return string.match(/hel/i); +} +noInline(testHel); + +function testHell(string) { + return string.match(/hell/i); +} +noInline(testHell); + +function testHello(string) { + return string.match(/hello/i); +} +noInline(testHello); + +function testHelloW(string) { + return string.match(/hellow/i); +} +noInline(testHelloW); + +function testHelloWo(string) { + return string.match(/hellowo/i); +} +noInline(testHelloWo); + +function testHelloWor(string) { + return string.match(/hellowor/i); +} +noInline(testHelloWor); + +function testHelloWorl(string) { + return string.match(/helloworl/i); +} +noInline(testHelloWorl); + +function testHelloWorld(string) { + return string.match(/helloworld/i); +} +noInline(testHelloWorld); + +for (var i = 0; i < 1e4; ++i) { + shouldBe(testH("HelloWorld")[0], `H`); + shouldBe(testHe("HelloWorld")[0], `He`); + shouldBe(testHel("HelloWorld")[0], `Hel`); + shouldBe(testHell("HelloWorld")[0], `Hell`); + shouldBe(testHello("HelloWorld")[0], `Hello`); + shouldBe(testHelloW("HelloWorld")[0], `HelloW`); + shouldBe(testHelloWo("HelloWorld")[0], `HelloWo`); + shouldBe(testHelloWor("HelloWorld")[0], `HelloWor`); + shouldBe(testHelloWorl("HelloWorld")[0], `HelloWorl`); + shouldBe(testHelloWorld("HelloWorld")[0], `HelloWorld`); + shouldBe(testH("HelloWorldこんにちは")[0], `H`); + shouldBe(testHe("HelloWorldこんにちは")[0], `He`); + shouldBe(testHel("HelloWorldこんにちは")[0], `Hel`); + shouldBe(testHell("HelloWorldこんにちは")[0], `Hell`); + shouldBe(testHello("HelloWorldこんにちは")[0], `Hello`); + shouldBe(testHelloW("HelloWorldこんにちは")[0], `HelloW`); + shouldBe(testHelloWo("HelloWorldこんにちは")[0], `HelloWo`); + shouldBe(testHelloWor("HelloWorldこんにちは")[0], `HelloWor`); + shouldBe(testHelloWorl("HelloWorldこんにちは")[0], `HelloWorl`); + shouldBe(testHelloWorld("HelloWorldこんにちは")[0], `HelloWorld`); +} diff --git a/implementation-contributed/javascriptcore/stress/characters-regexp.js b/implementation-contributed/javascriptcore/stress/characters-regexp.js new file mode 100644 index 0000000000..16b060e3b5 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/characters-regexp.js @@ -0,0 +1,77 @@ +function shouldBe(actual, expected) { + if (actual !== expected) + throw new Error('bad value: ' + actual); +} + +function testH(string) { + return string.match(/H/); +} +noInline(testH); + +function testHe(string) { + return string.match(/He/); +} +noInline(testHe); + +function testHel(string) { + return string.match(/Hel/); +} +noInline(testHel); + +function testHell(string) { + return string.match(/Hell/); +} +noInline(testHell); + +function testHello(string) { + return string.match(/Hello/); +} +noInline(testHello); + +function testHelloW(string) { + return string.match(/HelloW/); +} +noInline(testHelloW); + +function testHelloWo(string) { + return string.match(/HelloWo/); +} +noInline(testHelloWo); + +function testHelloWor(string) { + return string.match(/HelloWor/); +} +noInline(testHelloWor); + +function testHelloWorl(string) { + return string.match(/HelloWorl/); +} +noInline(testHelloWorl); + +function testHelloWorld(string) { + return string.match(/HelloWorld/); +} +noInline(testHelloWorld); + +for (var i = 0; i < 1e4; ++i) { + shouldBe(testH("HelloWorld")[0], `H`); + shouldBe(testHe("HelloWorld")[0], `He`); + shouldBe(testHel("HelloWorld")[0], `Hel`); + shouldBe(testHell("HelloWorld")[0], `Hell`); + shouldBe(testHello("HelloWorld")[0], `Hello`); + shouldBe(testHelloW("HelloWorld")[0], `HelloW`); + shouldBe(testHelloWo("HelloWorld")[0], `HelloWo`); + shouldBe(testHelloWor("HelloWorld")[0], `HelloWor`); + shouldBe(testHelloWorl("HelloWorld")[0], `HelloWorl`); + shouldBe(testHelloWorld("HelloWorld")[0], `HelloWorld`); + shouldBe(testH("HelloWorldこんにちは")[0], `H`); + shouldBe(testHe("HelloWorldこんにちは")[0], `He`); + shouldBe(testHel("HelloWorldこんにちは")[0], `Hel`); + shouldBe(testHell("HelloWorldこんにちは")[0], `Hell`); + shouldBe(testHello("HelloWorldこんにちは")[0], `Hello`); + shouldBe(testHelloW("HelloWorldこんにちは")[0], `HelloW`); + shouldBe(testHelloWo("HelloWorldこんにちは")[0], `HelloWo`); + shouldBe(testHelloWor("HelloWorldこんにちは")[0], `HelloWor`); + shouldBe(testHelloWorl("HelloWorldこんにちは")[0], `HelloWorl`); + shouldBe(testHelloWorld("HelloWorldこんにちは")[0], `HelloWorld`); +} diff --git a/implementation-contributed/javascriptcore/stress/dataview-jit-bounds-checks.js b/implementation-contributed/javascriptcore/stress/dataview-jit-bounds-checks.js new file mode 100644 index 0000000000..bd9a6dae0d --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/dataview-jit-bounds-checks.js @@ -0,0 +1,114 @@ +"use strict"; + +function assert(b, m = "") { + if (!b) + throw new Error("Bad: " + m); +} + +let getOps = { + getUint8: 1, + getUint16: 2, + getUint32: 4, + getInt8: 1, + getInt16: 2, + getInt32: 4, + getFloat32: 4, + getFloat64: 8, +}; + +let setOps = { + setUint8: 1, + setUint16: 2, + setUint32: 4, + setInt8: 1, + setInt16: 2, + setInt32: 4, + setFloat32: 4, + setFloat64: 8, +}; + +let getFuncs = []; +for (let p of Object.keys(getOps)) { + let endOfCall = getOps[p] === 1 ? ");" : ", true);"; + let str = ` + (function ${p}(dv, index) { + return dv.${p}(index${endOfCall} + }) + `; + + let func = eval(str); + noInline(func); + getFuncs.push(func); +} + +let setFuncs = []; +for (let p of Object.keys(setOps)) { + let endOfCall = setOps[p] === 1 ? ");" : ", true);"; + let str = ` + (function ${p}(dv, index, value) { + return dv.${p}(index, value${endOfCall} + }) + `; + + let func = eval(str); + noInline(func); + setFuncs.push(func); +} + +function assertThrowsRangeError(f) { + let e = null; + try { + f(); + } catch(err) { + e = err; + } + assert(e instanceof RangeError, e); +} + +function test(warmup) { + const size = 16*1024; + let ab = new ArrayBuffer(size); + let dv = new DataView(ab); + for (let i = 0; i < warmup; ++i) { + for (let f of getFuncs) { + f(dv, 0); + } + + for (let f of setFuncs) { + f(dv, 0, 10); + } + } + + for (let f of getFuncs) { + assertThrowsRangeError(() => { + let index = size - getOps[f.name] + 1; + f(dv, index); + }); + assertThrowsRangeError(() => { + let index = -1; + f(dv, index); + }); + assertThrowsRangeError(() => { + let index = -2147483648; + f(dv, index); + }); + } + + for (let f of setFuncs) { + assertThrowsRangeError(() => { + let index = size - setOps[f.name] + 1; + f(dv, index, 10); + }); + assertThrowsRangeError(() => { + let index = -1; + f(dv, index, 10); + }); + assertThrowsRangeError(() => { + let index = -2147483648; + f(dv, index, 10); + }); + } +} + +test(2000); +test(10000); diff --git a/implementation-contributed/javascriptcore/stress/dataview-jit-get.js b/implementation-contributed/javascriptcore/stress/dataview-jit-get.js new file mode 100644 index 0000000000..e0665af20c --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/dataview-jit-get.js @@ -0,0 +1,305 @@ +"use strict"; + +function assert(b) { + if (!b) + throw new Error("Bad!"); +} + +function test1() { + function bigEndian(o, i) { + return o.getInt32(i, false); + } + noInline(bigEndian); + function littleEndian(o, i) { + return o.getInt32(i, true); + } + noInline(littleEndian); + function biEndian(o, i, b) { + return o.getInt32(i, b); + } + noInline(biEndian); + + let ab = new ArrayBuffer(4); + let ta = new Int32Array(ab); + ta[0] = 0x01020304; + let dv = new DataView(ab); + + for (let i = 0; i < 10000; ++i) { + assert(bigEndian(dv, 0) === 0x04030201); + assert(littleEndian(dv, 0) === 0x01020304); + if (i % 2) + assert(biEndian(dv, 0, true) === 0x01020304); + else + assert(biEndian(dv, 0, false) === 0x04030201); + } + + for (let i = 0; i < 10000; ++i) { + assert(bigEndian(dv, 0) === 0x04030201); + assert(littleEndian(dv, 0) === 0x01020304); + if (i % 2) + assert(biEndian(dv, 0, true) === 0x01020304); + else + assert(biEndian(dv, 0, false) === 0x04030201); + } + + // Make sure we get the right sign. + ta[0] = -32361386; // 0xfe123456 + for (let i = 0; i < 10000; ++i) { + assert(bigEndian(dv, 0) === 0x563412fe); + assert(littleEndian(dv, 0) === -32361386); + if (i % 2) + assert(biEndian(dv, 0, true) === -32361386); + else + assert(biEndian(dv, 0, false) === 0x563412fe); + } + + // -2146290602 == (int)0x80123456 + ta[0] = 0x56341280; + for (let i = 0; i < 10000; ++i) { + assert(bigEndian(dv, 0) === -2146290602); + assert(littleEndian(dv, 0) === 0x56341280); + if (i % 2) + assert(biEndian(dv, 0, true) === 0x56341280); + else + assert(biEndian(dv, 0, false) === -2146290602); + } +} +test1(); + +function test2() { + function bigEndian(o, i) { + return o.getInt16(i, false); + } + noInline(bigEndian); + function littleEndian(o, i) { + return o.getInt16(i, true); + } + noInline(littleEndian); + function biEndian(o, i, b) { + return o.getInt16(i, b); + } + noInline(biEndian); + + let ab = new ArrayBuffer(2); + let ta = new Int16Array(ab); + ta[0] = 0x0102; + let dv = new DataView(ab); + + for (let i = 0; i < 10000; ++i) { + assert(bigEndian(dv, 0) === 0x0201); + assert(littleEndian(dv, 0) === 0x0102); + if (i % 2) + assert(biEndian(dv, 0, true) === 0x0102); + else + assert(biEndian(dv, 0, false) === 0x0201); + } + + // Check sign. + ta[0] = -512; // 0xfe00 + for (let i = 0; i < 10000; ++i) { + assert(bigEndian(dv, 0) === 0x00fe); + assert(littleEndian(dv, 0) === -512); + if (i % 2) + assert(biEndian(dv, 0, true) === -512); + else + assert(biEndian(dv, 0, false) === 0x00fe); + } + + // Check sign extension. + ta[0] = 0x00fe; + for (let i = 0; i < 10000; ++i) { + assert(bigEndian(dv, 0) === -512); + assert(littleEndian(dv, 0) === 0x00fe); + if (i % 2) + assert(biEndian(dv, 0, true) === 0x00fe); + else + assert(biEndian(dv, 0, false) === -512); + } +} +test2(); + +function test3() { + function bigEndian(o, i) { + return o.getFloat32(i, false); + } + noInline(bigEndian); + function littleEndian(o, i) { + return o.getFloat32(i, true); + } + noInline(littleEndian); + function biEndian(o, i, b) { + return o.getFloat32(i, b); + } + noInline(biEndian); + + let ab = new ArrayBuffer(4); + let ta = new Float32Array(ab); + const normal = 12912.403; // 0x4649c19d + const normalAsDouble = 12912.403320312500; + + const flipped = -5.1162437589918884e-21; + ta[0] = normal; + + let dv = new DataView(ab); + for (let i = 0; i < 10000; ++i) { + assert(bigEndian(dv, 0) === flipped); + assert(littleEndian(dv, 0) === 12912.403320312500); + if (i % 2) + assert(biEndian(dv, 0, true) === normalAsDouble); + else + assert(biEndian(dv, 0, false) === flipped); + } +} +test3(); + +function test4() { + function bigEndian(o, i) { + return o.getUint32(i, false); + } + noInline(bigEndian); + function littleEndian(o, i) { + return o.getUint32(i, true); + } + noInline(littleEndian); + function biEndian(o, i, b) { + return o.getUint32(i, b); + } + noInline(biEndian); + + let ab = new ArrayBuffer(4); + let ta = new Uint32Array(ab); + ta[0] = 0xa0b0d0f0; + + let dv = new DataView(ab); + for (let i = 0; i < 10000; ++i) { + assert(bigEndian(dv, 0) === 0xf0d0b0a0); + assert(littleEndian(dv, 0) === 0xa0b0d0f0); + if (i % 2) + assert(biEndian(dv, 0, true) === 0xa0b0d0f0); + else + assert(biEndian(dv, 0, false) === 0xf0d0b0a0); + } +} +test4(); + +function test5() { + function bigEndian(o, i) { + return o.getUint16(i, false); + } + noInline(bigEndian); + function littleEndian(o, i) { + return o.getUint16(i, true); + } + noInline(littleEndian); + function biEndian(o, i, b) { + return o.getUint16(i, b); + } + noInline(biEndian); + + let ab = new ArrayBuffer(4); + let ta = new Uint32Array(ab); + ta[0] = 0xa0b0d0f0; + + let dv = new DataView(ab); + for (let i = 0; i < 10000; ++i) { + assert(littleEndian(dv, 0) == 0xd0f0); + assert(bigEndian(dv, 0) == 0xf0d0); + + assert(littleEndian(dv, 1) == 0xb0d0); + assert(bigEndian(dv, 1) == 0xd0b0); + + assert(littleEndian(dv, 2) == 0xa0b0); + assert(bigEndian(dv, 2) == 0xb0a0); + + assert(biEndian(dv, 0, true) == 0xd0f0); + assert(biEndian(dv, 0, false) == 0xf0d0); + + assert(biEndian(dv, 1, true) == 0xb0d0); + assert(biEndian(dv, 1, false) == 0xd0b0); + + assert(biEndian(dv, 2, true) == 0xa0b0); + assert(biEndian(dv, 2, false) == 0xb0a0); + } +} +test5(); + +function test6() { + function bigEndian(o, i) { + return o.getInt16(i, false); + } + noInline(bigEndian); + function littleEndian(o, i) { + return o.getInt16(i, true); + } + noInline(littleEndian); + function biEndian(o, i, b) { + return o.getInt16(i, b); + } + noInline(biEndian); + + let ab = new ArrayBuffer(4); + let ta = new Uint32Array(ab); + ta[0] = 0xa070fa01; + + let dv = new DataView(ab); + for (let i = 0; i < 10000; ++i) { + assert(littleEndian(dv, 0) == -1535); + assert(bigEndian(dv, 0) == 0x01fa); + + assert(littleEndian(dv, 1) == 0x70fa); + assert(bigEndian(dv, 1) == -1424); + + assert(littleEndian(dv, 2) == -24464); + assert(bigEndian(dv, 2) == 0x70a0); + + assert(biEndian(dv, 0, true) == -1535); + assert(biEndian(dv, 0, false) == 0x01fa); + + assert(biEndian(dv, 1, true) == 0x70fa); + assert(biEndian(dv, 1, false) == -1424); + + assert(biEndian(dv, 2, true) == -24464); + assert(biEndian(dv, 2, false) == 0x70a0); + } +} +test6(); + +function test7() { + function load(o, i) { + return o.getInt8(i); + } + noInline(load); + + let ab = new ArrayBuffer(4); + let ta = new Uint32Array(ab); + ta[0] = 0xa070fa01; + + let dv = new DataView(ab); + for (let i = 0; i < 10000; ++i) { + assert(load(dv, 0) === 0x01); + assert(load(dv, 1) === -6); + assert(load(dv, 2) === 0x70); + assert(load(dv, 3) === -96); + } +} +test7(); + +function test8() { + function load(o, i) { + return o.getUint8(i); + } + noInline(load); + + let ab = new ArrayBuffer(4); + let ta = new Uint32Array(ab); + ta[0] = 0xa070fa01; + + let dv = new DataView(ab); + for (let i = 0; i < 10000; ++i) { + assert(load(dv, 0) === 0x01); + assert(load(dv, 1) === 0xfa); + assert(load(dv, 2) === 0x70); + assert(load(dv, 3) === 0xa0) + } +} +test8(); diff --git a/implementation-contributed/javascriptcore/stress/dataview-jit-neuter.js b/implementation-contributed/javascriptcore/stress/dataview-jit-neuter.js new file mode 100644 index 0000000000..635fc4c712 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/dataview-jit-neuter.js @@ -0,0 +1,59 @@ +"use strict"; + +function assert(b) { + if (!b) + throw new Error("Bad!"); +} + +function test() { + function load(o, i) { + return o.getUint8(i); + } + noInline(load); + + let ab = new ArrayBuffer(4); + let ta = new Uint32Array(ab); + ta[0] = 0xa070fa01; + let dv = new DataView(ab); + + for (let i = 0; i < 1000; ++i) { + assert(load(dv, 0) === 0x01); + } + + transferArrayBuffer(ab); + let e = null; + try { + load(dv, 0); + } catch(err) { + e = err; + } + assert(e instanceof RangeError); +} +test(); + + +function test2() { + function load(o, i) { + return o.getUint8(i); + } + noInline(load); + + let ab = new ArrayBuffer(4); + let ta = new Uint32Array(ab); + ta[0] = 0xa070fa01; + let dv = new DataView(ab); + + for (let i = 0; i < 10000; ++i) { + assert(load(dv, 0) === 0x01); + } + + transferArrayBuffer(ab); + let e = null; + try { + load(dv, 0); + } catch(err) { + e = err; + } + assert(e instanceof RangeError); +} +test2(); diff --git a/implementation-contributed/javascriptcore/stress/dataview-jit-set.js b/implementation-contributed/javascriptcore/stress/dataview-jit-set.js new file mode 100644 index 0000000000..b32ec895f2 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/dataview-jit-set.js @@ -0,0 +1,440 @@ +"use strict"; + +function assert(b) { + if (!b) + throw new Error; +} + +function readHex(dv, bytes) { + function isLittleEndian() { + let b = new ArrayBuffer(4); + let dv = new DataView(b); + dv.setInt32(0, 0x00112233, true); + return dv.getUint8(0) === 0x33; + } + let str = ""; + function readByte(i) { + let b = dv.getUint8(i).toString(16); + if (b.length === 1) + b = "0" + b; + else + assert(b.length === 2) + return b; + } + if (isLittleEndian()) { + for (let i = bytes; i--;) + str = str + readByte(i); + } else { + for (let i = 0; i < bytes; ++i) + str = str + readByte(i); + } + + return "0x" + str; +} + +{ + let b = new ArrayBuffer(4); + let dv = new DataView(b); + dv.setInt32(0, 0x00112233, true); + assert(readHex(dv, 4) === "0x00112233"); +} + +function test() { + function storeLittleEndian(dv, index, value) { + dv.setInt16(index, value, true); + } + noInline(storeLittleEndian); + + function storeBigEndian(dv, index, value) { + dv.setInt16(index, value, false); + } + noInline(storeBigEndian); + + function store(dv, index, value, littleEndian) { + dv.setInt16(index, value, littleEndian); + } + noInline(store); + + let buffer = new ArrayBuffer(2); + let arr = new Uint16Array(buffer); + let dv = new DataView(buffer); + + for (let i = 0; i < 10000; ++i) { + storeLittleEndian(dv, 0, 0xfaba); + assert(arr[0] === 0xfaba); + + store(dv, 0, 0xabcd, true); + assert(arr[0] === 0xabcd); + + store(dv, 0, 0xbadbeef, true); + assert(arr[0] === 0xbeef); + + storeLittleEndian(dv, 0, 0xbb4db33f, true); + assert(arr[0] === 0xb33f); + + storeBigEndian(dv, 0, 0xfada); + assert(arr[0] === 0xdafa); + + storeBigEndian(dv, 0, 0x12ab); + assert(arr[0] === 0xab12); + + store(dv, 0, 0x1234, false); + assert(arr[0] === 0x3412); + + store(dv, 0, 0x0102, false); + assert(arr[0] === 0x0201); + + store(dv, 0, -1, false); + assert(arr[0] === 0xffff); + + store(dv, 0, -2, false); + assert(arr[0] === 0xfeff); + + storeBigEndian(dv, 0, -1); + assert(arr[0] === 0xffff); + + storeBigEndian(dv, 0, -2); + assert(arr[0] === 0xfeff); + + storeBigEndian(dv, 0, -2147483648); + assert(arr[0] === 0x0000); + + storeLittleEndian(dv, 0, -2147483648); + assert(arr[0] === 0x0000); + + storeLittleEndian(dv, 0, -2147478988); + assert(arr[0] === 0x1234); + + storeBigEndian(dv, 0, -2147478988); + assert(arr[0] === 0x3412); + } +} +test(); + +function test2() { + function storeLittleEndian(dv, index, value) { + dv.setUint16(index, value, true); + } + noInline(storeLittleEndian); + + function storeBigEndian(dv, index, value) { + dv.setUint16(index, value, false); + } + noInline(storeBigEndian); + + function store(dv, index, value, littleEndian) { + dv.setUint16(index, value, littleEndian); + } + noInline(store); + + let buffer = new ArrayBuffer(2); + let arr = new Uint16Array(buffer); + let dv = new DataView(buffer); + + for (let i = 0; i < 10000; ++i) { + storeLittleEndian(dv, 0, 0xfaba); + assert(arr[0] === 0xfaba); + + store(dv, 0, 0xabcd, true); + assert(arr[0] === 0xabcd); + + store(dv, 0, 0xbadbeef, true); + assert(arr[0] === 0xbeef); + + storeLittleEndian(dv, 0, 0xbb4db33f, true); + assert(arr[0] === 0xb33f); + + storeBigEndian(dv, 0, 0xfada); + assert(arr[0] === 0xdafa); + + storeBigEndian(dv, 0, 0x12ab); + assert(arr[0] === 0xab12); + + store(dv, 0, 0x1234, false); + assert(arr[0] === 0x3412); + + store(dv, 0, 0x0102, false); + assert(arr[0] === 0x0201); + + store(dv, 0, -1, false); + assert(arr[0] === 0xffff); + + store(dv, 0, -2, false); + assert(arr[0] === 0xfeff); + + storeBigEndian(dv, 0, -1); + assert(arr[0] === 0xffff); + + storeBigEndian(dv, 0, -2); + assert(arr[0] === 0xfeff); + + storeBigEndian(dv, 0, -2147483648); + assert(arr[0] === 0x0000); + + storeLittleEndian(dv, 0, -2147483648); + assert(arr[0] === 0x0000); + + storeLittleEndian(dv, 0, -2147478988); + assert(arr[0] === 0x1234); + + storeBigEndian(dv, 0, -2147478988); + assert(arr[0] === 0x3412); + } +} +test2(); + +function test3() { + function storeLittleEndian(dv, index, value) { + dv.setUint32(index, value, true); + } + noInline(storeLittleEndian); + + function storeBigEndian(dv, index, value) { + dv.setUint32(index, value, false); + } + noInline(storeBigEndian); + + function store(dv, index, value, littleEndian) { + dv.setUint32(index, value, littleEndian); + } + noInline(store); + + let buffer = new ArrayBuffer(4); + let arr = new Uint32Array(buffer); + let arr2 = new Int32Array(buffer); + let dv = new DataView(buffer); + + for (let i = 0; i < 10000; ++i) { + storeLittleEndian(dv, 0, 0xffffffff); + assert(arr[0] === 0xffffffff); + assert(arr2[0] === -1); + + storeLittleEndian(dv, 0, 0xffaabbcc); + assert(arr[0] === 0xffaabbcc); + + storeBigEndian(dv, 0, 0x12345678); + assert(arr[0] === 0x78563412); + + storeBigEndian(dv, 0, 0xffaabbcc); + assert(arr[0] === 0xccbbaaff); + + store(dv, 0, 0xfaeadaca, false); + assert(arr[0] === 0xcadaeafa); + + store(dv, 0, 0xcadaeafa, false); + assert(arr2[0] === -85271862); + + store(dv, 0, 0x12345678, false); + assert(arr[0] === 0x78563412); + + storeBigEndian(dv, 0, 0xbeeffeeb); + assert(arr2[0] === -335614018); + } +} +test3(); + +function test4() { + function storeLittleEndian(dv, index, value) { + dv.setInt32(index, value, true); + } + noInline(storeLittleEndian); + + function storeBigEndian(dv, index, value) { + dv.setInt32(index, value, false); + } + noInline(storeBigEndian); + + function store(dv, index, value, littleEndian) { + dv.setInt32(index, value, littleEndian); + } + noInline(store); + + let buffer = new ArrayBuffer(4); + let arr = new Uint32Array(buffer); + let arr2 = new Int32Array(buffer); + let dv = new DataView(buffer); + + for (let i = 0; i < 10000; ++i) { + storeLittleEndian(dv, 0, 0xffffffff); + assert(arr[0] === 0xffffffff); + assert(arr2[0] === -1); + + storeLittleEndian(dv, 0, 0xffaabbcc); + assert(arr[0] === 0xffaabbcc); + + storeBigEndian(dv, 0, 0x12345678); + assert(arr[0] === 0x78563412); + + storeBigEndian(dv, 0, 0xffaabbcc); + assert(arr[0] === 0xccbbaaff); + + store(dv, 0, 0xfaeadaca, false); + assert(arr[0] === 0xcadaeafa); + + store(dv, 0, 0xcadaeafa, false); + assert(arr2[0] === -85271862); + + store(dv, 0, 0x12345678, false); + assert(arr[0] === 0x78563412); + + storeBigEndian(dv, 0, 0xbeeffeeb); + assert(arr2[0] === -335614018); + } +} +test4(); + +function test5() { + function storeLittleEndian(dv, index, value) { + dv.setFloat32(index, value, true); + } + noInline(storeLittleEndian); + + function storeBigEndian(dv, index, value) { + dv.setFloat32(index, value, false); + } + noInline(storeBigEndian); + + function store(dv, index, value, littleEndian) { + dv.setFloat32(index, value, littleEndian); + } + noInline(store); + + let buffer = new ArrayBuffer(4); + let arr = new Float32Array(buffer); + let bits = new Uint32Array(buffer); + let dv = new DataView(buffer); + + for (let i = 0; i < 10000; ++i) { + storeLittleEndian(dv, 0, 1.5); + assert(arr[0] === 1.5); + + storeLittleEndian(dv, 0, 12912.124123215122); + assert(arr[0] === 12912.1240234375); + assert(bits[0] === 0x4649c07f); + + storeLittleEndian(dv, 0, NaN); + assert(isNaN(arr[0])); + assert(bits[0] === 0x7FC00000); + + storeLittleEndian(dv, 0, 2.3879393e-38); + assert(arr[0] === 2.387939260590663e-38); + assert(bits[0] === 0x01020304); + + storeBigEndian(dv, 0, 2.3879393e-38); + assert(arr[0] === 1.539989614439558e-36); + assert(bits[0] === 0x04030201); + } +} +test5(); + +function test6() { + function storeLittleEndian(dv, index, value) { + dv.setFloat64(index, value, true); + } + noInline(storeLittleEndian); + + function storeBigEndian(dv, index, value) { + dv.setFloat64(index, value, false); + } + noInline(storeBigEndian); + + function store(dv, index, value, littleEndian) { + dv.setFloat64(index, value, littleEndian); + } + noInline(store); + + let buffer = new ArrayBuffer(8); + let arr = new Float64Array(buffer); + let dv = new DataView(buffer); + + for (let i = 0; i < 10000; ++i) { + storeLittleEndian(dv, 0, NaN); + assert(isNaN(arr[0])); + + storeLittleEndian(dv, 0, -2.5075187084135162e+284); + assert(arr[0] === -2.5075187084135162e+284); + assert(readHex(dv, 8) === "0xfafafafafafafafa"); + + store(dv, 0, 124.553, true); + assert(readHex(dv, 8) === "0x405f23645a1cac08"); + + store(dv, 0, Infinity, true); + assert(readHex(dv, 8) === "0x7ff0000000000000"); + + store(dv, 0, Infinity, false); + assert(readHex(dv, 8) === "0x000000000000f07f"); + + store(dv, 0, -Infinity, true); + assert(readHex(dv, 8) === "0xfff0000000000000"); + + storeBigEndian(dv, 0, -2.5075187084135162e+284); + assert(arr[0] === -2.5075187084135162e+284); + assert(readHex(dv, 8) === "0xfafafafafafafafa"); + + storeBigEndian(dv, 0, 124.553); + assert(readHex(dv, 8) === "0x08ac1c5a64235f40"); + } +} +test6(); + +function test7() { + function store(dv, index, value) { + dv.setInt8(index, value); + } + noInline(store); + + let buffer = new ArrayBuffer(1); + let arr = new Uint8Array(buffer); + let arr2 = new Int8Array(buffer); + let dv = new DataView(buffer); + + for (let i = 0; i < 10000; ++i) { + store(dv, 0, 0xff); + assert(arr[0] === 0xff); + assert(arr2[0] === -1); + + store(dv, 0, 0xff00); + assert(arr[0] === 0); + assert(arr2[0] === 0); + + store(dv, 0, -1); + assert(arr[0] === 0xff); + assert(arr2[0] === -1); + + store(dv, 0, 0x0badbeef); + assert(arr[0] === 0xef); + assert(arr2[0] === -17); + } +} +test7(); + +function test8() { + function store(dv, index, value) { + dv.setInt8(index, value); + } + noInline(store); + + let buffer = new ArrayBuffer(1); + let arr = new Uint8Array(buffer); + let arr2 = new Int8Array(buffer); + let dv = new DataView(buffer); + + for (let i = 0; i < 10000; ++i) { + store(dv, 0, 0xff); + assert(arr[0] === 0xff); + assert(arr2[0] === -1); + + store(dv, 0, 0xff00); + assert(arr[0] === 0); + assert(arr2[0] === 0); + + store(dv, 0, -1); + assert(arr[0] === 0xff); + assert(arr2[0] === -1); + + store(dv, 0, 0x0badbeef); + assert(arr[0] === 0xef); + assert(arr2[0] === -17); + } +} +test8(); diff --git a/implementation-contributed/javascriptcore/stress/dataview-jit-unaligned-accesses.js b/implementation-contributed/javascriptcore/stress/dataview-jit-unaligned-accesses.js new file mode 100644 index 0000000000..70918a3906 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/dataview-jit-unaligned-accesses.js @@ -0,0 +1,75 @@ +"use strict"; + +function assert(b, m = "") { + if (!b) + throw new Error("Bad: " + m); +} + +let getOps = { + getUint8: 1, + getUint16: 2, + getUint32: 4, + getInt8: 1, + getInt16: 2, + getInt32: 4, + getFloat32: 4, + getFloat64: 8, +}; + +let setOps = { + setUint8: 1, + setUint16: 2, + setUint32: 4, + setInt8: 1, + setInt16: 2, + setInt32: 4, + setFloat32: 4, + setFloat64: 8, +}; + +let getFuncs = []; +for (let p of Object.keys(getOps)) { + let endOfCall = getOps[p] === 1 ? ");" : ", true);"; + let str = ` + (function ${p}(dv, index) { + return dv.${p}(index${endOfCall} + }) + `; + + let func = eval(str); + noInline(func); + getFuncs.push(func); +} + +let setFuncs = []; +for (let p of Object.keys(setOps)) { + let endOfCall = setOps[p] === 1 ? ");" : ", true);"; + let str = ` + (function ${p}(dv, index, value) { + dv.${p}(index, value${endOfCall} + }) + `; + + let func = eval(str); + noInline(func); + setFuncs.push(func); +} + +function test() { + const size = 16*1024; + let ab = new ArrayBuffer(size); + let dv = new DataView(ab); + for (let i = 0; i < 100000; ++i) { + let index = (Math.random() * size) >>> 0; + index = Math.max(index - 8, 0); + for (let f of getFuncs) { + f(dv, index); + } + + for (let f of setFuncs) { + f(dv, index, 10); + } + } + +} +test();