summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/heap-analysis/byteSize-of-object.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/heap-analysis/byteSize-of-object.js')
-rw-r--r--js/src/jit-test/tests/heap-analysis/byteSize-of-object.js83
1 files changed, 83 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/heap-analysis/byteSize-of-object.js b/js/src/jit-test/tests/heap-analysis/byteSize-of-object.js
new file mode 100644
index 000000000..3b667aa4a
--- /dev/null
+++ b/js/src/jit-test/tests/heap-analysis/byteSize-of-object.js
@@ -0,0 +1,83 @@
+// Check that JS::ubi::Node::size returns reasonable results for objects.
+
+// 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.
+
+// 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.
+if (!getBuildConfiguration()['moz-memory'])
+ quit(0);
+
+if (getBuildConfiguration()['pointer-byte-size'] == 4)
+ var s = (s32, s64) => s32
+else
+ var s = (s32, s64) => s64
+
+function tenure(obj) {
+ gc();
+ return obj;
+}
+
+// Return the byte size of |obj|, ensuring that the size is not affected by
+// being tenured. (We use 'survives a GC' as an approximation for 'tenuring'.)
+function tByteSize(obj) {
+ var size = byteSize(obj);
+ minorgc();
+ if (size != byteSize(obj))
+ return 0;
+ return size;
+}
+
+assertEq(tByteSize({}), s(16, 32));
+
+// Try objects with only named properties.
+assertEq(tByteSize({ w: 1 }), s(32, 48));
+assertEq(tByteSize({ w: 1, x: 2 }), s(32, 48));
+assertEq(tByteSize({ w: 1, x: 2, y: 3 }), s(48, 64));
+assertEq(tByteSize({ w: 1, x: 2, y: 3, z:4 }), s(48, 64));
+assertEq(tByteSize({ w: 1, x: 2, y: 3, z:4, a: 5 }), s(80, 96));
+
+// Try objects with only indexed properties.
+assertEq(tByteSize({ 0:0 }), s(96, 112));
+assertEq(tByteSize({ 0:0, 1:1 }), s(96, 112));
+assertEq(tByteSize({ 0:0, 1:1, 2:2 }), s(112, 128));
+assertEq(tByteSize({ 0:0, 1:1, 2:2, 3:3 }), s(112, 128));
+assertEq(tByteSize({ 0:0, 1:1, 2:2, 3:3, 4:4 }), s(144, 160));
+
+// Mix indexed and named properties, exploring each combination of the size
+// classes above.
+//
+// Oddly, the changes here as the objects grow are not simply the sums of the
+// changes above: for example, with one named property, the objects with three
+// and five indexed properties are in different size classes; but with three
+// named properties, there's no break there.
+assertEq(tByteSize({ w:1, 0:0 }), s(96, 112));
+assertEq(tByteSize({ w:1, 0:0, 1:1, 2:2 }), s(112, 128));
+assertEq(tByteSize({ w:1, 0:0, 1:1, 2:2, 3:3, 4:4 }), s(144, 160));
+assertEq(tByteSize({ w:1, x:2, y:3, 0:0 }), s(112, 128));
+assertEq(tByteSize({ w:1, x:2, y:3, 0:0, 1:1, 2:2 }), s(144, 160));
+assertEq(tByteSize({ w:1, x:2, y:3, 0:0, 1:1, 2:2, 3:3, 4:4 }), s(144, 160));
+assertEq(tByteSize({ w:1, x:2, y:3, z:4, a:6, 0:0 }), s(144, 160));
+assertEq(tByteSize({ w:1, x:2, y:3, z:4, a:6, 0:0, 1:1, 2:2 }), s(144, 160));
+assertEq(tByteSize({ w:1, x:2, y:3, z:4, a:6, 0:0, 1:1, 2:2, 3:3, 4:4 }), s(176, 192));
+
+// Check various lengths of array.
+assertEq(tByteSize([]), s(80, 96));
+assertEq(tByteSize([1]), s(48, 64));
+assertEq(tByteSize([1, 2]), s(48, 64));
+assertEq(tByteSize([1, 2, 3]), s(80, 96));
+assertEq(tByteSize([1, 2, 3, 4]), s(80, 96));
+assertEq(tByteSize([1, 2, 3, 4, 5]), s(80, 96));
+assertEq(tByteSize([1, 2, 3, 4, 5, 6]), s(80, 96));
+assertEq(tByteSize([1, 2, 3, 4, 5, 6, 7]), s(112, 128));
+assertEq(tByteSize([1, 2, 3, 4, 5, 6, 7, 8]), s(112, 128));
+
+// Various forms of functions.
+assertEq(tByteSize(function () {}), s(32, 64));
+assertEq(tByteSize(function () {}.bind()), s(48, 80));
+assertEq(tByteSize(() => 1), s(48, 80));
+assertEq(tByteSize(Math.sin), s(32, 64));