Skip to content

Commit a543114

Browse files
paulbissfacebook-github-bot
authored andcommitted
Have CallFuncEntry operate on locals
Summary: - Generate an `EnterInlineFrame` instruction for `CallFuncEntry`. - Introduce a variant of `EnterInlineFrame` which "teleports" stack parameters to locals. Right now this is a noop but if we want to change the layout of frame locals it will be responsible for performing this transformation. - Change `CallFuncEntry` to take a callee `FramePtr` defined by `DefCalleeFP` rather than a `StkPtr`. - Matching tweaks for prologues. Reviewed By: jano Differential Revision: D72466109 fbshipit-source-id: 04f8da554e05ae646de2d7e2db0a7ed24e6d2b65
1 parent bff3c95 commit a543114

18 files changed

+342
-163
lines changed

hphp/doc/ir.specification

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,10 +1619,11 @@ To string conversions:
16191619
Defines a new frame pointer for an ActRec at callBCOff for use in an inlined
16201620
region. The frame is defined relative to S0, and S1 is the parent frame.
16211621

1622-
| EnterInlineFrame, ND, S(FramePtr), NF
1622+
| EnterInlineFrame<numInputs>, ND, S(FramePtr), NF
16231623

16241624
Marks the start of an inlined function whose stack resides offset cells below
1625-
the SP.
1625+
the SP. If non-zero numInputs items will be teleported from the stack into the
1626+
locals.
16261627

16271628
| LeaveInlineFrame, ND, S(FramePtr), NF
16281629

@@ -1687,11 +1688,11 @@ ReqBindJmp and CallFuncEntry.
16871688

16881689
| CallFuncEntry<target,spOffset,arFlags>,
16891690
| DCall,
1690-
| S(StkPtr) S(FramePtr) S(Cls|Obj|Nullptr),
1691+
| S(FramePtr) S(FramePtr) S(Cls|Obj|Nullptr),
16911692
| CRc|PRc
16921693

16931694
Transfer control to the func entry at `target' SrcKey, based on the pre-live
1694-
activation record and set of args on the stack pointed to by S0 at `spOffset'.
1695+
activation record and set of args in the callee frame pointed to by S0.
16951696
S1 is the current caller frame pointer. S2 is the context (nullptr, $this or
16961697
static::class).
16971698

@@ -2834,8 +2835,8 @@ ReqBindJmp and CallFuncEntry.
28342835

28352836
| KillIter<iterId>, ND, S(FramePtr), NF
28362837

2837-
Mark a given ActRec, local, or iterator as being dead for the purposes of
2838-
memory effects. It no longer contains a meaningful value.
2838+
Mark a given ActRec, local, or iterator as being dead for the
2839+
purposes of memory effects. It no longer contains a meaningful value.
28392840

28402841
These operations are used for both correctness and performance. Inserting a
28412842
kill can help us do store-elimination; if a write is followed by a kill on

