summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/heap-analysis/byteSize-of-bigint.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/heap-analysis/byteSize-of-bigint.js')
-rw-r--r--js/src/jit-test/tests/heap-analysis/byteSize-of-bigint.js122
1 files changed, 122 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/heap-analysis/byteSize-of-bigint.js b/js/src/jit-test/tests/heap-analysis/byteSize-of-bigint.js
new file mode 100644
index 0000000000..8b5994469e
--- /dev/null
+++ b/js/src/jit-test/tests/heap-analysis/byteSize-of-bigint.js
@@ -0,0 +1,122 @@
+// |jit-test| skip-if: !getBuildConfiguration()['moz-memory']
+// Run this test only if we're using jemalloc. Other malloc implementations
+// exhibit surprising behaviors. For example, 32-bit Fedora builds have
+// non-deterministic allocation sizes.
+
+// Check JS::ubi::Node::size results for BigInts.
+
+// We actually hard-code specific sizes into this test, even though they're
+// implementation details, because in practice there are only two architecture
+// variants to consider (32-bit and 64-bit), and if these sizes change, that's
+// something SpiderMonkey hackers really want to know; they're supposed to be
+// stable.
+
+const config = getBuildConfiguration();
+
+const pointerByteSize = config["pointer-byte-size"];
+assertEq(pointerByteSize === 4 || pointerByteSize === 8, true);
+
+const m32 = pointerByteSize === 4;
+
+// 32-bit: sizeof(CellWithLengthAndFlags) + 2 * sizeof(BigInt::Digit) = 8 + 2 * 4 = 16
+// 64-bit: sizeof(CellWithLengthAndFlags) + sizeof(BigInt::Digit) = 8 + 8 = 16
+const SIZE_OF_BIGINT = 16;
+
+// sizeof(BigInt::Digit)
+const SIZE_OF_DIGIT = pointerByteSize;
+
+// sizeof(JS::Value)
+const SIZE_OF_VALUE = 8;
+
+// See Nursery::bigIntHeaderSize().
+const SIZE_OF_BIGINT_HEADER = 8;
+
+const SIZE_OF_TENURED_BIGINT = SIZE_OF_BIGINT;
+const SIZE_OF_NURSERY_BIGINT = SIZE_OF_BIGINT + SIZE_OF_BIGINT_HEADER;
+
+function nurseryDigitSize(length) {
+ // See <https://bugzilla.mozilla.org/show_bug.cgi?id=1607186> for why we currently
+ // overallocate on 32-bit.
+ if (m32) {
+ length += (length & 1);
+ }
+ return length * SIZE_OF_DIGIT;
+}
+
+function mallocDigitSize(length) {
+ // See <https://bugzilla.mozilla.org/show_bug.cgi?id=1607186> for why we currently
+ // overallocate on 32-bit.
+ if (m32) {
+ length += (length & 1);
+ }
+
+ // Malloc buffer sizes are always a power of two.
+ return 1 << Math.ceil(Math.log2(length * SIZE_OF_DIGIT));
+}
+
+// Constant BigInts (tenured, inline digits).
+assertEq(byteSize(10n), SIZE_OF_TENURED_BIGINT);
+assertEq(byteSize(0xffff_ffff_ffff_ffffn), SIZE_OF_TENURED_BIGINT);
+
+// Constant BigInt (tenured, heap digits).
+assertEq(byteSize(0x1_0000_0000_0000_0000n),
+ SIZE_OF_TENURED_BIGINT + mallocDigitSize(m32 ? 3 : 2));
+assertEq(byteSize(0x1_0000_0000_0000_0000_0000_0000n),
+ SIZE_OF_TENURED_BIGINT + mallocDigitSize(m32 ? 4 : 2));
+assertEq(byteSize(0x1_0000_0000_0000_0000_0000_0000_0000_0000n),
+ SIZE_OF_TENURED_BIGINT + mallocDigitSize(m32 ? 5 : 3));
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Nursery BigInt tests below this point. //
+///////////////////////////////////////////////////////////////////////////////
+
+// Hack to skip this test if BigInts are not allocated in the nursery.
+{
+ const sample_nursery = BigInt(123456789);
+
+ const before = byteSize(sample_nursery);
+ gc();
+ const after = byteSize(sample_nursery);
+
+ let nursery_disabled = before == after;
+ if (nursery_disabled) {
+ printErr("nursery BigInts appear to be disabled");
+ quit(0);
+ }
+}
+
+// Convert an input BigInt, which is probably tenured because it's a literal in
+// the source text, to a nursery-allocated BigInt with the same contents.
+function copyBigInt(bi) {
+ var plusOne = bi + 1n;
+ return plusOne - 1n;
+}
+
+// Return the nursery byte size of |bi|.
+function nByteSize(bi) {
+ // BigInts that appear in the source will always be tenured.
+ return byteSize(copyBigInt(bi));
+}
+
+// BigInts (nursery, inline digits).
+assertEq(nByteSize(10n), SIZE_OF_NURSERY_BIGINT);
+assertEq(nByteSize(0xffff_ffff_ffff_ffffn), SIZE_OF_NURSERY_BIGINT);
+
+// BigInt (nursery, nursery heap digits).
+//
+// This assumes small nursery buffer allocations always succeed.
+assertEq(nByteSize(0x1_0000_0000_0000_0000n),
+ SIZE_OF_NURSERY_BIGINT + nurseryDigitSize(m32 ? 3 : 2));
+assertEq(nByteSize(0x1_0000_0000_0000_0000_0000_0000n),
+ SIZE_OF_NURSERY_BIGINT + nurseryDigitSize(m32 ? 4 : 2));
+assertEq(nByteSize(0x1_0000_0000_0000_0000_0000_0000_0000_0000n),
+ SIZE_OF_NURSERY_BIGINT + nurseryDigitSize(m32 ? 5 : 3));
+
+// BigInt (nursery, malloc heap digits).
+//
+// |Nursery::MaxNurseryBufferSize| is 1024, so when
+// |BigInt::digitLength * sizeof(BigInt::Digit)| exceeds 1024, the digits buffer
+// should be malloc'ed. Pick a larger number to be future-proof.
+assertEq(nByteSize(2n ** (64n * 1000n)),
+ SIZE_OF_NURSERY_BIGINT + mallocDigitSize(m32 ? 2002 : 1001));