Compare commits

..
Author SHA1 Message Date
Moonchild d654ede2c8 Trace strong edges if WeakRef stub preffed. 2026-11-05 06:59:58 +01:00
8 changed files with 100 additions and 40 deletions

No files matched your search

+1
View File
@@ -301,6 +301,7 @@ LoadContextOptions(const char* aPrefName, void* /* aClosure */)
.setAsyncStack(GetWorkerPref<bool>(NS_LITERAL_CSTRING("asyncstack")))
.setWerror(GetWorkerPref<bool>(NS_LITERAL_CSTRING("werror")))
.setStreams(GetWorkerPref<bool>(NS_LITERAL_CSTRING("streams")))
.setWeakRefs(GetWorkerPref<bool>(NS_LITERAL_CSTRING("weakrefs")))
.setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict")))
.setArrayProtoValues(GetWorkerPref<bool>(
NS_LITERAL_CSTRING("array_prototype_values")));
+1
View File
@@ -35,6 +35,7 @@ WORKER_SIMPLE_PREF("dom.serviceWorkers.openWindow.enabled", OpenWindowEnabled, O
WORKER_SIMPLE_PREF("dom.storageManager.enabled", StorageManagerEnabled, STORAGEMANAGER_ENABLED)
WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED)
WORKER_SIMPLE_PREF("dom.streams.enabled", StreamsEnabled, STREAMS_ENABLED)
WORKER_SIMPLE_PREF("javascript.options.weakrefs", WeakRefsEnabled, WEAKREFS_ENABLED)
WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED)
WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED)
WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK)
+57 -24
View File
@@ -66,10 +66,28 @@ struct WeakCell {
WeakCellKind kind;
WeakRef<JSObject*> object;
WeakRef<JS::Symbol*> symbol;
bool enabled;
WeakCell() : kind(WeakCellKind::Empty), object(nullptr), symbol(nullptr) {}
explicit WeakCell(JSObject* obj) : kind(WeakCellKind::Object), object(obj), symbol(nullptr) {}
explicit WeakCell(JS::Symbol* sym) : kind(WeakCellKind::Symbol), object(nullptr), symbol(sym) {}
WeakCell()
: kind(WeakCellKind::Empty)
, object(nullptr)
, symbol(nullptr)
, enabled(true)
{}
explicit WeakCell(JSObject* obj, bool enabled)
: kind(WeakCellKind::Object)
, object(obj)
, symbol(nullptr)
, enabled(enabled)
{}
explicit WeakCell(JS::Symbol* sym, bool enabled)
: kind(WeakCellKind::Symbol)
, object(nullptr)
, symbol(sym)
, enabled(enabled)
{}
void clear() {
kind = WeakCellKind::Empty;
@@ -101,7 +119,9 @@ struct WeakCell {
if (!target)
return;
if (IsInsideNursery(target)) {
if (!enabled || IsInsideNursery(target)) {
// Weak edges must be tenured.
// Trace strongly if inside nursery or WeakRef disabled.
TraceManuallyBarrieredEdge(trc, object.unsafeGet(), name);
} else {
if (trc->isMarkingTracer() && !target->asTenured().zone()->isCollecting())
@@ -111,9 +131,14 @@ struct WeakCell {
} else if (kind == WeakCellKind::Symbol) {
JS::Symbol* target = symbol.unbarrieredGet();
if (target) {
if (trc->isMarkingTracer() && !target->asTenured().zone()->isCollecting())
return;
TraceWeakEdge(trc, &symbol, name);
if (!enabled) {
// Trace strongly if WeakRef disabled.
TraceManuallyBarrieredEdge(trc, symbol.unsafeGet(), name);
} else {
if (trc->isMarkingTracer() && !target->asTenured().zone()->isCollecting())
return;
TraceWeakEdge(trc, &symbol, name);
}
}
}
}
@@ -124,14 +149,16 @@ struct WeakCell {
if (!target)
return;
if (IsInsideNursery(target)) {
if (!enabled) {
// Do nothing
} else if (IsInsideNursery(target)) {
TraceManuallyBarrieredEdge(trc, object.unsafeGet(), name);
} else if (target->asTenured().zone()->isCollecting()) {
TraceWeakEdge(trc, &object, name);
}
} else if (kind == WeakCellKind::Symbol) {
JS::Symbol* target = symbol.unbarrieredGet();
if (target && target->asTenured().zone()->isCollecting())
if (enabled && target && target->asTenured().zone()->isCollecting())
TraceWeakEdge(trc, &symbol, name);
}
}
@@ -143,22 +170,24 @@ struct FinalizationRecord {
WeakCell unregisterToken;
bool active;
bool queued;
bool enabled;
FinalizationRecord(HandleValue targetValue, HandleValue heldValue,
HandleValue unregisterTokenValue)
HandleValue unregisterTokenValue, bool enabled)
: heldValue(heldValue),
active(true),
queued(false)
queued(false),
enabled(enabled)
{
if (targetValue.isObject())
target = WeakCell(NormalizeWeakObject(&targetValue.toObject()));
target = WeakCell(NormalizeWeakObject(&targetValue.toObject()), enabled);
else
target = WeakCell(targetValue.toSymbol());
target = WeakCell(targetValue.toSymbol(), enabled);
if (unregisterTokenValue.isObject())
unregisterToken = WeakCell(NormalizeWeakObject(&unregisterTokenValue.toObject()));
unregisterToken = WeakCell(NormalizeWeakObject(&unregisterTokenValue.toObject()), enabled);
else if (unregisterTokenValue.isSymbol())
unregisterToken = WeakCell(unregisterTokenValue.toSymbol());
unregisterToken = WeakCell(unregisterTokenValue.toSymbol(), enabled);
}
void trace(JSTracer* trc) {
@@ -217,13 +246,15 @@ struct FinalizationRegistryObject::Data {
FinalizationRecordVector records;
FinalizationRecordVector cleanupQueue;
bool queuedForCleanup;
bool enabled;
explicit Data(JSObject* cleanupCallback)
explicit Data(JSObject* cleanupCallback, bool enabled)
: cleanupCallback(cleanupCallback),
cleanupJob(nullptr),
records(SystemAllocPolicy()),
cleanupQueue(SystemAllocPolicy()),
queuedForCleanup(false)
queuedForCleanup(false),
enabled(enabled)
{}
~Data() {
@@ -232,11 +263,13 @@ struct FinalizationRegistryObject::Data {
}
void trace(JSTracer* trc) {
JS::TraceEdge(trc, &cleanupCallback, "FinalizationRegistry cleanup callback");
if (cleanupJob.unbarrieredGet())
JS::TraceEdge(trc, &cleanupJob, "FinalizationRegistry cleanup job");
for (size_t i = 0; i < records.length(); i++)
records[i]->trace(trc);
if (enabled) {
JS::TraceEdge(trc, &cleanupCallback, "FinalizationRegistry cleanup callback");
if (cleanupJob.unbarrieredGet())
JS::TraceEdge(trc, &cleanupJob, "FinalizationRegistry cleanup job");
for (size_t i = 0; i < records.length(); i++)
records[i]->trace(trc);
}
}
bool appendRecord(FinalizationRecord* record) {
@@ -317,7 +350,7 @@ FinalizationRegistry_register_impl(JSContext* cx, const CallArgs& args)
unregisterToken.setUndefined();
}
FinalizationRecord* record = cx->new_<FinalizationRecord>(target, heldValue, unregisterToken);
FinalizationRecord* record = cx->new_<FinalizationRecord>(target, heldValue, unregisterToken, cx->options().weakRefs());
if (!record)
return false;
@@ -401,7 +434,7 @@ FinalizationRegistryObject::create(JSContext* cx, HandleObject cleanupCallback,
if (!obj)
return nullptr;
Data* data = cx->new_<Data>(cleanupCallback);
Data* data = cx->new_<Data>(cleanupCallback, cx->options().weakRefs());
if (!data)
return nullptr;
+14 -7
View File
@@ -146,9 +146,9 @@ WeakRefObject::create(JSContext* cx, HandleValue target, HandleObject proto /* =
Referent* data;
if (target.isObject())
data = cx->new_<Referent>(&target.toObject());
data = cx->new_<Referent>(&target.toObject(), cx->options().weakRefs());
else
data = cx->new_<Referent>(target.toSymbol());
data = cx->new_<Referent>(target.toSymbol(), cx->options().weakRefs());
if (!data)
return nullptr;
@@ -216,18 +216,25 @@ WeakRefObject::trace(JSTracer* trc, JSObject* obj)
if (!target)
return;
if (IsInsideNursery(target)) {
// Weak edges must be tenured; trace strongly while referent is in the nursery.
if (!data->enabled || IsInsideNursery(target)) {
// Weak edges must be tenured; trace strongly while referent is in
// the nursery or if WeakRefs are disabled by pref.
TraceManuallyBarrieredEdge(trc, data->objectTarget.unsafeGet(),
"WeakRef nursery referent");
"WeakRef strong referent");
} else {
TraceWeakEdge(trc, &data->objectTarget, "WeakRef referent");
}
} else {
MOZ_ASSERT(data->isSymbol());
JS::Symbol* target = data->symbolTarget.unbarrieredGet();
if (target)
TraceWeakEdge(trc, &data->symbolTarget, "WeakRef symbol referent");
if (target) {
if (data->enabled) {
TraceWeakEdge(trc, &data->symbolTarget, "WeakRef symbol referent");
} else {
TraceManuallyBarrieredEdge(trc, data->symbolTarget.unsafeGet(),
"WeakRef strong symbol referent");
}
}
}
}
}
+15 -5
View File
@@ -22,17 +22,27 @@ class WeakRefObject : public NativeObject
Symbol
};
explicit Referent(JSObject* obj)
: kind(Kind::Object), objectTarget(obj), symbolTarget(nullptr) {}
explicit Referent(JS::Symbol* sym)
: kind(Kind::Symbol), objectTarget(nullptr), symbolTarget(sym) {}
explicit Referent(JSObject* obj, bool enabled)
: kind(Kind::Object)
, objectTarget(obj)
, symbolTarget(nullptr)
, enabled(enabled)
{}
explicit Referent(JS::Symbol* sym, bool enabled)
: kind(Kind::Symbol)
, objectTarget(nullptr)
, symbolTarget(sym)
, enabled(enabled)
{}
bool isObject() const { return kind == Kind::Object; }
bool isSymbol() const { return kind == Kind::Symbol; }
Kind kind;
WeakRef<JSObject*> objectTarget;
WeakRef<JS::Symbol*> symbolTarget;
bool enabled;
};
static const Class class_;
+6 -3
View File
@@ -999,7 +999,8 @@ class JS_PUBLIC_API(ContextOptions) {
strictMode_(false),
extraWarnings_(false),
arrayProtoValues_(true),
streams_(false)
streams_(false),
weakRefs_(false)
{
}
@@ -1139,12 +1140,13 @@ class JS_PUBLIC_API(ContextOptions) {
return *this;
}
bool weakRefs() const { return true; }
bool weakRefs() const { return weakRefs_; }
ContextOptions& setWeakRefs(bool flag) {
(void) flag;
weakRefs_ = flag;
return *this;
}
ContextOptions& toggleWeakRefs() {
weakRefs_ = !weakRefs_;
return *this;
}
@@ -1165,6 +1167,7 @@ class JS_PUBLIC_API(ContextOptions) {
bool extraWarnings_ : 1;
bool arrayProtoValues_ : 1;
bool streams_ : 1;
bool weakRefs_ : 1;
};
JS_PUBLIC_API(ContextOptions&)
+3 -1
View File
@@ -1442,6 +1442,7 @@ ReloadPrefsCallback(const char* pref, void* data)
bool extraWarnings = Preferences::GetBool(JS_OPTIONS_DOT_STR "strict");
bool streams = Preferences::GetBool(JS_OPTIONS_DOT_STR "streams");
bool weakRefs = Preferences::GetBool(JS_OPTIONS_DOT_STR "weakrefs");
bool unboxedObjects = Preferences::GetBool(JS_OPTIONS_DOT_STR "unboxed_objects");
@@ -1468,7 +1469,8 @@ ReloadPrefsCallback(const char* pref, void* data)
.setWerror(werror)
.setExtraWarnings(extraWarnings)
.setArrayProtoValues(arrayProtoValues)
.setStreams(streams);
.setStreams(streams)
.setWeakRefs(weakRefs);
JS_SetParallelParsingEnabled(cx, parallelParsing);
JS_SetOffthreadIonCompilationEnabled(cx, offthreadIonCompilation);
+3
View File
@@ -1314,6 +1314,9 @@ pref("javascript.options.dynamicImport", true);
// Streams API
pref("javascript.options.streams", true);
// WeakRefs API
pref("javascript.options.weakrefs", true);
// advanced prefs
pref("advanced.mailftp", false);
pref("image.animation_mode", "normal");