From a67ae5c63bf5edb966d2c1386b36b06240020c91 Mon Sep 17 00:00:00 2001 From: win7-7 Date: Sat, 10 Jan 2026 23:49:14 +0200 Subject: [PATCH] 1328948 + 1421152 + 903519 forgotten part. 1328948 - add is(), as() to Cell. 903519 - Strings in the nursery: JIT, HeapAPI.h was forgotten. 1421152 - Add a checked cast method to TenuredCell. --- js/src/gc/Allocator.cpp | 14 +++++ js/src/gc/Marking.cpp | 127 ++++++++++++++++++++++++++++++++++++++++ js/src/jit/MIRGraph.cpp | 2 +- js/src/vm/Debugger.cpp | 14 ++--- 4 files changed, 149 insertions(+), 8 deletions(-) diff --git a/js/src/gc/Allocator.cpp b/js/src/gc/Allocator.cpp index 5dc8caeea6..4ebeb7fe72 100644 --- a/js/src/gc/Allocator.cpp +++ b/js/src/gc/Allocator.cpp @@ -6,6 +6,7 @@ #include "gc/Allocator.h" + #include "jscntxt.h" #include "gc/GCInternals.h" @@ -209,6 +210,19 @@ js::Allocate(ExclusiveContext* cx) AllocKind kind = MapTypeToFinalizeKind::kind; size_t thingSize = sizeof(T); + + // === ADD DETAILED DIAGNOSTIC OUTPUT HERE === + size_t arenaSize = Arena::thingSize(kind); + + fprintf(stderr, "\n=== GC Allocation Debug ===\n"); + fprintf(stderr, "Type name: %s\n", typeid(T).name()); + fprintf(stderr, "sizeof(T): %zu bytes\n", thingSize); + fprintf(stderr, "Arena::thingSize(kind): %zu bytes\n", arenaSize); + fprintf(stderr, "CellAlignBytes: %zu bytes\n", CellAlignBytes); + fprintf(stderr, "Match: %s\n", (thingSize == arenaSize) ? "YES" : "NO - MISMATCH!"); + fprintf(stderr, "Size difference: %zd bytes\n", (size_t)thingSize - (size_t)arenaSize); + fprintf(stderr, "========================\n\n"); + MOZ_ASSERT(thingSize == Arena::thingSize(kind)); if (cx->isJSContext()) { diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index aa6d508682..9a602e3be9 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -1956,6 +1956,133 @@ GCMarker::restoreValueArray(JSObject* objArg, void** vpp, void** endp) /*** Mark Stack ***********************************************************************************/ +static_assert(sizeof(MarkStack::TaggedPtr) == sizeof(uintptr_t), + "A TaggedPtr should be the same size as a pointer"); +static_assert(sizeof(MarkStack::ValueArray) == sizeof(MarkStack::SavedValueArray), + "ValueArray and SavedValueArray should be the same size"); +static_assert((sizeof(MarkStack::ValueArray) % sizeof(uintptr_t)) == 0, + "ValueArray and SavedValueArray should be multiples of the pointer size"); + +static const size_t ValueArrayWords = sizeof(MarkStack::ValueArray) / sizeof(uintptr_t); + +template +struct MapTypeToMarkStackTag {}; +template <> +struct MapTypeToMarkStackTag { static const auto value = MarkStack::ObjectTag; }; +template <> +struct MapTypeToMarkStackTag { static const auto value = MarkStack::GroupTag; }; +template <> +struct MapTypeToMarkStackTag { static const auto value = MarkStack::JitCodeTag; }; +template <> +struct MapTypeToMarkStackTag { static const auto value = MarkStack::ScriptTag; }; + +static inline bool +TagIsArrayTag(MarkStack::Tag tag) +{ + return tag == MarkStack::ValueArrayTag || tag == MarkStack::SavedValueArrayTag; +} + +static inline void +CheckValueArray(const MarkStack::ValueArray& array) +{ + MOZ_ASSERT(array.ptr.tag() == MarkStack::ValueArrayTag); + MOZ_ASSERT(uintptr_t(array.start) <= uintptr_t(array.end)); + MOZ_ASSERT((uintptr_t(array.end) - uintptr_t(array.start)) % sizeof(Value) == 0); +} + +static inline void +CheckSavedValueArray(const MarkStack::SavedValueArray& array) +{ + MOZ_ASSERT(array.ptr.tag() == MarkStack::SavedValueArrayTag); + MOZ_ASSERT(array.kind == HeapSlot::Slot || array.kind == HeapSlot::Element); +} + +inline +MarkStack::TaggedPtr::TaggedPtr(Tag tag, Cell* ptr) + : bits(tag | uintptr_t(ptr)) +{ + MOZ_ASSERT(tag <= LastTag); + MOZ_ASSERT((uintptr_t(ptr) & CellAlignMask) == 0); +} + +inline MarkStack::Tag +MarkStack::TaggedPtr::tag() const +{ + auto tag = Tag(bits & TagMask); + MOZ_ASSERT(tag <= LastTag); + return tag; +} + +inline Cell* +MarkStack::TaggedPtr::ptr() const +{ + return reinterpret_cast(bits & ~TagMask); +} + +template +inline T* +MarkStack::TaggedPtr::as() const +{ + MOZ_ASSERT(tag() == MapTypeToMarkStackTag::value); + MOZ_ASSERT(ptr()->isTenured()); + MOZ_ASSERT(ptr()->is()); + return static_cast(ptr()); +} + +inline JSObject* +MarkStack::TaggedPtr::asValueArrayObject() const +{ + MOZ_ASSERT(tag() == ValueArrayTag); + MOZ_ASSERT(ptr()->isTenured()); + MOZ_ASSERT(ptr()->is()); + return static_cast(ptr()); +} + +inline JSObject* +MarkStack::TaggedPtr::asSavedValueArrayObject() const +{ + MOZ_ASSERT(tag() == SavedValueArrayTag); + MOZ_ASSERT(ptr()->isTenured()); + MOZ_ASSERT(ptr()->is()); + return static_cast(ptr()); +} + +inline JSRope* +MarkStack::TaggedPtr::asTempRope() const +{ + MOZ_ASSERT(tag() == TempRopeTag); + MOZ_ASSERT(ptr()->isTenured()); + MOZ_ASSERT(ptr()->is()); + return static_cast(ptr()); +} + +inline +MarkStack::ValueArray::ValueArray(JSObject* obj, HeapSlot* startArg, HeapSlot* endArg) + : end(endArg), start(startArg), ptr(ValueArrayTag, obj) +{} + +inline +MarkStack::SavedValueArray::SavedValueArray(JSObject* obj, size_t indexArg, HeapSlot::Kind kindArg) + : kind(kindArg), index(indexArg), ptr(SavedValueArrayTag, obj) +{} + +MarkStack::MarkStack(size_t maxCapacity) + : stack_(nullptr) + , tos_(nullptr) + , end_(nullptr) + , baseCapacity_(0) + , maxCapacity_(maxCapacity) +#ifdef DEBUG + , iteratorCount_(0) +#endif +{} + +MarkStack::~MarkStack() +{ + MOZ_ASSERT(iteratorCount_ == 0); + js_free(stack_); +} + bool MarkStack::init(JSGCMode gcMode) { diff --git a/js/src/jit/MIRGraph.cpp b/js/src/jit/MIRGraph.cpp index c0fad8325d..1b6e412930 100644 --- a/js/src/jit/MIRGraph.cpp +++ b/js/src/jit/MIRGraph.cpp @@ -37,7 +37,7 @@ MIRGenerator::MIRGenerator(CompileCompartment* compartment, const JitCompileOpti instrumentedProfiling_(false), instrumentedProfilingIsCached_(false), safeForMinorGC_(true), - stringsCanBeInNursery_(compartment ? compartment->zone()->canNurseryAllocateStrings() : false), + stringsCanBeInNursery_(compartment ? GetJitContext()->compartment->zone()->canNurseryAllocateStrings() : false), minWasmHeapLength_(0), options(options), gs_(alloc) diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index dd5e02eb81..578726f997 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -5311,10 +5311,10 @@ static inline DebuggerScriptReferent GetScriptReferent(JSObject* obj) { MOZ_ASSERT(obj->getClass() == &DebuggerScript_class); - if (gc::Cell* cell = GetScriptReferentCell(obj)) { - if (cell->getTraceKind() == JS::TraceKind::Script) - return AsVariant(static_cast(cell)); - MOZ_ASSERT(cell->getTraceKind() == JS::TraceKind::Object); + if (gc::Cell* cell = GetScriptReferentCell(obj)) { + if (cell->is()) + return AsVariant(cell->as()); + MOZ_ASSERT(cell->is()); return AsVariant(&static_cast(cell)->as()); } return AsVariant(static_cast(nullptr)); @@ -5326,13 +5326,13 @@ DebuggerScript_trace(JSTracer* trc, JSObject* obj) /* This comes from a private pointer, so no barrier needed. */ gc::Cell* cell = GetScriptReferentCell(obj); if (cell) { - if (cell->getTraceKind() == JS::TraceKind::Script) { - JSScript* script = static_cast(cell); + if (cell->is()) { + JSScript* script = cell->as(); TraceManuallyBarrieredCrossCompartmentEdge(trc, obj, &script, "Debugger.Script script referent"); obj->as().setPrivateUnbarriered(script); } else { - JSObject* wasm = static_cast(cell); + JSObject* wasm = cell->as(); TraceManuallyBarrieredCrossCompartmentEdge(trc, obj, &wasm, "Debugger.Script wasm referent"); MOZ_ASSERT(wasm->is());