tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

byteSize-of-bigint.js (4379B)


      1 // |jit-test| skip-if: !getBuildConfiguration("moz-memory")
      2 // Run this test only if we're using jemalloc. Other malloc implementations
      3 // exhibit surprising behaviors. For example, 32-bit Fedora builds have
      4 // non-deterministic allocation sizes.
      5 
      6 // Check JS::ubi::Node::size results for BigInts.
      7 
      8 // We actually hard-code specific sizes into this test, even though they're
      9 // implementation details, because in practice there are only two architecture
     10 // variants to consider (32-bit and 64-bit), and if these sizes change, that's
     11 // something SpiderMonkey hackers really want to know; they're supposed to be
     12 // stable.
     13 
     14 const pointerByteSize = getBuildConfiguration("pointer-byte-size");
     15 assertEq(pointerByteSize === 4 || pointerByteSize === 8, true);
     16 
     17 const m32 = pointerByteSize === 4;
     18 
     19 // 32-bit: sizeof(CellWithLengthAndFlags) + 2 * sizeof(BigInt::Digit) = 8 + 2 * 4 = 16
     20 // 64-bit: sizeof(CellWithLengthAndFlags) + sizeof(BigInt::Digit) = 8 + 8 = 16
     21 const SIZE_OF_BIGINT = 16;
     22 
     23 // sizeof(BigInt::Digit)
     24 const SIZE_OF_DIGIT = pointerByteSize;
     25 
     26 // sizeof(JS::Value)
     27 const SIZE_OF_VALUE = 8;
     28 
     29 // See Nursery::bigIntHeaderSize().
     30 const SIZE_OF_BIGINT_HEADER = 8;
     31 
     32 const SIZE_OF_TENURED_BIGINT = SIZE_OF_BIGINT;
     33 const SIZE_OF_NURSERY_BIGINT = SIZE_OF_BIGINT + SIZE_OF_BIGINT_HEADER;
     34 
     35 function nurseryDigitSize(length) {
     36  // See <https://bugzilla.mozilla.org/show_bug.cgi?id=1607186> for why we currently
     37  // overallocate on 32-bit.
     38  if (m32) {
     39    length += (length & 1);
     40  }
     41  return length * SIZE_OF_DIGIT;
     42 }
     43 
     44 function mallocDigitSize(length) {
     45  // See <https://bugzilla.mozilla.org/show_bug.cgi?id=1607186> for why we currently
     46  // overallocate on 32-bit.
     47  if (m32) {
     48    length += (length & 1);
     49  }
     50 
     51  // Malloc buffer sizes are always a power of two.
     52  return 1 << Math.ceil(Math.log2(length * SIZE_OF_DIGIT));
     53 }
     54 
     55 // Constant BigInts (tenured, inline digits).
     56 assertEq(byteSize(10n), SIZE_OF_TENURED_BIGINT);
     57 assertEq(byteSize(0xffff_ffff_ffff_ffffn), SIZE_OF_TENURED_BIGINT);
     58 
     59 // Constant BigInt (tenured, heap digits).
     60 assertEq(byteSize(0x1_0000_0000_0000_0000n),
     61         SIZE_OF_TENURED_BIGINT + mallocDigitSize(m32 ? 3 : 2));
     62 assertEq(byteSize(0x1_0000_0000_0000_0000_0000_0000n),
     63         SIZE_OF_TENURED_BIGINT + mallocDigitSize(m32 ? 4 : 2));
     64 assertEq(byteSize(0x1_0000_0000_0000_0000_0000_0000_0000_0000n),
     65         SIZE_OF_TENURED_BIGINT + mallocDigitSize(m32 ? 5 : 3));
     66 
     67 
     68 ///////////////////////////////////////////////////////////////////////////////
     69 // Nursery BigInt tests below this point.                                    //
     70 ///////////////////////////////////////////////////////////////////////////////
     71 
     72 // Hack to skip this test if BigInts are not allocated in the nursery.
     73 {
     74  const sample_nursery = BigInt(123456789);
     75 
     76  const before = byteSize(sample_nursery);
     77  gc();
     78  const after = byteSize(sample_nursery);
     79 
     80  let nursery_disabled = before == after;
     81  if (nursery_disabled) {
     82    printErr("nursery BigInts appear to be disabled");
     83    quit(0);
     84  }
     85 }
     86 
     87 // Convert an input BigInt, which is probably tenured because it's a literal in
     88 // the source text, to a nursery-allocated BigInt with the same contents.
     89 function copyBigInt(bi) {
     90  var plusOne = bi + 1n;
     91  return plusOne - 1n;
     92 }
     93 
     94 // Return the nursery byte size of |bi|.
     95 function nByteSize(bi) {
     96  // BigInts that appear in the source will always be tenured.
     97  return byteSize(copyBigInt(bi));
     98 }
     99 
    100 // BigInts (nursery, inline digits).
    101 assertEq(nByteSize(10n), SIZE_OF_NURSERY_BIGINT);
    102 assertEq(nByteSize(0xffff_ffff_ffff_ffffn), SIZE_OF_NURSERY_BIGINT);
    103 
    104 // BigInt (nursery, nursery heap digits).
    105 //
    106 // This assumes small nursery buffer allocations always succeed.
    107 assertEq(nByteSize(0x1_0000_0000_0000_0000n),
    108         SIZE_OF_NURSERY_BIGINT + nurseryDigitSize(m32 ? 3 : 2));
    109 assertEq(nByteSize(0x1_0000_0000_0000_0000_0000_0000n),
    110         SIZE_OF_NURSERY_BIGINT + nurseryDigitSize(m32 ? 4 : 2));
    111 assertEq(nByteSize(0x1_0000_0000_0000_0000_0000_0000_0000_0000n),
    112         SIZE_OF_NURSERY_BIGINT + nurseryDigitSize(m32 ? 5 : 3));
    113 
    114 // BigInt (nursery, malloc heap digits).
    115 //
    116 // |Nursery::MaxNurseryBufferSize| is 1024, so when
    117 // |BigInt::digitLength * sizeof(BigInt::Digit)| exceeds 1024, the digits buffer
    118 // should be malloc'ed. Pick a larger number to be future-proof.
    119 assertEq(nByteSize(2n ** (64n * 1000n)),
    120         SIZE_OF_NURSERY_BIGINT + mallocDigitSize(m32 ? 2002 : 1001));