Skip to content

Commit 485efc1

Browse files
committed
Bug 1703469: Use JSScript instead of JSFunction in trial inlining r=jandem
We inline scripts, not functions, so switching to scripts as soon as possible in the inliner makes everything a little cleaner. Differential Revision: https://phabricator.services.mozilla.com/D251758
1 parent 4e6df2c commit 485efc1

File tree

3 files changed

+62
-54
lines changed

3 files changed

+62
-54
lines changed

js/src/jit/TrialInlining.cpp

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ Maybe<InlinableCallData> FindInlinableCallData(ICCacheIRStub* stub) {
206206

207207
ObjOperandId calleeGuardOperand;
208208
CallFlags flags;
209-
JSFunction* target = nullptr;
209+
JSScript* targetScript = nullptr;
210210

211211
CacheIRReader reader(stubInfo);
212212
while (reader.more()) {
@@ -219,21 +219,26 @@ Maybe<InlinableCallData> FindInlinableCallData(ICCacheIRStub* stub) {
219219

220220
switch (op) {
221221
case CacheOp::GuardSpecificFunction: {
222-
// If we see a guard, remember which operand we are guarding.
222+
// If we see a guard for a scripted function, remember which
223+
// operand we are guarding.
223224
MOZ_ASSERT(data.isNothing());
224-
calleeGuardOperand = reader.objOperandId();
225+
ObjOperandId maybeCalleeGuardOperand = reader.objOperandId();
225226
uint32_t targetOffset = reader.stubOffset();
226227
(void)reader.stubOffset(); // nargsAndFlags
227-
uintptr_t rawTarget = stubInfo->getStubRawWord(stubData, targetOffset);
228-
target = reinterpret_cast<JSFunction*>(rawTarget);
228+
uintptr_t rawFunction = stubInfo->getStubRawWord(stubData, targetOffset);
229+
JSFunction* function = reinterpret_cast<JSFunction*>(rawFunction);
230+
if (function->hasBytecode()) {
231+
calleeGuardOperand = maybeCalleeGuardOperand;
232+
targetScript = function->nonLazyScript();
233+
}
229234
break;
230235
}
231236
case CacheOp::GuardFunctionScript: {
232237
MOZ_ASSERT(data.isNothing());
233238
calleeGuardOperand = reader.objOperandId();
234239
uint32_t targetOffset = reader.stubOffset();
235-
uintptr_t rawTarget = stubInfo->getStubRawWord(stubData, targetOffset);
236-
target = reinterpret_cast<BaseScript*>(rawTarget)->function();
240+
uintptr_t rawScript = stubInfo->getStubRawWord(stubData, targetOffset);
241+
targetScript = reinterpret_cast<JSScript*>(rawScript);
237242
(void)reader.stubOffset(); // nargsAndFlags
238243
break;
239244
}
@@ -294,7 +299,7 @@ Maybe<InlinableCallData> FindInlinableCallData(ICCacheIRStub* stub) {
294299
}
295300
data->calleeOperand = calleeGuardOperand;
296301
data->callFlags = flags;
297-
data->target = target;
302+
data->target = targetScript;
298303
}
299304
return data;
300305
}
@@ -306,7 +311,7 @@ Maybe<InlinableGetterData> FindInlinableGetterData(ICCacheIRStub* stub) {
306311
const uint8_t* stubData = stub->stubDataStart();
307312

308313
ObjOperandId maybeCalleeOperand;
309-
uintptr_t maybeRawCallee = 0;
314+
JSScript* targetScript = nullptr;
310315

311316
CacheIRReader reader(stubInfo);
312317
while (reader.more()) {
@@ -320,9 +325,14 @@ Maybe<InlinableGetterData> FindInlinableGetterData(ICCacheIRStub* stub) {
320325
switch (op) {
321326
case CacheOp::LoadObject: {
322327
// 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);
328+
ObjOperandId resultOperand = reader.objOperandId();
329+
uint32_t objOffset = reader.stubOffset();
330+
uintptr_t rawObject = stubInfo->getStubRawWord(stubData, objOffset);
331+
JSObject* object = reinterpret_cast<JSObject*>(rawObject);
332+
if (object->is<JSFunction>() && object->as<JSFunction>().hasBytecode()) {
333+
maybeCalleeOperand = resultOperand;
334+
targetScript = object->as<JSFunction>().nonLazyScript();
335+
}
326336
break;
327337
}
328338
case CacheOp::CallScriptedGetterResult: {
@@ -333,7 +343,7 @@ Maybe<InlinableGetterData> FindInlinableGetterData(ICCacheIRStub* stub) {
333343

334344
if (maybeCalleeOperand == calleeOperand) {
335345
data.emplace();
336-
data->target = reinterpret_cast<JSFunction*>(maybeRawCallee);
346+
data->target = targetScript;
337347
data->receiverOperand = receiverOperand;
338348
data->calleeOperand = calleeOperand;
339349
data->sameRealm = sameRealm;
@@ -352,7 +362,7 @@ Maybe<InlinableGetterData> FindInlinableGetterData(ICCacheIRStub* stub) {
352362

353363
if (maybeCalleeOperand == calleeOperand) {
354364
data.emplace();
355-
data->target = reinterpret_cast<JSFunction*>(maybeRawCallee);
365+
data->target = targetScript;
356366
data->receiverOperand = receiverOperand;
357367
data->calleeOperand = calleeOperand;
358368
data->icScript = reinterpret_cast<ICScript*>(rawICScript);
@@ -384,7 +394,7 @@ Maybe<InlinableSetterData> FindInlinableSetterData(ICCacheIRStub* stub) {
384394
const uint8_t* stubData = stub->stubDataStart();
385395

386396
ObjOperandId maybeCalleeOperand;
387-
uintptr_t maybeRawCallee = 0;
397+
JSScript* targetScript = nullptr;
388398

389399
CacheIRReader reader(stubInfo);
390400
while (reader.more()) {
@@ -398,9 +408,14 @@ Maybe<InlinableSetterData> FindInlinableSetterData(ICCacheIRStub* stub) {
398408
switch (op) {
399409
case CacheOp::LoadObject: {
400410
// If we load a constant object, remember it in case it's the callee.
401-
maybeCalleeOperand = reader.objOperandId();
402-
uint32_t maybeCalleeOffset = reader.stubOffset();
403-
maybeRawCallee = stubInfo->getStubRawWord(stubData, maybeCalleeOffset);
411+
ObjOperandId resultOperand = reader.objOperandId();
412+
uint32_t objOffset = reader.stubOffset();
413+
uintptr_t rawObject = stubInfo->getStubRawWord(stubData, objOffset);
414+
JSObject* object = reinterpret_cast<JSObject*>(rawObject);
415+
if (object->is<JSFunction>() && object->as<JSFunction>().hasBytecode()) {
416+
maybeCalleeOperand = resultOperand;
417+
targetScript = object->as<JSFunction>().nonLazyScript();
418+
}
404419
break;
405420
}
406421
case CacheOp::CallScriptedSetter: {
@@ -412,7 +427,7 @@ Maybe<InlinableSetterData> FindInlinableSetterData(ICCacheIRStub* stub) {
412427

413428
if (maybeCalleeOperand == calleeOperand) {
414429
data.emplace();
415-
data->target = reinterpret_cast<JSFunction*>(maybeRawCallee);
430+
data->target = targetScript;
416431
data->receiverOperand = receiverOperand;
417432
data->calleeOperand = calleeOperand;
418433
data->rhsOperand = rhsOperand;
@@ -433,7 +448,7 @@ Maybe<InlinableSetterData> FindInlinableSetterData(ICCacheIRStub* stub) {
433448

434449
if (maybeCalleeOperand == calleeOperand) {
435450
data.emplace();
436-
data->target = reinterpret_cast<JSFunction*>(maybeRawCallee);
451+
data->target = targetScript;
437452
data->receiverOperand = receiverOperand;
438453
data->calleeOperand = calleeOperand;
439454
data->rhsOperand = rhsOperand;
@@ -512,13 +527,12 @@ bool TrialInliner::IsValidInliningOp(JSOp op) {
512527
}
513528

514529
/*static*/
515-
bool TrialInliner::canInline(JSFunction* target, HandleScript caller,
530+
bool TrialInliner::canInline(JSScript* script, HandleScript caller,
516531
BytecodeLocation loc) {
517-
if (!target->hasJitScript()) {
532+
if (!script->hasJitScript()) {
518533
JitSpew(JitSpew_WarpTrialInlining, "SKIP: no JIT script");
519534
return false;
520535
}
521-
JSScript* script = target->nonLazyScript();
522536
if (!script->jitScript()->hasBaselineScript()) {
523537
JitSpew(JitSpew_WarpTrialInlining, "SKIP: no BaselineScript");
524538
return false;
@@ -536,7 +550,7 @@ bool TrialInliner::canInline(JSFunction* target, HandleScript caller,
536550
return false;
537551
}
538552
// Don't inline cross-realm calls.
539-
if (target->realm() != caller->realm()) {
553+
if (script->realm() != caller->realm()) {
540554
JitSpew(JitSpew_WarpTrialInlining, "SKIP: cross-realm call");
541555
return false;
542556
}
@@ -567,9 +581,10 @@ bool TrialInliner::canInline(JSFunction* target, HandleScript caller,
567581
}
568582
}
569583

570-
if (TooManyFormalArguments(target->nargs())) {
584+
if (script->function() &&
585+
TooManyFormalArguments(script->function()->nargs())) {
571586
JitSpew(JitSpew_WarpTrialInlining, "SKIP: Too many formal arguments: %u",
572-
unsigned(target->nargs()));
587+
unsigned(script->function()->nargs()));
573588
return false;
574589
}
575590

@@ -623,38 +638,36 @@ static bool ShouldUseMonomorphicInlining(JSScript* targetScript) {
623638
return true;
624639
}
625640

626-
TrialInliningDecision TrialInliner::getInliningDecision(JSFunction* target,
641+
TrialInliningDecision TrialInliner::getInliningDecision(JSScript* targetScript,
627642
ICCacheIRStub* stub,
628643
BytecodeLocation loc) {
629644
#ifdef JS_JITSPEW
630645
if (JitSpewEnabled(JitSpew_WarpTrialInlining)) {
631-
BaseScript* baseScript =
632-
target->hasBaseScript() ? target->baseScript() : nullptr;
633-
634646
UniqueChars funName;
635-
if (target->maybePartialDisplayAtom()) {
636-
funName = AtomToPrintableString(cx(), target->maybePartialDisplayAtom());
647+
if (targetScript->function()) {
648+
if (JSAtom* atom = targetScript->function()->maybePartialDisplayAtom()) {
649+
funName = AtomToPrintableString(cx(), atom);
650+
}
637651
}
638652

639653
JitSpew(JitSpew_WarpTrialInlining,
640654
"Inlining candidate JSOp::%s (offset=%u): callee script '%s' "
641655
"(%s:%u:%u)",
642656
CodeName(loc.getOp()), loc.bytecodeToOffset(script_),
643657
funName ? funName.get() : "<unnamed>",
644-
baseScript ? baseScript->filename() : "<not-scripted>",
645-
baseScript ? baseScript->lineno() : 0,
646-
baseScript ? baseScript->column().oneOriginValue() : 0);
658+
targetScript->filename(),
659+
targetScript->lineno(),
660+
targetScript->column().oneOriginValue());
647661
JitSpewIndent spewIndent(JitSpew_WarpTrialInlining);
648662
}
649663
#endif
650664

651-
if (!canInline(target, script_, loc)) {
665+
if (!canInline(targetScript, script_, loc)) {
652666
return TrialInliningDecision::NoInline;
653667
}
654668

655669
// Don't inline (direct) recursive calls. This still allows recursion if
656670
// called through another function (f => g => f).
657-
JSScript* targetScript = target->nonLazyScript();
658671
if (script_ == targetScript) {
659672
JitSpew(JitSpew_WarpTrialInlining, "SKIP: recursion");
660673
return TrialInliningDecision::NoInline;
@@ -705,18 +718,15 @@ TrialInliningDecision TrialInliner::getInliningDecision(JSFunction* target,
705718
return TrialInliningDecision::MonomorphicInline;
706719
}
707720

708-
ICScript* TrialInliner::createInlinedICScript(JSFunction* target,
721+
ICScript* TrialInliner::createInlinedICScript(JSScript* targetScript,
709722
BytecodeLocation loc) {
710-
MOZ_ASSERT(target->hasJitEntry());
711-
MOZ_ASSERT(target->hasJitScript());
723+
MOZ_ASSERT(targetScript->hasJitScript());
712724

713725
InliningRoot* root = getOrCreateInliningRoot();
714726
if (!root) {
715727
return nullptr;
716728
}
717729

718-
JSScript* targetScript = target->baseScript()->asJSScript();
719-
720730
// We don't have to check for overflow here because we have already
721731
// successfully allocated an ICScript with this number of entries
722732
// when creating the JitScript for the target function, and we
@@ -857,7 +867,8 @@ bool TrialInliner::maybeInlineGetter(ICEntry& entry, ICFallbackStub* fallback,
857867
cloneSharedPrefix(stub, data->endOfSharedPrefix, writer);
858868

859869
writer.callInlinedGetterResult(data->receiverOperand, data->calleeOperand,
860-
data->target, newICScript, data->sameRealm);
870+
data->target->function(), newICScript,
871+
data->sameRealm);
861872
writer.returnFromIC();
862873

863874
return replaceICStub(entry, fallback, writer, kind);
@@ -901,8 +912,8 @@ bool TrialInliner::maybeInlineSetter(ICEntry& entry, ICFallbackStub* fallback,
901912
cloneSharedPrefix(stub, data->endOfSharedPrefix, writer);
902913

903914
writer.callInlinedSetter(data->receiverOperand, data->calleeOperand,
904-
data->target, data->rhsOperand, newICScript,
905-
data->sameRealm);
915+
data->target->function(), data->rhsOperand,
916+
newICScript, data->sameRealm);
906917
writer.returnFromIC();
907918

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

js/src/jit/TrialInlining.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@
4949
class JS_PUBLIC_API JSTracer;
5050
struct JS_PUBLIC_API JSContext;
5151

52-
class JSFunction;
53-
5452
namespace JS {
5553
class Zone;
5654
}
@@ -112,7 +110,7 @@ class InliningRoot {
112110

113111
class InlinableOpData {
114112
public:
115-
JSFunction* target = nullptr;
113+
JSScript* target = nullptr;
116114
ICScript* icScript = nullptr;
117115
const uint8_t* endOfSharedPrefix = nullptr;
118116
};
@@ -168,7 +166,7 @@ class MOZ_RAII TrialInliner {
168166
[[nodiscard]] bool maybeInlineSetter(ICEntry& entry, ICFallbackStub* fallback,
169167
BytecodeLocation loc, CacheKind kind);
170168

171-
static bool canInline(JSFunction* target, HandleScript caller,
169+
static bool canInline(JSScript* target, HandleScript caller,
172170
BytecodeLocation loc);
173171

174172
static bool IsValidInliningOp(JSOp op);
@@ -177,11 +175,11 @@ class MOZ_RAII TrialInliner {
177175
ICCacheIRStub* maybeSingleStub(const ICEntry& entry);
178176
void cloneSharedPrefix(ICCacheIRStub* stub, const uint8_t* endOfPrefix,
179177
CacheIRWriter& writer);
180-
ICScript* createInlinedICScript(JSFunction* target, BytecodeLocation loc);
178+
ICScript* createInlinedICScript(JSScript* target, BytecodeLocation loc);
181179
[[nodiscard]] bool replaceICStub(ICEntry& entry, ICFallbackStub* fallback,
182180
CacheIRWriter& writer, CacheKind kind);
183181

184-
TrialInliningDecision getInliningDecision(JSFunction* target,
182+
TrialInliningDecision getInliningDecision(JSScript* target,
185183
ICCacheIRStub* stub,
186184
BytecodeLocation loc);
187185

js/src/jit/WarpOracle.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,8 +1019,8 @@ AbortReasonOr<bool> WarpScriptOracle::maybeInlineCall(
10191019
return false;
10201020
}
10211021

1022-
RootedFunction targetFunction(cx_, inlineData->target);
1023-
if (!TrialInliner::canInline(targetFunction, script_, loc)) {
1022+
RootedScript targetScript(cx_, inlineData->target);
1023+
if (!TrialInliner::canInline(targetScript, script_, loc)) {
10241024
return false;
10251025
}
10261026

@@ -1029,7 +1029,6 @@ AbortReasonOr<bool> WarpScriptOracle::maybeInlineCall(
10291029
MOZ_ASSERT_IF(!isTrialInlined, fallbackStub->trialInliningState() ==
10301030
TrialInliningState::MonomorphicInlined);
10311031

1032-
RootedScript targetScript(cx_, targetFunction->nonLazyScript());
10331032
ICScript* icScript = nullptr;
10341033
if (isTrialInlined) {
10351034
icScript = inlineData->icScript;

0 commit comments

Comments
 (0)