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:
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.