hphp/runtime/vm/jit/extra-data.h

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,29 +1321,26 @@ struct CallData : IRExtraData {
13211321

13221322
struct CallFuncEntryData : IRExtraData {
13231323
explicit CallFuncEntryData(const SrcKey& target,
1324-
IRSPRelOffset spOffset,
13251324
uint32_t numInitArgs,
13261325
uint32_t arFlags,
13271326
bool formingRegion)
13281327
: target(target)
1329-
, spOffset(spOffset)
13301328
, numInitArgs(numInitArgs)
13311329
, arFlags(arFlags)
13321330
, formingRegion(formingRegion)
13331331
{}
13341332

13351333
std::string show() const {
13361334
return folly::sformat(
1337-
"{}, IRSP {}, numInitArgs {}, arFlags {}{}",
1338-
showShort(target), spOffset.offset, numInitArgs, arFlags,
1335+
"{}, numInitArgs {}, arFlags {}{}",
1336+
showShort(target), numInitArgs, arFlags,
13391337
formingRegion ? ",formingRegion" :""
13401338
);
13411339
}
13421340

13431341
size_t stableHash() const {
13441342
return folly::hash::hash_combine(
13451343
SrcKey::StableHasher()(target),
1346-
std::hash<int32_t>()(spOffset.offset),
13471344
std::hash<uint32_t>()(numInitArgs),
13481345
std::hash<uint32_t>()(arFlags),
13491346
std::hash<bool>()(formingRegion)
@@ -1352,7 +1349,6 @@ struct CallFuncEntryData : IRExtraData {
13521349

13531350
bool equals(const CallFuncEntryData& o) const {
13541351
return target == o.target &&
1355-
spOffset == o.spOffset &&
13561352
numInitArgs == o.numInitArgs &&
13571353
arFlags == o.arFlags &&
13581354
formingRegion == o.formingRegion;
@@ -1362,12 +1358,7 @@ struct CallFuncEntryData : IRExtraData {
13621358
return arFlags & (1 << ActRec::AsyncEagerRet);
13631359
}
13641360

1365-
void updateStackOffsets(int32_t delta) {
1366-
spOffset.offset += delta;
1367-
}
1368-
13691361
SrcKey target;
1370-
IRSPRelOffset spOffset;
13711362
uint32_t numInitArgs;
13721363
uint32_t arFlags;
13731364
bool formingRegion;
@@ -3054,6 +3045,40 @@ struct LdClsFallbackData : IRExtraData {
30543045
LdClsFallback fallback;
30553046
};
30563047

3048+
struct EnterInlineFrameData : IRExtraData {
3049+
EnterInlineFrameData(bool copy, uint32_t numInitArgs)
3050+
: copy(copy)
3051+
, numInitArgs(numInitArgs)
3052+
{}
3053+
3054+
static EnterInlineFrameData Copy(uint32_t numInitArgs) {
3055+
return EnterInlineFrameData {true, numInitArgs};
3056+
}
3057+
3058+
static EnterInlineFrameData NoCopy() {
3059+
return EnterInlineFrameData {false, 0};
3060+
}
3061+
3062+
std::string show() const {
3063+
return folly::to<std::string>(copy ? "copy, " : "",
3064+
"numInitArgs ", numInitArgs);
3065+
}
3066+
size_t hash() const {
3067+
return folly::hash::hash_combine(
3068+
copy ? 1 : 0,
3069+
std::hash<uint32_t>()(numInitArgs)
3070+
);
3071+
}
3072+
size_t stableHash() const { return hash(); }
3073+
3074+
bool equals(const EnterInlineFrameData& o) const {
3075+
return copy == o.copy && numInitArgs == o.numInitArgs;
3076+
}
3077+
3078+
bool copy;
3079+
uint32_t numInitArgs;
3080+
};
3081+
30573082
//////////////////////////////////////////////////////////////////////
30583083

30593084
#define X(op, data) \
@@ -3134,6 +3159,7 @@ X(CallBuiltin, CallBuiltinData);
31343159
X(CallFuncEntry, CallFuncEntryData);
31353160
X(InlineSideExit, InlineSideExitData);
31363161
X(InlineSideExitSyncStack, StackRange);
3162+
X(EnterInlineFrame, EnterInlineFrameData);
31373163
X(RetCtrl, RetCtrlData);
31383164
X(AsyncFuncRet, IRSPRelOffsetData);
31393165
X(AsyncFuncRetSlow, IRSPRelOffsetData);

hphp/runtime/vm/jit/frame-state.cpp

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -347,20 +347,17 @@ void FrameStateMgr::update(const IRInstruction* inst) {
347347
assertx(cur().checkMInstrStateDead());
348348
auto const extra = inst->extra<CallFuncEntry>();
349349
auto const callee = extra->target.func();
350-
// Remove tracked state for the slots for argc and the actrec.
351-
uint32_t numCells = kNumActRecCells + callee->numFuncEntryInputs();
352-
for (auto i = uint32_t{0}; i < numCells; ++i) {
353-
setValue(stk(extra->spOffset + i), nullptr);
354-
}
350+
auto const defCalleeFP = inst->src(0)->inst();
351+
assertx(defCalleeFP->is(DefCalleeFP));
352+
355353
// Set the type of out parameter locations.
356-
auto const base = extra->spOffset + numCells;
354+
auto const base =
355+
defCalleeFP->extra<DefCalleeFP>()->spOffset + kNumActRecCells;
357356
for (auto i = uint32_t{0}; i < callee->numInOutParams(); ++i) {
358357
setType(stk(base + i), irgen::callOutType(callee, i));
359358
}
360359
// We consider popping an ActRec and args to be synced to memory.
361360
assertx(cur().bcSPOff == inst->marker().bcSPOff());
362-
assertx(cur().bcSPOff.offset >= numCells);
363-
cur().bcSPOff -= numCells;
364361
}
365362
break;
366363

@@ -498,16 +495,20 @@ void FrameStateMgr::update(const IRInstruction* inst) {
498495

499496
case StLoc:
500497
case StLocMeta:
501-
setValueAndSyncMBase(
502-
loc(inst->extra<LocalId>()->locId),
503-
inst->src(1),
504-
false
505-
);
498+
if (inst->src(0) == cur().fp()) {
499+
setValueAndSyncMBase(
500+
loc(inst->extra<LocalId>()->locId),
501+
inst->src(1),
502+
false
503+
);
504+
}
506505
break;
507506

508507
case LdLoc: {
509-
auto const id = inst->extra<LdLoc>()->locId;
510-
setValueAndSyncMBase(loc(id), inst->dst(), true);
508+
if (inst->src(0) == cur().fp()) {
509+
auto const id = inst->extra<LdLoc>()->locId;
510+
setValueAndSyncMBase(loc(id), inst->dst(), true);
511+
}
511512
break;
512513
}
513514

@@ -1011,14 +1012,17 @@ void FrameStateMgr::trackEnterInlineFrame(const IRInstruction* inst) {
10111012
auto const extra = inst->src(0)->inst()->extra<DefCalleeFP>();
10121013
auto const callee = extra->func;
10131014
auto const spOffset = extra->spOffset;
1014-
assertx(cur().bcSPOff == spOffset.to<SBInvOffset>(irSPOff()));
1015+
auto const adjust = inst->extra<EnterInlineFrame>()->copy
1016+
? callee->numFuncEntryInputs()
1017+
: 0;
1018+
assertx(cur().bcSPOff - adjust == spOffset.to<SBInvOffset>(irSPOff()));
10151019

10161020
// Remove space from callee's frame from the caller's stack.
1017-
for (auto i = uint32_t{0}; i < kNumActRecCells; ++i) {
1018-
setValue(stk(spOffset + i), nullptr);
1021+
for (auto i = uint32_t{0}; i < kNumActRecCells + adjust; ++i) {
1022+
setValue(stk(spOffset - adjust + i), nullptr);
10191023
}
10201024
assertx(cur().bcSPOff.offset >= kNumActRecCells);
1021-
cur().bcSPOff -= kNumActRecCells;
1025+
cur().bcSPOff -= kNumActRecCells + adjust;
10221026

10231027
if (callee->isCPPBuiltin()) {
10241028
auto const inout = callee->numInOutParams();

hphp/runtime/vm/jit/inlining-decider.cpp

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -725,10 +725,13 @@ RegionDescPtr selectCalleeCFG(SrcKey callerSk, SrcKey entry,
725725
}
726726
}
727727

728-
irgen::RegionAndLazyUnit selectCalleeRegion(const irgen::IRGS& irgs,
729-
SrcKey entry,
730-
Type ctxType,
731-
SrcKey callerSk) {
728+
irgen::RegionAndLazyUnit selectCalleeRegion(
729+
const irgen::IRGS& irgs,
730+
SrcKey entry,
731+
Type ctxType,
732+
SrcKey callerSk,
733+
std::vector<Type> inputTypes
734+
) {
732735
assertx(entry.funcEntry());
733736
auto const callee = entry.func();
734737

@@ -778,20 +781,13 @@ irgen::RegionAndLazyUnit selectCalleeRegion(const irgen::IRGS& irgs,
778781
}
779782

780783
FTRACE(2, "selectCalleeRegion: callee = {}\n", callee->fullName()->data());
781-
auto const firstInputPos = callee->numFuncEntryInputs() - 1;
782-
std::vector<Type> inputTypes;
783-
for (uint32_t i = 0; i < callee->numFuncEntryInputs(); ++i) {
784-
// DataTypeGeneric is used because we're just passing the locals into the
785-
// callee. It's up to the callee to constrain further if needed.
786-
auto const offset = BCSPRelOffset{safe_cast<int32_t>(firstInputPos - i)};
787-
auto const type = irgen::publicTopType(irgs, offset);
788-
assertx(type <= TCell);
784+
assertx(inputTypes.size() == callee->numFuncEntryInputs());
789785

786+
for (int i = 0; i < inputTypes.size(); ++i) {
790787
// If we don't have sufficient type information to inline the region return
791788
// early
792-
if (type == TBottom) return {callerSk, nullptr};
793-
FTRACE(2, "input {}: {}\n", i + 1, type);
794-
inputTypes.push_back(type);
789+
if (inputTypes[i] == TBottom) return {callerSk, nullptr};
790+
FTRACE(2, "input {}: {}\n", i + 1, inputTypes[i]);
795791
}
796792

797793
while (entry.trivialDVFuncEntry()) {

hphp/runtime/vm/jit/inlining-decider.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ int costOfInlining(SrcKey callerSk,
103103
irgen::RegionAndLazyUnit selectCalleeRegion(const irgen::IRGS& irgs,
104104
SrcKey entry,
105105
Type ctxType,
106-
SrcKey callerSk);
106+
SrcKey callerSk,
107+
std::vector<Type> inputTypes);
107108

108109
void setInliningMetadata(uint64_t baseProfCount,
109110
const jit::hash_map<FuncId, uint32_t>& funcTargetCounts);

0 commit comments

Comments
 (0)