tor-browser

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

commit 04b79e143f1822d644cbe64f2dc106cf8f751f49
parent e1f5e5d7187a9cf6ac7835b9e9b529863fb95334
Author: Julian Seward <jseward@acm.org>
Date:   Tue, 30 Sep 2025 16:32:03 +0000

Bug 1991368 - Add js::gc::AllocKind::OBJECT6.  r=jonco,jandem.

Currently the available AllocKind sizes allow the following numbers of slots in
an object: 0, 2, 4, 8, 12 and 16.  The step from 4 to 8 encompasses many of the
wasm-gc objects we see allocated in JS3 wasm benchmarks.  It would be helpful
to have a 6-slot object, so that objects requiring 5 or 6 slots don't wind up
getting allocated 8 regardless.

The patch is straightforwardly cargo-culted from the ::OBJECT8/::ARRAYBUFFER8
cases.

Differential Revision: https://phabricator.services.mozilla.com/D266785

Diffstat:
Mjs/src/gc/AllocKind.h | 4++++
Mjs/src/gc/Compacting.cpp | 4++++
Mjs/src/gc/GC.cpp | 2+-
Mjs/src/gc/ObjectKind-inl.h | 6+++++-
Mjs/src/gc/Sweeping.cpp | 43+++++++++++++++++--------------------------
Mjs/src/jit-test/tests/heap-analysis/byteSize-of-object.js | 12++++++------
Mjs/src/vm/ArrayBufferObject.cpp | 4++++
Mjs/src/vm/GlobalObject.h | 3+++
Mjs/src/vm/JSObject.h | 4++++
9 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/js/src/gc/AllocKind.h b/js/src/gc/AllocKind.h @@ -72,6 +72,10 @@ namespace gc { D(OBJECT4, Object, JSObject, JSObject_Slots4, None, true, true) \ D(OBJECT4_FOREGROUND, Object, JSObject, JSObject_Slots4, Foreground, true, true) \ D(OBJECT4_BACKGROUND, Object, JSObject, JSObject_Slots4, Background, true, true) \ + D(ARRAYBUFFER6, Object, JSObject, JSObject_Slots6, Background, true, true) \ + D(OBJECT6, Object, JSObject, JSObject_Slots6, None, true, true) \ + D(OBJECT6_FOREGROUND, Object, JSObject, JSObject_Slots6, Foreground, true, true) \ + D(OBJECT6_BACKGROUND, Object, JSObject, JSObject_Slots6, Background, true, true) \ D(ARRAYBUFFER8, Object, JSObject, JSObject_Slots8, Background, true, true) \ D(OBJECT8, Object, JSObject, JSObject_Slots8, None, true, true) \ D(OBJECT8_FOREGROUND, Object, JSObject, JSObject_Slots8, Foreground, true, true) \ diff --git a/js/src/gc/Compacting.cpp b/js/src/gc/Compacting.cpp @@ -752,6 +752,10 @@ static constexpr AllocKinds UpdatePhaseTwo{AllocKind::FUNCTION, AllocKind::OBJECT4, AllocKind::OBJECT4_FOREGROUND, AllocKind::OBJECT4_BACKGROUND, + AllocKind::ARRAYBUFFER6, + AllocKind::OBJECT6, + AllocKind::OBJECT6_FOREGROUND, + AllocKind::OBJECT6_BACKGROUND, AllocKind::ARRAYBUFFER8, AllocKind::OBJECT8, AllocKind::OBJECT8_FOREGROUND, diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp @@ -280,7 +280,7 @@ constexpr uint32_t gc::slotsToAllocKindBytes[] = { // correspond to. // clang-format off /* 0 */ sizeof(JSObject_Slots0), sizeof(JSObject_Slots2), sizeof(JSObject_Slots2), sizeof(JSObject_Slots4), - /* 4 */ sizeof(JSObject_Slots4), sizeof(JSObject_Slots8), sizeof(JSObject_Slots8), sizeof(JSObject_Slots8), + /* 4 */ sizeof(JSObject_Slots4), sizeof(JSObject_Slots6), sizeof(JSObject_Slots6), sizeof(JSObject_Slots8), /* 8 */ sizeof(JSObject_Slots8), sizeof(JSObject_Slots12), sizeof(JSObject_Slots12), sizeof(JSObject_Slots12), /* 12 */ sizeof(JSObject_Slots12), sizeof(JSObject_Slots16), sizeof(JSObject_Slots16), sizeof(JSObject_Slots16), /* 16 */ sizeof(JSObject_Slots16) diff --git a/js/src/gc/ObjectKind-inl.h b/js/src/gc/ObjectKind-inl.h @@ -21,7 +21,7 @@ namespace gc { inline constexpr AllocKind slotsToThingKind[] = { // clang-format off /* 0 */ AllocKind::OBJECT0, AllocKind::OBJECT2, AllocKind::OBJECT2, AllocKind::OBJECT4, - /* 4 */ AllocKind::OBJECT4, AllocKind::OBJECT8, AllocKind::OBJECT8, AllocKind::OBJECT8, + /* 4 */ AllocKind::OBJECT4, AllocKind::OBJECT6, AllocKind::OBJECT6, AllocKind::OBJECT8, /* 8 */ AllocKind::OBJECT8, AllocKind::OBJECT12, AllocKind::OBJECT12, AllocKind::OBJECT12, /* 12 */ AllocKind::OBJECT12, AllocKind::OBJECT16, AllocKind::OBJECT16, AllocKind::OBJECT16, /* 16 */ AllocKind::OBJECT16 @@ -110,6 +110,10 @@ static constexpr size_t GetGCKindSlots(AllocKind thingKind) { case AllocKind::OBJECT4_FOREGROUND: case AllocKind::OBJECT4_BACKGROUND: return 4; + case AllocKind::OBJECT6: + case AllocKind::OBJECT6_FOREGROUND: + case AllocKind::OBJECT6_BACKGROUND: + return 6; case AllocKind::FUNCTION_EXTENDED: return 7; case AllocKind::OBJECT8: diff --git a/js/src/gc/Sweeping.cpp b/js/src/gc/Sweeping.cpp @@ -82,9 +82,10 @@ using JS::SliceBudget; */ static constexpr AllocKinds ForegroundObjectFinalizePhase = { - AllocKind::OBJECT0_FOREGROUND, AllocKind::OBJECT2_FOREGROUND, - AllocKind::OBJECT4_FOREGROUND, AllocKind::OBJECT8_FOREGROUND, - AllocKind::OBJECT12_FOREGROUND, AllocKind::OBJECT16_FOREGROUND}; + AllocKind::OBJECT0_FOREGROUND, AllocKind::OBJECT2_FOREGROUND, + AllocKind::OBJECT4_FOREGROUND, AllocKind::OBJECT6_FOREGROUND, + AllocKind::OBJECT8_FOREGROUND, AllocKind::OBJECT12_FOREGROUND, + AllocKind::OBJECT16_FOREGROUND}; static constexpr AllocKinds ForegroundNonObjectFinalizePhase = { AllocKind::SCRIPT, AllocKind::JITCODE}; @@ -92,34 +93,24 @@ static constexpr AllocKinds ForegroundNonObjectFinalizePhase = { static constexpr AllocKinds BackgroundObjectFinalizePhase = { AllocKind::OBJECT0_BACKGROUND, AllocKind::OBJECT2_BACKGROUND, AllocKind::ARRAYBUFFER4, AllocKind::OBJECT4_BACKGROUND, + AllocKind::ARRAYBUFFER6, AllocKind::OBJECT6_BACKGROUND, AllocKind::ARRAYBUFFER8, AllocKind::OBJECT8_BACKGROUND, AllocKind::ARRAYBUFFER12, AllocKind::OBJECT12_BACKGROUND, AllocKind::ARRAYBUFFER16, AllocKind::OBJECT16_BACKGROUND}; static constexpr AllocKinds BackgroundTrivialFinalizePhase = { - AllocKind::FUNCTION, - AllocKind::FUNCTION_EXTENDED, - AllocKind::OBJECT0, - AllocKind::OBJECT2, - AllocKind::OBJECT4, - AllocKind::OBJECT8, - AllocKind::OBJECT12, - AllocKind::OBJECT16, - AllocKind::SCOPE, - AllocKind::REGEXP_SHARED, - AllocKind::FAT_INLINE_STRING, - AllocKind::STRING, - AllocKind::EXTERNAL_STRING, - AllocKind::FAT_INLINE_ATOM, - AllocKind::ATOM, - AllocKind::SYMBOL, - AllocKind::BIGINT, - AllocKind::SHAPE, - AllocKind::BASE_SHAPE, - AllocKind::GETTER_SETTER, - AllocKind::COMPACT_PROP_MAP, - AllocKind::NORMAL_PROP_MAP, - AllocKind::DICT_PROP_MAP}; + AllocKind::FUNCTION, AllocKind::FUNCTION_EXTENDED, + AllocKind::OBJECT0, AllocKind::OBJECT2, + AllocKind::OBJECT4, AllocKind::OBJECT6, + AllocKind::OBJECT8, AllocKind::OBJECT12, + AllocKind::OBJECT16, AllocKind::SCOPE, + AllocKind::REGEXP_SHARED, AllocKind::FAT_INLINE_STRING, + AllocKind::STRING, AllocKind::EXTERNAL_STRING, + AllocKind::FAT_INLINE_ATOM, AllocKind::ATOM, + AllocKind::SYMBOL, AllocKind::BIGINT, + AllocKind::SHAPE, AllocKind::BASE_SHAPE, + AllocKind::GETTER_SETTER, AllocKind::COMPACT_PROP_MAP, + AllocKind::NORMAL_PROP_MAP, AllocKind::DICT_PROP_MAP}; static constexpr AllocKinds AllBackgroundSweptKinds = BackgroundObjectFinalizePhase + BackgroundTrivialFinalizePhase; 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 @@ -33,7 +33,7 @@ assertEq(tByteSize({ w: 1 }), s(32, 40)); assertEq(tByteSize({ w: 1, x: 2 }), s(32, 40)); assertEq(tByteSize({ w: 1, x: 2, y: 3 }), s(48, 56)); assertEq(tByteSize({ w: 1, x: 2, y: 3, z:4 }), s(48, 56)); -assertEq(tByteSize({ w: 1, x: 2, y: 3, z:4, a: 5 }), s(80, 88)); +assertEq(tByteSize({ w: 1, x: 2, y: 3, z:4, a: 5 }), s(64, 72)); // Try objects with only indexed properties. assertEq(tByteSize({ 0:0 }), s(80, 88)); @@ -50,16 +50,16 @@ assertEq(tByteSize({ w:1, 0:0, 1:1, 2:2, 3:3, 4:4 }), s(96, assertEq(tByteSize({ w:1, x:2, y:3, 0:0 }), s(112, 120)); assertEq(tByteSize({ w:1, x:2, y:3, 0:0, 1:1, 2:2 }), s(112, 120)); assertEq(tByteSize({ w:1, x:2, y:3, 0:0, 1:1, 2:2, 3:3, 4:4 }), s(112, 120)); -assertEq(tByteSize({ w:1, x:2, y:3, z:4, a:6, 0:0 }), s(144, 152)); -assertEq(tByteSize({ w:1, x:2, y:3, z:4, a:6, 0:0, 1:1, 2:2 }), s(144, 152)); -assertEq(tByteSize({ w:1, x:2, y:3, z:4, a:6, 0:0, 1:1, 2:2, 3:3, 4:4 }), s(144, 152)); +assertEq(tByteSize({ w:1, x:2, y:3, z:4, a:6, 0:0 }), s(128, 136)); +assertEq(tByteSize({ w:1, x:2, y:3, z:4, a:6, 0:0, 1:1, 2:2 }), s(128, 136)); +assertEq(tByteSize({ w:1, x:2, y:3, z:4, a:6, 0:0, 1:1, 2:2, 3:3, 4:4 }), s(128, 136)); // Check various lengths of array. assertEq(tByteSize([]), s(80, 88)); assertEq(tByteSize([1]), s(48, 56)); assertEq(tByteSize([1, 2]), s(48, 56)); -assertEq(tByteSize([1, 2, 3]), s(80, 88)); -assertEq(tByteSize([1, 2, 3, 4]), s(80, 88)); +assertEq(tByteSize([1, 2, 3]), s(64, 72)); +assertEq(tByteSize([1, 2, 3, 4]), s(64, 72)); assertEq(tByteSize([1, 2, 3, 4, 5]), s(80, 88)); assertEq(tByteSize([1, 2, 3, 4, 5, 6]), s(80, 88)); assertEq(tByteSize([1, 2, 3, 4, 5, 6, 7]), s(112, 120)); diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp @@ -2176,6 +2176,9 @@ static constexpr js::gc::AllocKind GetArrayBufferGCObjectKind(size_t numSlots) { if (numSlots <= 4) { return js::gc::AllocKind::ARRAYBUFFER4; } + if (numSlots <= 6) { + return js::gc::AllocKind::ARRAYBUFFER6; + } if (numSlots <= 8) { return js::gc::AllocKind::ARRAYBUFFER8; } @@ -2189,6 +2192,7 @@ template <class ArrayBufferType> static ArrayBufferType* NewArrayBufferObject(JSContext* cx, HandleObject proto_, gc::AllocKind allocKind) { MOZ_ASSERT(allocKind == gc::AllocKind::ARRAYBUFFER4 || + allocKind == gc::AllocKind::ARRAYBUFFER6 || allocKind == gc::AllocKind::ARRAYBUFFER8 || allocKind == gc::AllocKind::ARRAYBUFFER12 || allocKind == gc::AllocKind::ARRAYBUFFER16); diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h @@ -69,6 +69,7 @@ enum class PlainObjectSlotsKind { Slots0, Slots2, Slots4, + Slots6, Slots8, Slots12, Slots16, @@ -84,6 +85,8 @@ static PlainObjectSlotsKind PlainObjectSlotsKindFromAllocKind( return PlainObjectSlotsKind::Slots2; case gc::AllocKind::OBJECT4: return PlainObjectSlotsKind::Slots4; + case gc::AllocKind::OBJECT6: + return PlainObjectSlotsKind::Slots6; case gc::AllocKind::OBJECT8: return PlainObjectSlotsKind::Slots8; case gc::AllocKind::OBJECT12: diff --git a/js/src/vm/JSObject.h b/js/src/vm/JSObject.h @@ -732,6 +732,10 @@ struct JSObject_Slots4 : JSObject { void* data[2]; js::Value fslots[4]; }; +struct JSObject_Slots6 : JSObject { + void* data[2]; + js::Value fslots[6]; +}; struct JSObject_Slots7 : JSObject { // Only used for extended functions which are required to have exactly seven // fixed slots due to JIT assumptions.