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.
This commit is contained in:
win7-7 2026-01-10 23:49:14 +02:00 committed by wuggy
commit a67ae5c63b
4 changed files with 149 additions and 8 deletions

View file

@ -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<T>::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()) {

View file

@ -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 <typename T>
struct MapTypeToMarkStackTag {};
template <>
struct MapTypeToMarkStackTag<JSObject*> { static const auto value = MarkStack::ObjectTag; };
template <>
struct MapTypeToMarkStackTag<ObjectGroup*> { static const auto value = MarkStack::GroupTag; };
template <>
struct MapTypeToMarkStackTag<jit::JitCode*> { static const auto value = MarkStack::JitCodeTag; };
template <>
struct MapTypeToMarkStackTag<JSScript*> { 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<Cell*>(bits & ~TagMask);
}
template <typename T>
inline T*
MarkStack::TaggedPtr::as() const
{
MOZ_ASSERT(tag() == MapTypeToMarkStackTag<T*>::value);
MOZ_ASSERT(ptr()->isTenured());
MOZ_ASSERT(ptr()->is<T>());
return static_cast<T*>(ptr());
}
inline JSObject*
MarkStack::TaggedPtr::asValueArrayObject() const
{
MOZ_ASSERT(tag() == ValueArrayTag);
MOZ_ASSERT(ptr()->isTenured());
MOZ_ASSERT(ptr()->is<JSObject>());
return static_cast<JSObject*>(ptr());
}
inline JSObject*
MarkStack::TaggedPtr::asSavedValueArrayObject() const
{
MOZ_ASSERT(tag() == SavedValueArrayTag);
MOZ_ASSERT(ptr()->isTenured());
MOZ_ASSERT(ptr()->is<JSObject>());
return static_cast<JSObject*>(ptr());
}
inline JSRope*
MarkStack::TaggedPtr::asTempRope() const
{
MOZ_ASSERT(tag() == TempRopeTag);
MOZ_ASSERT(ptr()->isTenured());
MOZ_ASSERT(ptr()->is<JSString>());
return static_cast<JSRope*>(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)
{

View file

@ -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)

View file

@ -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<JSScript*>(cell));
MOZ_ASSERT(cell->getTraceKind() == JS::TraceKind::Object);
if (gc::Cell* cell = GetScriptReferentCell(obj)) {
if (cell->is<JSScript>())
return AsVariant(cell->as<JSScript>());
MOZ_ASSERT(cell->is<JSObject>());
return AsVariant(&static_cast<NativeObject*>(cell)->as<WasmInstanceObject>());
}
return AsVariant(static_cast<JSScript*>(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<JSScript*>(cell);
if (cell->is<JSScript>()) {
JSScript* script = cell->as<JSScript>();
TraceManuallyBarrieredCrossCompartmentEdge(trc, obj, &script,
"Debugger.Script script referent");
obj->as<NativeObject>().setPrivateUnbarriered(script);
} else {
JSObject* wasm = static_cast<JSObject*>(cell);
JSObject* wasm = cell->as<JSObject>();
TraceManuallyBarrieredCrossCompartmentEdge(trc, obj, &wasm,
"Debugger.Script wasm referent");
MOZ_ASSERT(wasm->is<WasmInstanceObject>());