Implement FCallArray in IR
Esse commit está contido em:
@@ -881,6 +881,14 @@ InlineReturn S0:FramePtr
|
||||
|
||||
Unlinks a frame constructed by DefInlineFP.
|
||||
|
||||
D:StkPtr = CallArray S0:StkPtr
|
||||
|
||||
Invoke function corresponding to the current FPI with array args.
|
||||
S0 points to the stack resulting after the ActRec for the function
|
||||
and the array of its arguments is pushed. CallArray pops the array
|
||||
off the stack, pushes the elements of the array as arguments, and
|
||||
invokes the function in the ActRec.
|
||||
|
||||
D:StkPtr = Call S0:StkPtr S1:ConstInt S2:Func S3...
|
||||
|
||||
Invoke the function S2 with ActRec S0 and variadic arguments S3...
|
||||
|
||||
@@ -3238,6 +3238,18 @@ void CodeGenerator::cgInlineCreateCont(IRInstruction* inst) {
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::cgCallArray(IRInstruction* inst) {
|
||||
Offset pc = inst->getExtra<CallArray>()->pc;
|
||||
Offset after = inst->getExtra<CallArray>()->after;
|
||||
|
||||
ArgGroup args;
|
||||
args.imm(pc).imm(after);
|
||||
|
||||
// fCallArrayHelper makes the actual call by smashing its return address.
|
||||
cgCallHelper(m_as, (TCA)TranslatorX64::fCallArrayHelper,
|
||||
nullptr, kSyncPoint, args);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgCall(IRInstruction* inst) {
|
||||
SSATmp* actRec = inst->getSrc(0);
|
||||
SSATmp* returnBcOffset = inst->getSrc(1);
|
||||
|
||||
@@ -1776,8 +1776,10 @@ void HhbcTranslator::emitFPushClsMethodF(int32_t numParams,
|
||||
}
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitFCallArray() {
|
||||
PUNT(FCallArray); // can't interpret one because of control flow
|
||||
void HhbcTranslator::emitFCallArray(const Offset pcOffset,
|
||||
const Offset after) {
|
||||
SSATmp* stack = spillStack();
|
||||
gen(CallArray, CallArrayData(pcOffset, after), stack);
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitFCall(uint32_t numParams,
|
||||
|
||||
@@ -240,7 +240,7 @@ struct HhbcTranslator {
|
||||
void emitFPushCtorD(int32_t numParams, int32_t classNameStrId);
|
||||
void emitFPushCtor(int32_t numParams);
|
||||
void emitCreateCl(int32_t numParams, int32_t classNameStrId);
|
||||
void emitFCallArray();
|
||||
void emitFCallArray(const Offset pcOffset, const Offset after);
|
||||
void emitFCall(uint32_t numParams,
|
||||
Offset returnBcOffset,
|
||||
const Func* callee);
|
||||
|
||||
@@ -333,6 +333,7 @@ O(LdRaw, DParam, SUnk, NF) \
|
||||
O(FreeActRec, D(FramePtr), S(FramePtr), Mem) \
|
||||
/* name dstinfo srcinfo flags */ \
|
||||
O(Call, D(StkPtr), SUnk, E|Mem|CRc|Refs) \
|
||||
O(CallArray, D(StkPtr), S(StkPtr), E|Mem|N|CRc|Refs) \
|
||||
O(CallBuiltin, DBuiltin, SUnk, E|Mem|Refs|Er|N|PRc) \
|
||||
O(NativeImpl, ND, C(Func) S(FramePtr), E|Mem|N|Refs) \
|
||||
/* XXX: why does RetCtrl sometimes get PtrToGen */ \
|
||||
@@ -798,6 +799,19 @@ struct BCOffset : IRExtraData {
|
||||
Offset offset;
|
||||
};
|
||||
|
||||
/*
|
||||
* FCallArray offsets
|
||||
*/
|
||||
struct CallArrayData : IRExtraData {
|
||||
explicit CallArrayData(Offset pcOffset, Offset aft)
|
||||
: pc(pcOffset), after(aft) {}
|
||||
|
||||
std::string show() const { return folly::to<std::string>(pc, ", ", after); }
|
||||
|
||||
Offset pc, after;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define X(op, data) \
|
||||
@@ -830,6 +844,7 @@ X(ReDefGeneratorSP, StackOffset);
|
||||
X(DefSP, StackOffset);
|
||||
X(DefInlineFP, BCOffset);
|
||||
X(InlineCreateCont, CreateContData);
|
||||
X(CallArray, CallArrayData);
|
||||
|
||||
#undef X
|
||||
|
||||
|
||||
@@ -1321,7 +1321,11 @@ TranslatorX64::irTranslateFCall(const Tracelet& t,
|
||||
void
|
||||
TranslatorX64::irTranslateFCallArray(const Tracelet& t,
|
||||
const NormalizedInstruction& i) {
|
||||
HHIR_EMIT(FCallArray);
|
||||
const Offset pcOffset = i.offset();
|
||||
SrcKey next = i.next ? i.next->source : t.m_nextSk;
|
||||
const Offset after = next.offset();
|
||||
|
||||
HHIR_EMIT(FCallArray, pcOffset, after);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -376,6 +376,7 @@ void LinearScan::allocRegToInstruction(InstructionList::iterator it) {
|
||||
opc == ReDefSP ||
|
||||
opc == ReDefGeneratorSP ||
|
||||
opc == Call ||
|
||||
opc == CallArray ||
|
||||
opc == SpillStack ||
|
||||
opc == SpillFrame ||
|
||||
opc == ExceptionBarrier ||
|
||||
|
||||
@@ -69,6 +69,18 @@ SSATmp* getStackValue(SSATmp* sp,
|
||||
type);
|
||||
}
|
||||
|
||||
case CallArray:
|
||||
// sp = CallArray(stack)
|
||||
if (index == 0) {
|
||||
// return value from call
|
||||
return nullptr;
|
||||
}
|
||||
spansCall = true;
|
||||
return getStackValue(inst->getSrc(0), // sp == ActRec + array arg
|
||||
index + kNumActRecCells,
|
||||
spansCall,
|
||||
type);
|
||||
|
||||
case Call:
|
||||
// sp = call(actrec, bcoffset, func, args...)
|
||||
if (index == 0) {
|
||||
|
||||
@@ -496,6 +496,15 @@ void TraceBuilder::updateTrackedState(IRInstruction* inst) {
|
||||
killLocals();
|
||||
break;
|
||||
|
||||
case CallArray:
|
||||
m_spValue = inst->getDst();
|
||||
// A CallArray pops the ActRec an array arg and pushes a return value.
|
||||
m_spOffset -= kNumActRecCells;
|
||||
assert(m_spOffset >= 0);
|
||||
killCse();
|
||||
killLocals();
|
||||
break;
|
||||
|
||||
case ContEnter:
|
||||
killCse();
|
||||
killLocals();
|
||||
|
||||
@@ -233,15 +233,15 @@ TCA funcBodyHelper(ActRec* fp) {
|
||||
return tca;
|
||||
}
|
||||
|
||||
void TranslatorX64::fCallArrayHelper(const FCallArrayArgs* args) {
|
||||
void TranslatorX64::fCallArrayHelper(const Offset pcOff, const Offset pcNext) {
|
||||
DECLARE_FRAME_POINTER(framePtr);
|
||||
ActRec* fp = (ActRec*)framePtr->m_savedRbp;
|
||||
|
||||
VMExecutionContext *ec = g_vmContext;
|
||||
ec->m_fp = fp;
|
||||
ec->m_stack.top() = sp;
|
||||
ec->m_pc = curUnit()->at(args->m_pcOff);
|
||||
PC pc = curUnit()->at(args->m_pcNext);
|
||||
ec->m_pc = curUnit()->at(pcOff);
|
||||
PC pc = curUnit()->at(pcNext);
|
||||
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
bool runFunc = ec->doFCallArray(pc);
|
||||
|
||||
@@ -9844,13 +9844,10 @@ void TranslatorX64::translateFCallArray(const Tracelet& t,
|
||||
|
||||
syncOutputs(i);
|
||||
|
||||
FCallArrayArgs* args = m_globalData.alloc<FCallArrayArgs>();
|
||||
emitImmReg(a, (uint64_t)args, argNumToRegName[0]);
|
||||
emitImmReg(a, (uint64_t)i.offset(), argNumToRegName[0]);
|
||||
emitImmReg(a, (uint64_t)after, argNumToRegName[1]);
|
||||
emitCall(a, (TCA)fCallArrayHelper, true);
|
||||
|
||||
args->m_pcOff = i.offset();
|
||||
args->m_pcNext = after;
|
||||
|
||||
if (i.breaksTracelet) {
|
||||
SrcKey fallThru(curFunc(), after);
|
||||
emitBindJmp(fallThru);
|
||||
|
||||
@@ -999,11 +999,7 @@ private:
|
||||
bool m_local;
|
||||
};
|
||||
static void reqLitHelper(const ReqLitStaticArgs* args);
|
||||
struct FCallArrayArgs {
|
||||
Offset m_pcOff;
|
||||
Offset m_pcNext;
|
||||
};
|
||||
static void fCallArrayHelper(const FCallArrayArgs* args);
|
||||
static void fCallArrayHelper(const Offset pcOff, const Offset pcNext);
|
||||
|
||||
TCA getNativeTrampoline(TCA helperAddress);
|
||||
TCA emitNativeTrampoline(TCA helperAddress);
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário