commit 663cd21c73e19373278db3c608af71a3d41c92b5
parent 308fa93df32b39923d2541215d3712f5debf3d68
Author: Daniel Minor <dminor@mozilla.com>
Date: Tue, 25 Nov 2025 19:12:07 +0000
Bug 1998177 - Remove now unused CanOptimizeStringProtoSymbolLookup and OptimizeStringPrototypeSymbolsFuse; r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D273894
Diffstat:
13 files changed, 0 insertions(+), 158 deletions(-)
diff --git a/js/src/jit-test/tests/fuses/string-proto-symbols-1.js b/js/src/jit-test/tests/fuses/string-proto-symbols-1.js
@@ -1,20 +0,0 @@
-// Adding certain symbol properties to String.prototype or Object.prototype pops
-// the fuse.
-for (let holder of ["String.prototype", "Object.prototype"]) {
- for (let sym of ["Symbol.match", "Symbol.replace", "Symbol.search", "Symbol.split"]) {
- newGlobal().evaluate(`
- assertEq(getFuseState().OptimizeStringPrototypeSymbolsFuse.intact, true);
- ${holder}[${sym}] = null;
- assertEq(getFuseState().OptimizeStringPrototypeSymbolsFuse.intact, false);
- `);
- }
-}
-
-// Changing String.prototype's proto also pops the fuse. A no-op change is fine.
-newGlobal().evaluate(`
- assertEq(getFuseState().OptimizeStringPrototypeSymbolsFuse.intact, true);
- Object.setPrototypeOf(String.prototype, Object.prototype);
- assertEq(getFuseState().OptimizeStringPrototypeSymbolsFuse.intact, true);
- Object.setPrototypeOf(String.prototype, {});
- assertEq(getFuseState().OptimizeStringPrototypeSymbolsFuse.intact, false);
-`);
diff --git a/js/src/jit-test/tests/fuses/string-proto-symbols-2.js b/js/src/jit-test/tests/fuses/string-proto-symbols-2.js
@@ -1,16 +0,0 @@
-// Test for CanOptimizeStringProtoSymbolLookup intrinsic.
-function test() {
- const CanOptimizeStringProtoSymbolLookup = getSelfHostedValue("CanOptimizeStringProtoSymbolLookup");
- for (var i = 0; i < 55; i++) {
- if (i === 10) {
- String.prototype.foo = "bar";
- Object.prototype.hello = "world";
- }
- if (i === 40) {
- // Pops the fuse.
- Object.prototype[Symbol.replace] = 123;
- }
- assertEq(CanOptimizeStringProtoSymbolLookup(), i < 40);
- }
-}
-test();
diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp
@@ -7560,30 +7560,6 @@ AttachDecision InlinableNativeIRGenerator::tryAttachCanOptimizeArraySpecies() {
return AttachDecision::Attach;
}
-AttachDecision
-InlinableNativeIRGenerator::tryAttachCanOptimizeStringProtoSymbolLookup() {
- // Self-hosted code calls this with no arguments.
- MOZ_ASSERT(args_.length() == 0);
-
- // Initialize the input operand.
- initializeInputOperand();
-
- // Note: we don't need to call emitNativeCalleeGuard for intrinsics.
-
- if (cx_->realm()->realmFuses.optimizeStringPrototypeSymbolsFuse.intact()) {
- writer.guardFuse(RealmFuses::FuseIndex::OptimizeStringPrototypeSymbolsFuse);
- writer.loadBooleanResult(true);
- writer.returnFromIC();
- trackAttached("CanOptimizeStringProtoSymbolLookup.Optimized");
- } else {
- writer.loadBooleanResult(false);
- writer.returnFromIC();
- trackAttached("CanOptimizeStringProtoSymbolLookup.Deoptimized");
- }
-
- return AttachDecision::Attach;
-}
-
AttachDecision InlinableNativeIRGenerator::tryAttachGuardToClass(
InlinableNative native) {
// Self-hosted code calls this with an object argument.
@@ -13247,8 +13223,6 @@ AttachDecision InlinableNativeIRGenerator::tryAttachStub() {
return tryAttachIsCrossRealmArrayConstructor();
case InlinableNative::IntrinsicCanOptimizeArraySpecies:
return tryAttachCanOptimizeArraySpecies();
- case InlinableNative::IntrinsicCanOptimizeStringProtoSymbolLookup:
- return tryAttachCanOptimizeStringProtoSymbolLookup();
case InlinableNative::IntrinsicGuardToArrayIterator:
case InlinableNative::IntrinsicGuardToMapIterator:
case InlinableNative::IntrinsicGuardToSetIterator:
diff --git a/js/src/jit/CacheIRGenerator.h b/js/src/jit/CacheIRGenerator.h
@@ -766,7 +766,6 @@ class MOZ_RAII InlinableNativeIRGenerator {
AttachDecision tryAttachIsConstructor();
AttachDecision tryAttachIsCrossRealmArrayConstructor();
AttachDecision tryAttachCanOptimizeArraySpecies();
- AttachDecision tryAttachCanOptimizeStringProtoSymbolLookup();
AttachDecision tryAttachGuardToClass(InlinableNative native);
AttachDecision tryAttachGuardToClass(GuardClassKind kind);
AttachDecision tryAttachGuardToArrayBuffer();
diff --git a/js/src/jit/CompilationDependencyTracker.h b/js/src/jit/CompilationDependencyTracker.h
@@ -26,7 +26,6 @@ struct CompilationDependency : public TempObject {
ArraySpecies,
TypedArraySpecies,
RegExpPrototype,
- StringPrototypeSymbols,
EmulatesUndefined,
ArrayExceedsInt32Length,
ObjectFuseProperty,
diff --git a/js/src/jit/InlinableNatives.cpp b/js/src/jit/InlinableNatives.cpp
@@ -215,7 +215,6 @@ bool js::jit::CanInlineNativeCrossRealm(InlinableNative native) {
case InlinableNative::IntrinsicIsObject:
case InlinableNative::IntrinsicIsCrossRealmArrayConstructor:
case InlinableNative::IntrinsicCanOptimizeArraySpecies:
- case InlinableNative::IntrinsicCanOptimizeStringProtoSymbolLookup:
case InlinableNative::IntrinsicToInteger:
case InlinableNative::IntrinsicToLength:
case InlinableNative::IntrinsicIsConstructing:
diff --git a/js/src/jit/InlinableNatives.h b/js/src/jit/InlinableNatives.h
@@ -242,7 +242,6 @@
_(IntrinsicIsObject) \
_(IntrinsicIsCrossRealmArrayConstructor) \
_(IntrinsicCanOptimizeArraySpecies) \
- _(IntrinsicCanOptimizeStringProtoSymbolLookup) \
_(IntrinsicToInteger) \
_(IntrinsicToLength) \
_(IntrinsicIsConstructing) \
diff --git a/js/src/jit/WarpCacheIRTranspiler.cpp b/js/src/jit/WarpCacheIRTranspiler.cpp
@@ -482,7 +482,6 @@ bool WarpCacheIRTranspiler::emitGuardFuse(RealmFuses::FuseIndex fuseIndex) {
case RealmFuses::FuseIndex::OptimizeArraySpeciesFuse:
case RealmFuses::FuseIndex::OptimizeTypedArraySpeciesFuse:
case RealmFuses::FuseIndex::OptimizeRegExpPrototypeFuse:
- case RealmFuses::FuseIndex::OptimizeStringPrototypeSymbolsFuse:
// This is a no-op because WarpOracle has added a compilation dependency.
MOZ_ASSERT(RealmFuses::isInvalidatingFuse(fuseIndex));
return true;
diff --git a/js/src/jit/WarpOracle.cpp b/js/src/jit/WarpOracle.cpp
@@ -862,12 +862,6 @@ bool WarpOracle::addFuseDependency(RealmFuses::FuseIndex fuseIndex,
CompilationDependency::Type::RegExpPrototype>;
return addIfStillValid(Dependency());
}
- case RealmFuses::FuseIndex::OptimizeStringPrototypeSymbolsFuse: {
- using Dependency = RealmFuseDependency<
- &RealmFuses::optimizeStringPrototypeSymbolsFuse,
- CompilationDependency::Type::StringPrototypeSymbols>;
- return addIfStillValid(Dependency());
- }
default:
MOZ_ASSERT(!RealmFuses::isInvalidatingFuse(fuseIndex));
*stillValid = true;
diff --git a/js/src/vm/RealmFuses.cpp b/js/src/vm/RealmFuses.cpp
@@ -554,35 +554,6 @@ bool js::OptimizeRegExpPrototypeFuse::checkInvariant(JSContext* cx) {
return true;
}
-bool js::OptimizeStringPrototypeSymbolsFuse::checkInvariant(JSContext* cx) {
- auto* stringProto =
- cx->global()->maybeGetPrototype<NativeObject>(JSProto_String);
- if (!stringProto) {
- // No proto, invariant still holds.
- return true;
- }
-
- // String.prototype must have Object.prototype as proto.
- auto* objectProto = &cx->global()->getObjectPrototype().as<NativeObject>();
- if (stringProto->staticPrototype() != objectProto) {
- return false;
- }
-
- // The objects must not have a @@match, @@replace, @@search, @@split property.
- auto hasSymbolProp = [&](JS::Symbol* symbol) {
- PropertyKey key = PropertyKey::Symbol(symbol);
- return stringProto->containsPure(key) || objectProto->containsPure(key);
- };
- if (hasSymbolProp(cx->wellKnownSymbols().match) ||
- hasSymbolProp(cx->wellKnownSymbols().replace) ||
- hasSymbolProp(cx->wellKnownSymbols().search) ||
- hasSymbolProp(cx->wellKnownSymbols().split)) {
- return false;
- }
-
- return true;
-}
-
bool js::OptimizeMapObjectIteratorFuse::checkInvariant(JSContext* cx) {
// Ensure Map.prototype's @@iterator slot is unchanged.
auto* proto = cx->global()->maybeGetPrototype<NativeObject>(JSProto_Map);
diff --git a/js/src/vm/RealmFuses.h b/js/src/vm/RealmFuses.h
@@ -247,20 +247,6 @@ struct OptimizeRegExpPrototypeFuse final : public InvalidatingRealmFuse {
virtual bool checkInvariant(JSContext* cx) override;
};
-// Fuse used to optimize lookups of certain symbols on String.prototype.
-// If this fuse is intact, the following invariants must hold:
-//
-// - The builtin String.prototype object has the builtin Object.prototype object
-// as prototype.
-// - Both String.prototype and Object.prototype don't have any of the following
-// properties: Symbol.match, Symbol.replace, Symbol.search, Symbol.split.
-struct OptimizeStringPrototypeSymbolsFuse final : public InvalidatingRealmFuse {
- virtual const char* name() override {
- return "OptimizeStringPrototypeSymbolsFuse";
- }
- virtual bool checkInvariant(JSContext* cx) override;
-};
-
// Guard used to optimize iterating over Map objects. If this fuse is intact,
// the following invariants must hold:
//
@@ -345,7 +331,6 @@ struct OptimizeWeakSetPrototypeAddFuse final : public RealmFuse {
FUSE(OptimizeTypedArraySpeciesFuse, optimizeTypedArraySpeciesFuse) \
FUSE(OptimizePromiseLookupFuse, optimizePromiseLookupFuse) \
FUSE(OptimizeRegExpPrototypeFuse, optimizeRegExpPrototypeFuse) \
- FUSE(OptimizeStringPrototypeSymbolsFuse, optimizeStringPrototypeSymbolsFuse) \
FUSE(OptimizeMapObjectIteratorFuse, optimizeMapObjectIteratorFuse) \
FUSE(OptimizeSetObjectIteratorFuse, optimizeSetObjectIteratorFuse) \
FUSE(OptimizeMapPrototypeSetFuse, optimizeMapPrototypeSetFuse) \
diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp
@@ -310,18 +310,6 @@ static bool intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
-static bool intrinsic_CanOptimizeStringProtoSymbolLookup(JSContext* cx,
- unsigned argc,
- Value* vp) {
- CallArgs args = CallArgsFromVp(argc, vp);
- MOZ_ASSERT(args.length() == 0);
-
- bool optimizable =
- cx->realm()->realmFuses.optimizeStringPrototypeSymbolsFuse.intact();
- args.rval().setBoolean(optimizable);
- return true;
-}
-
static void ThrowErrorWithType(JSContext* cx, JSExnType type,
const CallArgs& args) {
MOZ_RELEASE_ASSERT(args[0].isInt32());
@@ -1628,9 +1616,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_INLINABLE_FN("CanOptimizeArraySpecies",
intrinsic_CanOptimizeArraySpecies, 1, 0,
IntrinsicCanOptimizeArraySpecies),
- JS_INLINABLE_FN("CanOptimizeStringProtoSymbolLookup",
- intrinsic_CanOptimizeStringProtoSymbolLookup, 0, 0,
- IntrinsicCanOptimizeStringProtoSymbolLookup),
JS_FN("ConstructFunction", intrinsic_ConstructFunction, 2, 0),
JS_FN("ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1, 0),
JS_FN("CopyDataPropertiesOrGetOwnKeys",
diff --git a/js/src/vm/Watchtower.cpp b/js/src/vm/Watchtower.cpp
@@ -147,25 +147,6 @@ void MaybePopReturnFuses(JSContext* cx, Handle<NativeObject*> nobj) {
}
}
-static void MaybePopStringPrototypeSymbolsFuse(JSContext* cx, NativeObject* obj,
- PropertyKey key) {
- if (!key.isSymbol()) {
- return;
- }
- GlobalObject* global = &obj->global();
- if (obj != global->maybeGetPrototype(JSProto_String) &&
- obj != global->maybeGetPrototype(JSProto_Object)) {
- return;
- }
- if (key.toSymbol() == cx->wellKnownSymbols().match ||
- key.toSymbol() == cx->wellKnownSymbols().replace ||
- key.toSymbol() == cx->wellKnownSymbols().search ||
- key.toSymbol() == cx->wellKnownSymbols().split) {
- obj->realm()->realmFuses.optimizeStringPrototypeSymbolsFuse.popFuse(
- cx, obj->realm()->realmFuses);
- }
-}
-
// static
bool Watchtower::watchPropertyAddSlow(JSContext* cx, Handle<NativeObject*> obj,
HandleId id) {
@@ -182,8 +163,6 @@ bool Watchtower::watchPropertyAddSlow(JSContext* cx, Handle<NativeObject*> obj,
if (id == NameToId(cx->names().return_)) {
MaybePopReturnFuses(cx, obj);
}
-
- MaybePopStringPrototypeSymbolsFuse(cx, obj, id);
}
if (MOZ_UNLIKELY(obj->useWatchtowerTestingLog())) {
@@ -300,11 +279,6 @@ static bool WatchProtoChangeImpl(JSContext* cx, HandleObject obj) {
cx, nobj->realm()->realmFuses);
}
- if (nobj == nobj->global().maybeGetPrototype(JSProto_String)) {
- nobj->realm()->realmFuses.optimizeStringPrototypeSymbolsFuse.popFuse(
- cx, nobj->realm()->realmFuses);
- }
-
auto protoKey = StandardProtoKeyOrNull(nobj);
if (IsTypedArrayProtoKey(protoKey) &&
nobj == nobj->global().maybeGetPrototype(protoKey)) {