commit 68d78760c1542142ee7a53016bb3f8d1dbadd38a
parent f32734c044aaf4c436a1cbdd3ab45008fbc4d05e
Author: André Bargull <andre.bargull@gmail.com>
Date: Mon, 20 Oct 2025 12:27:41 +0000
Bug 1991402 - Part 5: Inline natives in super-get accesses. r=jandem
Passing the receiver-value to `InlinableNativeIRGenerator` as the this-value
allows to support inlining through native accessor functions in `GetPropSuper`
and `GetElemSuper` operations.
Drive-by change:
- Change some MutableHandleValue to just HandleValue.
Differential Revision: https://phabricator.services.mozilla.com/D266597
Diffstat:
7 files changed, 59 insertions(+), 26 deletions(-)
diff --git a/js/src/jit-test/tests/cacheir/inlinable-native-accessor-5.js b/js/src/jit-test/tests/cacheir/inlinable-native-accessor-5.js
@@ -0,0 +1,31 @@
+// Test calling an inlinable native accessor through a Get{Prop,Elem}Super operation.
+
+class MySet extends Set {
+ get size() {
+ return super.size;
+ }
+}
+
+function testWithClass() {
+ var sets = [
+ new MySet(),
+ new MySet([1, 2, 3, 4]),
+ ];
+ for (var i = 0; i < 100; ++i) {
+ var set = sets[i & 1];
+ assertEq(set.size, (i & 1) * 4);
+ }
+}
+testWithClass();
+
+function testWithReflect() {
+ var sets = [
+ new Set(),
+ new Set([1, 2, 3, 4]),
+ ];
+ for (var i = 0; i < 100; ++i) {
+ var set = sets[i & 1];
+ assertEq(Reflect.get(Set.prototype, "size", set), (i & 1) * 4);
+ }
+}
+testWithReflect();
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
@@ -718,7 +718,7 @@ bool DoGetElemFallback(JSContext* cx, BaselineFrame* frame,
#endif
TryAttachStub<GetPropIRGenerator>("GetElem", cx, frame, stub,
- CacheKind::GetElem, lhs, rhs);
+ CacheKind::GetElem, lhs, rhs, lhs);
if (!GetElementOperation(cx, lhs, rhs, res)) {
return false;
@@ -752,7 +752,8 @@ bool DoGetElemSuperFallback(JSContext* cx, BaselineFrame* frame,
}
TryAttachStub<GetPropIRGenerator>("GetElemSuper", cx, frame, stub,
- CacheKind::GetElemSuper, lhs, rhs);
+ CacheKind::GetElemSuper, lhs, rhs,
+ receiver);
return GetObjectElementOperation(cx, op, lhsObj, receiver, rhs, res);
}
@@ -1288,7 +1289,7 @@ bool FallbackICCodeCompiler::emit_LazyConstant() {
//
bool DoGetPropFallback(JSContext* cx, BaselineFrame* frame,
- ICFallbackStub* stub, MutableHandleValue val,
+ ICFallbackStub* stub, HandleValue val,
MutableHandleValue res) {
stub->incrementEnteredCount();
MaybeNotifyWarp(frame->outerScript(), stub);
@@ -1304,7 +1305,7 @@ bool DoGetPropFallback(JSContext* cx, BaselineFrame* frame,
RootedValue idVal(cx, StringValue(name));
TryAttachStub<GetPropIRGenerator>("GetProp", cx, frame, stub,
- CacheKind::GetProp, val, idVal);
+ CacheKind::GetProp, val, idVal, val);
if (op == JSOp::GetBoundName) {
RootedObject env(cx, &val.toObject());
@@ -1322,7 +1323,7 @@ bool DoGetPropFallback(JSContext* cx, BaselineFrame* frame,
bool DoGetPropSuperFallback(JSContext* cx, BaselineFrame* frame,
ICFallbackStub* stub, HandleValue receiver,
- MutableHandleValue val, MutableHandleValue res) {
+ HandleValue val, MutableHandleValue res) {
stub->incrementEnteredCount();
MaybeNotifyWarp(frame->outerScript(), stub);
@@ -1346,7 +1347,8 @@ bool DoGetPropSuperFallback(JSContext* cx, BaselineFrame* frame,
}
TryAttachStub<GetPropIRGenerator>("GetPropSuper", cx, frame, stub,
- CacheKind::GetPropSuper, val, idVal);
+ CacheKind::GetPropSuper, val, idVal,
+ receiver);
if (!GetProperty(cx, valObj, receiver, name, res)) {
return false;
@@ -1369,7 +1371,7 @@ bool FallbackICCodeCompiler::emitGetProp(bool hasReceiver) {
masm.pushBaselineFramePtr(FramePointer, R0.scratchReg());
using Fn = bool (*)(JSContext*, BaselineFrame*, ICFallbackStub*,
- HandleValue, MutableHandleValue, MutableHandleValue);
+ HandleValue, HandleValue, MutableHandleValue);
if (!tailCallVM<Fn, DoGetPropSuperFallback>(masm)) {
return false;
}
@@ -1383,7 +1385,7 @@ bool FallbackICCodeCompiler::emitGetProp(bool hasReceiver) {
masm.pushBaselineFramePtr(FramePointer, R0.scratchReg());
using Fn = bool (*)(JSContext*, BaselineFrame*, ICFallbackStub*,
- MutableHandleValue, MutableHandleValue);
+ HandleValue, MutableHandleValue);
if (!tailCallVM<Fn, DoGetPropFallback>(masm)) {
return false;
}
diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h
@@ -391,13 +391,12 @@ extern bool DoLazyConstantFallback(JSContext* cx, BaselineFrame* frame,
MutableHandleValue res);
extern bool DoGetPropFallback(JSContext* cx, BaselineFrame* frame,
- ICFallbackStub* stub, MutableHandleValue val,
+ ICFallbackStub* stub, HandleValue val,
MutableHandleValue res);
extern bool DoGetPropSuperFallback(JSContext* cx, BaselineFrame* frame,
ICFallbackStub* stub, HandleValue receiver,
- MutableHandleValue val,
- MutableHandleValue res);
+ HandleValue val, MutableHandleValue res);
extern bool DoSetPropFallback(JSContext* cx, BaselineFrame* frame,
ICFallbackStub* stub, Value* stack,
diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp
@@ -300,8 +300,12 @@ gc::AllocSite* IRGenerator::maybeCreateAllocSite() {
GetPropIRGenerator::GetPropIRGenerator(JSContext* cx, HandleScript script,
jsbytecode* pc, ICState state,
CacheKind cacheKind, HandleValue val,
- HandleValue idVal)
- : IRGenerator(cx, script, pc, cacheKind, state), val_(val), idVal_(idVal) {}
+ HandleValue idVal,
+ HandleValue receiverVal)
+ : IRGenerator(cx, script, pc, cacheKind, state),
+ val_(val),
+ idVal_(idVal),
+ receiverVal_(receiverVal) {}
static void EmitLoadSlotResult(CacheIRWriter& writer, ObjOperandId holderId,
NativeObject* holder, PropertyInfo prop) {
@@ -2446,15 +2450,10 @@ AttachDecision GetPropIRGenerator::tryAttachInlinableNativeGetter(
NativeObject* holder, PropertyInfo prop, ValOperandId receiverId) {
MOZ_ASSERT(mode_ == ICState::Mode::Specialized);
- // Receiver should be the object.
- if (isSuper()) {
- return AttachDecision::NoAction;
- }
-
Rooted<JSFunction*> target(cx_, &holder->getGetter(prop)->as<JSFunction>());
MOZ_ASSERT(target->isNativeWithoutJitEntry());
- Handle<Value> thisValue = val_;
+ Handle<Value> thisValue = receiverVal_;
bool isSpread = false;
bool isSameRealm = cx_->realm() == target->realm();
diff --git a/js/src/jit/CacheIRGenerator.h b/js/src/jit/CacheIRGenerator.h
@@ -165,6 +165,7 @@ class MOZ_RAII IRGenerator {
class MOZ_RAII GetPropIRGenerator : public IRGenerator {
HandleValue val_;
HandleValue idVal_;
+ HandleValue receiverVal_;
friend class InlinableNativeIRGenerator;
@@ -298,7 +299,7 @@ class MOZ_RAII GetPropIRGenerator : public IRGenerator {
public:
GetPropIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc,
ICState state, CacheKind cacheKind, HandleValue val,
- HandleValue idVal);
+ HandleValue idVal, HandleValue receiverVal);
AttachDecision tryAttachStub();
};
@@ -679,7 +680,7 @@ class MOZ_RAII InlinableNativeIRGenerator {
JSOp op() const { return generator_.jsop(); }
uint32_t stackArgc() const { return stackArgc_; }
- // Inlined native accessor for GetProp or GetElem operations.
+ // Inlined native accessor for GetProp(Super) or GetElem(Super) operations.
bool isAccessorOp() const { return !IsInvokeOp(op()); }
bool isCalleeBoundFunction() const;
@@ -1133,7 +1134,8 @@ inline bool BytecodeCallOpCanHaveInlinableNative(JSOp op) {
// Returns true for bytecode get ops that can use InlinableNativeIRGenerator.
inline bool BytecodeGetOpCanHaveInlinableNative(JSOp op) {
- return op == JSOp::GetProp || op == JSOp::GetElem;
+ return op == JSOp::GetProp || op == JSOp::GetElem ||
+ op == JSOp::GetPropSuper || op == JSOp::GetElemSuper;
}
inline bool BytecodeOpCanHaveAllocSite(JSOp op) {
diff --git a/js/src/jit/IonIC.cpp b/js/src/jit/IonIC.cpp
@@ -174,7 +174,7 @@ bool IonGetPropertyIC::update(JSContext* cx, HandleScript outerScript,
MOZ_ASSERT(!val.isMagic());
TryAttachIonStub<GetPropIRGenerator>(cx, ic, ionScript, ic->kind(), val,
- idVal);
+ idVal, val);
if (ic->kind() == CacheKind::GetProp) {
Rooted<PropertyName*> name(cx, idVal.toString()->asAtom().asPropertyName());
@@ -219,7 +219,7 @@ bool IonGetPropSuperIC::update(JSContext* cx, HandleScript outerScript,
RootedValue val(cx, ObjectValue(*obj));
TryAttachIonStub<GetPropIRGenerator>(cx, ic, ionScript, ic->kind(), val,
- idVal);
+ idVal, receiver);
if (ic->kind() == CacheKind::GetPropSuper) {
Rooted<PropertyName*> name(cx, idVal.toString()->asAtom().asPropertyName());
diff --git a/js/src/vm/PortableBaselineInterpret.cpp b/js/src/vm/PortableBaselineInterpret.cpp
@@ -5601,7 +5601,7 @@ DEFINE_IC(NewObject, 0, {
DEFINE_IC(GetProp, 1, {
IC_LOAD_VAL(value0, 0);
PUSH_FALLBACK_IC_FRAME();
- if (!DoGetPropFallback(cx, ctx.frame, fallback, &value0, &ctx.state.res)) {
+ if (!DoGetPropFallback(cx, ctx.frame, fallback, value0, &ctx.state.res)) {
goto error;
}
});
@@ -5610,7 +5610,7 @@ DEFINE_IC(GetPropSuper, 2, {
IC_LOAD_VAL(value0, 1);
IC_LOAD_VAL(value1, 0);
PUSH_FALLBACK_IC_FRAME();
- if (!DoGetPropSuperFallback(cx, ctx.frame, fallback, value0, &value1,
+ if (!DoGetPropSuperFallback(cx, ctx.frame, fallback, value0, value1,
&ctx.state.res)) {
goto error;
}