Skip to content

Commit f4f5b7d

Browse files
committed
Bug 1703469: Use operand for callee in scripted getters r=jandem
This should generate roughly the same code as before. The one exception is in the Ion CacheIR compiler, where we no longer have direct access to the callee, so if it's a cross-realm getter, we have to load the correct realm out of the callee using switchToObjectRealm (instead of baking it in with switchToRealm). It didn't seem worth adding an entire extra operand to make that particular case a bit faster. (The same comment applies to the next patch, which does the same as this one, but for setters.) Differential Revision: https://phabricator.services.mozilla.com/D251753
1 parent cd8148d commit f4f5b7d

File tree

8 files changed

+78
-59
lines changed

8 files changed

+78
-59
lines changed

js/src/jit/BaselineCacheIRCompiler.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -544,19 +544,17 @@ bool BaselineCacheIRCompiler::emitLoadDynamicSlotResult(ObjOperandId objId,
544544
}
545545

546546
bool BaselineCacheIRCompiler::emitCallScriptedGetterShared(
547-
ValOperandId receiverId, uint32_t getterOffset, bool sameRealm,
547+
ValOperandId receiverId, ObjOperandId calleeId, bool sameRealm,
548548
uint32_t nargsAndFlagsOffset, Maybe<uint32_t> icScriptOffset) {
549549
ValueOperand receiver = allocator.useValueRegister(masm, receiverId);
550-
Address getterAddr(stubAddress(getterOffset));
550+
Register callee = allocator.useRegister(masm, calleeId);
551551

552552
AutoScratchRegister code(allocator, masm);
553-
AutoScratchRegister callee(allocator, masm);
554553
AutoScratchRegister scratch(allocator, masm);
555554

556555
bool isInlined = icScriptOffset.isSome();
557556

558557
// First, retrieve raw jitcode for getter.
559-
masm.loadPtr(getterAddr, callee);
560558
if (isInlined) {
561559
FailurePath* failure;
562560
if (!addFailurePath(&failure)) {
@@ -621,19 +619,19 @@ bool BaselineCacheIRCompiler::emitCallScriptedGetterShared(
621619
}
622620

623621
bool BaselineCacheIRCompiler::emitCallScriptedGetterResult(
624-
ValOperandId receiverId, uint32_t getterOffset, bool sameRealm,
622+
ValOperandId receiverId, ObjOperandId calleeId, bool sameRealm,
625623
uint32_t nargsAndFlagsOffset) {
626624
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
627625
Maybe<uint32_t> icScriptOffset = mozilla::Nothing();
628-
return emitCallScriptedGetterShared(receiverId, getterOffset, sameRealm,
626+
return emitCallScriptedGetterShared(receiverId, calleeId, sameRealm,
629627
nargsAndFlagsOffset, icScriptOffset);
630628
}
631629

632630
bool BaselineCacheIRCompiler::emitCallInlinedGetterResult(
633-
ValOperandId receiverId, uint32_t getterOffset, uint32_t icScriptOffset,
631+
ValOperandId receiverId, ObjOperandId calleeId, uint32_t icScriptOffset,
634632
bool sameRealm, uint32_t nargsAndFlagsOffset) {
635633
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
636-
return emitCallScriptedGetterShared(receiverId, getterOffset, sameRealm,
634+
return emitCallScriptedGetterShared(receiverId, calleeId, sameRealm,
637635
nargsAndFlagsOffset,
638636
mozilla::Some(icScriptOffset));
639637
}

js/src/jit/BaselineCacheIRCompiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler {
118118
void emitAtomizeString(Register str, Register temp, Label* failure);
119119

120120
bool emitCallScriptedGetterShared(ValOperandId receiverId,
121-
uint32_t getterOffset, bool sameRealm,
121+
ObjOperandId calleeId, bool sameRealm,
122122
uint32_t nargsAndFlagsOffset,
123123
mozilla::Maybe<uint32_t> icScriptOffset);
124124
bool emitCallScriptedSetterShared(ObjOperandId receiverId,

js/src/jit/CacheIROps.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,7 +2550,7 @@
25502550
custom_writer: true
25512551
args:
25522552
receiver: ValId
2553-
getter: ObjectField
2553+
callee: ObjId
25542554
sameRealm: BoolImm
25552555
nargsAndFlags: RawInt32Field
25562556

@@ -2561,7 +2561,7 @@
25612561
custom_writer: true
25622562
args:
25632563
receiver: ValId
2564-
getter: ObjectField
2564+
callee: ObjId
25652565
icScript: RawPointerField
25662566
sameRealm: BoolImm
25672567
nargsAndFlags: RawInt32Field

js/src/jit/CacheIRWriter.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -618,19 +618,27 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
618618
callClassHook_(calleeId, argc, flags, argcFixed, target);
619619
}
620620

621+
private:
622+
ObjOperandId getterSetterCalleeOperand(JSFunction* target) {
623+
return loadObject(target);
624+
}
625+
public:
626+
621627
void callScriptedGetterResult(ValOperandId receiver, JSFunction* getter,
622628
bool sameRealm) {
623629
MOZ_ASSERT(getter->hasJitEntry());
624630
uint32_t nargsAndFlags = getter->flagsAndArgCountRaw();
625-
callScriptedGetterResult_(receiver, getter, sameRealm, nargsAndFlags);
631+
ObjOperandId callee = getterSetterCalleeOperand(getter);
632+
callScriptedGetterResult_(receiver, callee, sameRealm, nargsAndFlags);
626633
trialInliningState_ = TrialInliningState::Candidate;
627634
}
628635

629-
void callInlinedGetterResult(ValOperandId receiver, JSFunction* getter,
630-
ICScript* icScript, bool sameRealm) {
636+
void callInlinedGetterResult(ValOperandId receiver, ObjOperandId callee,
637+
JSFunction* getter, ICScript* icScript,
638+
bool sameRealm) {
631639
MOZ_ASSERT(getter->hasJitEntry());
632640
uint32_t nargsAndFlags = getter->flagsAndArgCountRaw();
633-
callInlinedGetterResult_(receiver, getter, icScript, sameRealm,
641+
callInlinedGetterResult_(receiver, callee, icScript, sameRealm,
634642
nargsAndFlags);
635643
trialInliningState_ = TrialInliningState::Inlined;
636644
}

js/src/jit/IonCacheIRCompiler.cpp

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -924,18 +924,18 @@ bool IonCacheIRCompiler::emitLoadDynamicSlotResult(ObjOperandId objId,
924924
}
925925

926926
bool IonCacheIRCompiler::emitCallScriptedGetterResult(
927-
ValOperandId receiverId, uint32_t getterOffset, bool sameRealm,
928-
uint32_t nargsAndFlagsOffset) {
927+
ValOperandId receiverId, ObjOperandId calleeId,
928+
bool sameRealm, uint32_t nargsAndFlagsOffset) {
929929
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
930930
AutoSaveLiveRegisters save(*this);
931931
AutoOutputRegister output(*this);
932932

933933
ValueOperand receiver = allocator.useValueRegister(masm, receiverId);
934-
935-
JSFunction* target = &objectStubField(getterOffset)->as<JSFunction>();
934+
Register callee = allocator.useRegister(masm, calleeId);
936935
AutoScratchRegister scratch(allocator, masm);
937936

938-
MOZ_ASSERT(sameRealm == (cx_->realm() == target->realm()));
937+
int32_t nargsAndFlags = int32StubField(nargsAndFlagsOffset);
938+
size_t nargs = nargsAndFlags >> JSFunction::ArgCountShift;
939939

940940
allocator.discardStack(masm);
941941

@@ -946,34 +946,31 @@ bool IonCacheIRCompiler::emitCallScriptedGetterResult(
946946
// The JitFrameLayout pushed below will be aligned to JitStackAlignment,
947947
// so we just have to make sure the stack is aligned after we push the
948948
// |this| + argument Values.
949-
uint32_t argSize = (target->nargs() + 1) * sizeof(Value);
949+
uint32_t argSize = (nargs + 1) * sizeof(Value);
950950
uint32_t padding =
951951
ComputeByteAlignment(masm.framePushed() + argSize, JitStackAlignment);
952952
MOZ_ASSERT(padding % sizeof(uintptr_t) == 0);
953953
MOZ_ASSERT(padding < JitStackAlignment);
954954
masm.reserveStack(padding);
955955

956-
for (size_t i = 0; i < target->nargs(); i++) {
956+
for (size_t i = 0; i < nargs; i++) {
957957
masm.Push(UndefinedValue());
958958
}
959959
masm.Push(receiver);
960960

961961
if (!sameRealm) {
962-
masm.switchToRealm(target->realm(), scratch);
962+
masm.switchToObjectRealm(callee, scratch);
963963
}
964964

965-
masm.movePtr(ImmGCPtr(target), scratch);
966-
967-
masm.Push(scratch);
965+
masm.Push(callee);
968966
masm.PushFrameDescriptorForJitCall(FrameType::IonICCall, /* argc = */ 0);
969967

970968
// Check stack alignment. Add 2 * sizeof(uintptr_t) for the return address and
971969
// frame pointer pushed by the call/callee.
972970
MOZ_ASSERT(
973971
((masm.framePushed() + 2 * sizeof(uintptr_t)) % JitStackAlignment) == 0);
974972

975-
MOZ_ASSERT(target->hasJitEntry());
976-
masm.loadJitCodeRaw(scratch, scratch);
973+
masm.loadJitCodeRaw(callee, scratch);
977974
masm.callJit(scratch);
978975

979976
if (!sameRealm) {
@@ -1126,7 +1123,7 @@ bool IonCacheIRCompiler::emitCallScriptedProxyGetByValueResult(
11261123
#endif
11271124

11281125
bool IonCacheIRCompiler::emitCallInlinedGetterResult(
1129-
ValOperandId receiverId, uint32_t getterOffset, uint32_t icScriptOffset,
1126+
ValOperandId receiverId, ObjOperandId calleeId, uint32_t icScriptOffset,
11301127
bool sameRealm, uint32_t nargsAndFlagsOffset) {
11311128
MOZ_CRASH("Trial inlining not supported in Ion");
11321129
}

js/src/jit/TrialInlining.cpp

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,9 @@ Maybe<InlinableGetterData> FindInlinableGetterData(ICCacheIRStub* stub) {
305305
const CacheIRStubInfo* stubInfo = stub->stubInfo();
306306
const uint8_t* stubData = stub->stubDataStart();
307307

308+
ObjOperandId maybeCalleeOperand;
309+
uintptr_t maybeRawCallee = 0;
310+
308311
CacheIRReader reader(stubInfo);
309312
while (reader.more()) {
310313
const uint8_t* opStart = reader.currentPosition();
@@ -315,37 +318,47 @@ Maybe<InlinableGetterData> FindInlinableGetterData(ICCacheIRStub* stub) {
315318
mozilla::DebugOnly<const uint8_t*> argStart = reader.currentPosition();
316319

317320
switch (op) {
321+
case CacheOp::LoadObject: {
322+
// If we load a constant object, remember it in case it's the callee.
323+
maybeCalleeOperand = reader.objOperandId();
324+
uint32_t maybeCalleeOffset = reader.stubOffset();
325+
maybeRawCallee = stubInfo->getStubRawWord(stubData, maybeCalleeOffset);
326+
break;
327+
}
318328
case CacheOp::CallScriptedGetterResult: {
319-
data.emplace();
320-
data->receiverOperand = reader.valOperandId();
321-
322-
uint32_t getterOffset = reader.stubOffset();
323-
uintptr_t rawTarget = stubInfo->getStubRawWord(stubData, getterOffset);
324-
data->target = reinterpret_cast<JSFunction*>(rawTarget);
325-
326-
data->sameRealm = reader.readBool();
329+
ValOperandId receiverOperand = reader.valOperandId();
330+
ObjOperandId calleeOperand = reader.objOperandId();
331+
bool sameRealm = reader.readBool();
327332
(void)reader.stubOffset(); // nargsAndFlags
328333

329-
data->endOfSharedPrefix = opStart;
334+
if (maybeCalleeOperand == calleeOperand) {
335+
data.emplace();
336+
data->target = reinterpret_cast<JSFunction*>(maybeRawCallee);
337+
data->receiverOperand = receiverOperand;
338+
data->calleeOperand = calleeOperand;
339+
data->sameRealm = sameRealm;
340+
data->endOfSharedPrefix = opStart;
341+
}
330342
break;
331343
}
332344
case CacheOp::CallInlinedGetterResult: {
333-
data.emplace();
334-
data->receiverOperand = reader.valOperandId();
335-
336-
uint32_t getterOffset = reader.stubOffset();
337-
uintptr_t rawTarget = stubInfo->getStubRawWord(stubData, getterOffset);
338-
data->target = reinterpret_cast<JSFunction*>(rawTarget);
339-
345+
ValOperandId receiverOperand = reader.valOperandId();
346+
ObjOperandId calleeOperand = reader.objOperandId();
340347
uint32_t icScriptOffset = reader.stubOffset();
341348
uintptr_t rawICScript =
342349
stubInfo->getStubRawWord(stubData, icScriptOffset);
343-
data->icScript = reinterpret_cast<ICScript*>(rawICScript);
344-
345-
data->sameRealm = reader.readBool();
350+
bool sameRealm = reader.readBool();
346351
(void)reader.stubOffset(); // nargsAndFlags
347352

348-
data->endOfSharedPrefix = opStart;
353+
if (maybeCalleeOperand == calleeOperand) {
354+
data.emplace();
355+
data->target = reinterpret_cast<JSFunction*>(maybeRawCallee);
356+
data->receiverOperand = receiverOperand;
357+
data->calleeOperand = calleeOperand;
358+
data->icScript = reinterpret_cast<ICScript*>(rawICScript);
359+
data->sameRealm = sameRealm;
360+
data->endOfSharedPrefix = opStart;
361+
}
349362
break;
350363
}
351364
default:
@@ -829,8 +842,8 @@ bool TrialInliner::maybeInlineGetter(ICEntry& entry, ICFallbackStub* fallback,
829842
}
830843
cloneSharedPrefix(stub, data->endOfSharedPrefix, writer);
831844

832-
writer.callInlinedGetterResult(data->receiverOperand, data->target,
833-
newICScript, data->sameRealm);
845+
writer.callInlinedGetterResult(data->receiverOperand, data->calleeOperand,
846+
data->target, newICScript, data->sameRealm);
834847
writer.returnFromIC();
835848

836849
return replaceICStub(entry, fallback, writer, kind);

js/src/jit/TrialInlining.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class InlinableCallData : public InlinableOpData {
126126
class InlinableGetterData : public InlinableOpData {
127127
public:
128128
ValOperandId receiverOperand;
129+
ObjOperandId calleeOperand;
129130
bool sameRealm = false;
130131
};
131132

js/src/jit/WarpCacheIRTranspiler.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ class MOZ_RAII WarpCacheIRTranspiler : public WarpBuilderShared {
302302

303303
[[nodiscard]] bool emitCallGetterResult(CallKind kind,
304304
ValOperandId receiverId,
305-
uint32_t getterOffset, bool sameRealm,
305+
MDefinition* getter, bool sameRealm,
306306
uint32_t nargsAndFlagsOffset);
307307
[[nodiscard]] bool emitCallSetter(CallKind kind, ObjOperandId receiverId,
308308
uint32_t setterOffset, ValOperandId rhsId,
@@ -6618,11 +6618,10 @@ bool WarpCacheIRTranspiler::emitGuardWasmArg(ValOperandId argId,
66186618

66196619
bool WarpCacheIRTranspiler::emitCallGetterResult(CallKind kind,
66206620
ValOperandId receiverId,
6621-
uint32_t getterOffset,
6621+
MDefinition* getter,
66226622
bool sameRealm,
66236623
uint32_t nargsAndFlagsOffset) {
66246624
MDefinition* receiver = getOperand(receiverId);
6625-
MDefinition* getter = objectStubField(getterOffset);
66266625
if (kind == CallKind::Scripted && callInfo_ && callInfo_->isInlined()) {
66276626
// We are transpiling to generate the correct guards. We also update the
66286627
// CallInfo to use the correct arguments. Code for the inlined getter
@@ -6664,23 +6663,26 @@ bool WarpCacheIRTranspiler::emitCallGetterResult(CallKind kind,
66646663
}
66656664

66666665
bool WarpCacheIRTranspiler::emitCallScriptedGetterResult(
6667-
ValOperandId receiverId, uint32_t getterOffset, bool sameRealm,
6666+
ValOperandId receiverId, ObjOperandId calleeId, bool sameRealm,
66686667
uint32_t nargsAndFlagsOffset) {
6669-
return emitCallGetterResult(CallKind::Scripted, receiverId, getterOffset,
6668+
MDefinition* getter = getOperand(calleeId);
6669+
return emitCallGetterResult(CallKind::Scripted, receiverId, getter,
66706670
sameRealm, nargsAndFlagsOffset);
66716671
}
66726672

66736673
bool WarpCacheIRTranspiler::emitCallInlinedGetterResult(
6674-
ValOperandId receiverId, uint32_t getterOffset, uint32_t icScriptOffset,
6674+
ValOperandId receiverId, ObjOperandId calleeId, uint32_t icScriptOffset,
66756675
bool sameRealm, uint32_t nargsAndFlagsOffset) {
6676-
return emitCallGetterResult(CallKind::Scripted, receiverId, getterOffset,
6676+
MDefinition* getter = getOperand(calleeId);
6677+
return emitCallGetterResult(CallKind::Scripted, receiverId, getter,
66776678
sameRealm, nargsAndFlagsOffset);
66786679
}
66796680

66806681
bool WarpCacheIRTranspiler::emitCallNativeGetterResult(
66816682
ValOperandId receiverId, uint32_t getterOffset, bool sameRealm,
66826683
uint32_t nargsAndFlagsOffset) {
6683-
return emitCallGetterResult(CallKind::Native, receiverId, getterOffset,
6684+
MDefinition* getter = objectStubField(getterOffset);
6685+
return emitCallGetterResult(CallKind::Native, receiverId, getter,
66846686
sameRealm, nargsAndFlagsOffset);
66856687
}
66866688

0 commit comments

Comments
 (0)