Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions JSTests/stress/buffer-accessor-jit-bigint-write.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//@ requireOptions("--useDollarVM=1")

function shouldBe(actual, expected, message) {
if (actual !== expected) throw new Error(message + ": expected " + expected + " but got " + actual);
}
function shouldThrow(f, expected, message) {
let error = null;
try {
f();
} catch (e) {
error = e;
}
if (!(error instanceof expected)) throw new Error(message + ": expected a " + expected.name + " but got " + error);
}

const accessors = $vm.createBufferAccessors();
class Buffer extends Uint8Array {}
Object.assign(Buffer.prototype, accessors);

const buf = new Buffer(64);
const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);

function writeBigInt64LE(b, v, o) {
return b.writeBigInt64LE(v, o);
}
noInline(writeBigInt64LE);
function writeBigInt64BE(b, v, o) {
return b.writeBigInt64BE(v, o);
}
noInline(writeBigInt64BE);
function writeBigUInt64LE(b, v, o) {
return b.writeBigUInt64LE(v, o);
}
noInline(writeBigUInt64LE);
function writeBigUInt64BE(b, v, o) {
return b.writeBigUInt64BE(v, o);
}
noInline(writeBigUInt64BE);

const values = [0n, 1n, -1n, 42n, -42n, 2n ** 31n, -(2n ** 31n), 2n ** 32n + 7n, 2n ** 63n - 1n, -(2n ** 63n)];
for (let i = 0; i < 2e4; ++i) {
const o = (i & 7) * 8;
const v = values[i % values.length];
shouldBe(writeBigInt64LE(buf, v, o), o + 8, "writeBigInt64LE result");
shouldBe(dv.getBigInt64(o, true), v, "writeBigInt64LE store");
shouldBe(writeBigInt64BE(buf, v, o), o + 8, "writeBigInt64BE result");
shouldBe(dv.getBigInt64(o, false), v, "writeBigInt64BE store");
if (v >= 0n) {
shouldBe(writeBigUInt64LE(buf, v, o), o + 8, "writeBigUInt64LE result");
shouldBe(dv.getBigUint64(o, true), v, "writeBigUInt64LE store");
shouldBe(writeBigUInt64BE(buf, v, o), o + 8, "writeBigUInt64BE result");
shouldBe(dv.getBigUint64(o, false), v, "writeBigUInt64BE store");
}
}

for (let i = 0; i < 2e4; ++i) {
shouldBe(writeBigUInt64LE(buf, 2n ** 64n - 1n, 0), 8, "unsigned max");
shouldBe(dv.getBigUint64(0, true), 2n ** 64n - 1n, "unsigned max store");
shouldThrow(() => writeBigUInt64LE(buf, -1n, 0), RangeError, "unsigned negative");
shouldThrow(() => writeBigUInt64LE(buf, 2n ** 64n, 0), RangeError, "unsigned too big");
shouldThrow(() => writeBigInt64LE(buf, 2n ** 63n, 0), RangeError, "signed too big");
shouldThrow(() => writeBigInt64LE(buf, -(2n ** 63n) - 1n, 0), RangeError, "signed too small");
shouldThrow(() => writeBigInt64LE(buf, 2n ** 100n, 0), RangeError, "way too big");
shouldThrow(() => writeBigInt64LE(buf, 5, 0), TypeError, "a number is not a BigInt");
shouldThrow(() => writeBigInt64LE(buf, 0n, 57), RangeError, "out of bounds");
shouldBe(dv.getBigInt64(0, true), -1n, "the failed writes stored nothing");
}
46 changes: 46 additions & 0 deletions JSTests/stress/buffer-accessor-jit-byteoffset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//@ requireOptions("--useDollarVM=1")

let ab;
try {
ab = new ArrayBuffer(4 * 2 ** 30);
} catch (e) {
quit();
}
Object.assign(Uint8Array.prototype, $vm.createBufferAccessors());

function shouldBe(actual, expected, message) {
if (actual !== expected)
throw new Error(message + ": expected " + expected + " but got " + actual);
}
function shouldThrow(f, expected, message) {
let error = null;
try {
f();
} catch (e) {
error = e;
}
if (!(error instanceof expected))
throw new Error(message + ": expected a " + expected.name + " but got " + error);
}

const tailOffset = 4 * 2 ** 30 - 64;
const tail = new Uint8Array(ab, tailOffset, 64);
const wide = new Uint8Array(ab, 2 ** 31);
const raw = new DataView(ab);

function readAt(v, o) { return v.readInt32LE(o); }
function writeAt(v, x, o) { return v.writeInt32LE(x, o); }
noInline(readAt);
noInline(writeAt);

for (let i = 0; i < 3e5; ++i) {
shouldBe(writeAt(tail, i, 8), 12, "write into the ~4GB byteOffset view");
shouldBe(readAt(tail, 8), i, "read the ~4GB byteOffset view back");
shouldBe(writeAt(wide, ~i, wide.length - 4), wide.length, "write at the top of the 2GB byteOffset view");
shouldBe(readAt(wide, wide.length - 4), ~i, "read at the top of the 2GB byteOffset view");
}
shouldBe(raw.getInt32(tailOffset + 8, true), 3e5 - 1, "the store landed at byteOffset + offset in the raw buffer");
shouldBe(raw.getInt32(2 ** 31 + wide.length - 4, true), ~(3e5 - 1), "the store landed at the 2GB byteOffset");
shouldThrow(() => readAt(tail, 61), RangeError, "straddling the end of the small view");
shouldThrow(() => writeAt(wide, 0, wide.length - 3), RangeError, "straddling the end of the wide view");
shouldBe(numberOfDFGCompiles(readAt) <= 3, true, "the huge byteOffset does not cause recompiles");
Loading
Loading