Translate FPushFuncU
We were punting on this, but it's a pretty easy translation, and it makes calling functions from inside namespaces much faster. Closes #814
Esse commit está contido em:
@@ -2248,6 +2248,43 @@ void CodeGenerator::cgLdFuncCached(IRInstruction* inst) {
|
||||
});
|
||||
}
|
||||
|
||||
void CodeGenerator::cgLdFuncCachedU(IRInstruction* inst) {
|
||||
SSATmp* dst = inst->dst();
|
||||
SSATmp* methodName = inst->src(0);
|
||||
SSATmp* fallbackName = inst->src(1);
|
||||
|
||||
// allocate both cache handles
|
||||
const StringData* name = methodName->getValStr();
|
||||
CacheHandle ch = TargetCache::allocFixedFunction(name);
|
||||
size_t funcCacheOff = ch + offsetof(FixedFuncCache, m_func);
|
||||
|
||||
const StringData* fallback = fallbackName->getValStr();
|
||||
CacheHandle fch = TargetCache::allocFixedFunction(fallback);
|
||||
size_t fallbackCacheOff = fch + offsetof(FixedFuncCache, m_func);
|
||||
|
||||
// check the first cache handle, then the fallback
|
||||
auto dstReg = m_regs[dst].reg();
|
||||
Label end;
|
||||
if (dstReg == InvalidReg) {
|
||||
m_as. cmpq (0, rVmTl[funcCacheOff]);
|
||||
m_as. jcc8 (CC_NZ, end);
|
||||
m_as. cmpq (0, rVmTl[fallbackCacheOff]);
|
||||
} else {
|
||||
m_as. loadq(rVmTl[funcCacheOff], dstReg);
|
||||
m_as. testq(dstReg, dstReg);
|
||||
m_as. jcc8 (CC_NZ, end);
|
||||
m_as. loadq(rVmTl[fallbackCacheOff], dstReg);
|
||||
m_as. testq(dstReg, dstReg);
|
||||
}
|
||||
|
||||
// finally, jump to native call in astubs if neither hits
|
||||
unlikelyIfBlock(CC_Z, [&] (Asm& a) {
|
||||
// same helper as LdFuncCached
|
||||
cgCallNative(a, inst);
|
||||
});
|
||||
asm_label(m_as, end);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgLdFuncCachedSafe(IRInstruction* inst) {
|
||||
cgLdFuncCachedCommon(inst);
|
||||
if (Block* taken = inst->taken()) {
|
||||
|
||||
@@ -1965,35 +1965,48 @@ void HhbcTranslator::emitCreateCl(int32_t numParams, int32_t funNameStrId) {
|
||||
push(closure);
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitFPushFuncD(int32_t numParams, int32_t funcId) {
|
||||
const NamedEntityPair& nep = lookupNamedEntityPairId(funcId);
|
||||
const StringData* name = nep.first;
|
||||
const Func* func = Unit::lookupFunc(nep.second);
|
||||
if (!func) {
|
||||
// function lookup failed so just do the same as FPushFunc
|
||||
emitFPushFunc(numParams, cns(name));
|
||||
return;
|
||||
void HhbcTranslator::emitFPushFuncCommon(const Func* func,
|
||||
const StringData* name,
|
||||
const StringData* fallback,
|
||||
int32_t numParams) {
|
||||
if (func) {
|
||||
func->validate();
|
||||
if (func->isNameBindingImmutable(curUnit())) {
|
||||
emitFPushActRec(cns(func),
|
||||
m_tb->genDefInitNull(),
|
||||
numParams,
|
||||
nullptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
func->validate();
|
||||
|
||||
const bool immutable = func->isNameBindingImmutable(curUnit());
|
||||
|
||||
IRTrace* catchTrace = nullptr;
|
||||
if (!immutable) {
|
||||
catchTrace = getCatchTrace(); // LdFuncCached can throw
|
||||
}
|
||||
SSATmp* ssaFunc = immutable ? cns(func)
|
||||
: gen(LdFuncCached, catchTrace, cns(name));
|
||||
// LdFuncCached can throw
|
||||
IRTrace* catchTrace = getCatchTrace();
|
||||
SSATmp* ssaFunc = fallback
|
||||
? gen(LdFuncCachedU, catchTrace, cns(name), cns(fallback))
|
||||
: gen(LdFuncCached, catchTrace, cns(name));
|
||||
emitFPushActRec(ssaFunc,
|
||||
m_tb->genDefInitNull(),
|
||||
numParams,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitFPushFuncD(int32_t numParams, int32_t funcId) {
|
||||
const NamedEntityPair& nep = lookupNamedEntityPairId(funcId);
|
||||
const StringData* name = nep.first;
|
||||
const Func* func = Unit::lookupFunc(nep.second);
|
||||
emitFPushFuncCommon(func, name, nullptr, numParams);
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitFPushFuncU(int32_t numParams,
|
||||
int32_t funcId,
|
||||
int32_t fallbackFuncId) {
|
||||
PUNT(FPushFuncU);
|
||||
const NamedEntityPair& nep = lookupNamedEntityPairId(funcId);
|
||||
const StringData* name = nep.first;
|
||||
const Func* func = Unit::lookupFunc(nep.second);
|
||||
const NamedEntityPair& fallbackNep = lookupNamedEntityPairId(fallbackFuncId);
|
||||
const StringData* fallbackName = fallbackNep.first;
|
||||
emitFPushFuncCommon(func, name, fallbackName, numParams);
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitFPushFunc(int32_t numParams) {
|
||||
|
||||
@@ -255,6 +255,10 @@ struct HhbcTranslator {
|
||||
const Func* func, int numArgs);
|
||||
void emitFPushActRec(SSATmp* func, SSATmp* objOrClass, int32_t numArgs,
|
||||
const StringData* invName = nullptr);
|
||||
void emitFPushFuncCommon(const Func* func,
|
||||
const StringData* name,
|
||||
const StringData* fallback,
|
||||
int32_t numParams);
|
||||
void emitFPushFuncD(int32_t numParams, int32_t funcId);
|
||||
void emitFPushFuncU(int32_t numParams,
|
||||
int32_t funcId,
|
||||
|
||||
@@ -910,6 +910,11 @@ Translator::translateFPushFuncD(const NormalizedInstruction& i) {
|
||||
HHIR_EMIT(FPushFuncD, (i.imm[0].u_IVA), (i.imm[1].u_SA));
|
||||
}
|
||||
|
||||
void
|
||||
Translator::translateFPushFuncU(const NormalizedInstruction& i) {
|
||||
HHIR_EMIT(FPushFuncU, i.imm[0].u_IVA, i.imm[1].u_SA, i.imm[2].u_SA);
|
||||
}
|
||||
|
||||
void
|
||||
Translator::translateFPassCOp(const NormalizedInstruction& i) {
|
||||
auto const op = i.op();
|
||||
|
||||
@@ -359,6 +359,7 @@ O(LdGblAddr, D(PtrToGen), S(Str), N) \
|
||||
O(LdObjClass, D(Cls), S(Obj), C) \
|
||||
O(LdFunc, D(Func), S(Str), E|N|CRc|Er) \
|
||||
O(LdFuncCached, D(Func), CStr, N|C|E|Er) \
|
||||
O(LdFuncCachedU, D(Func), CStr CStr, N|C|E|Er) \
|
||||
O(LdFuncCachedSafe, D(Func), CStr, C) \
|
||||
O(LdARFuncPtr, D(Func), S(StkPtr,FramePtr) C(Int), C) \
|
||||
O(LdSSwitchDestFast, D(TCA), S(Gen), N) \
|
||||
|
||||
@@ -158,6 +158,8 @@ static CallMap s_callMap({
|
||||
{{SSA, 0}, {SSA, 1}, {TV, 2}, {SSA, 3}}},
|
||||
{LdFuncCached, (TCA)FixedFuncCache::lookupUnknownFunc, DSSA, SSync,
|
||||
{{SSA, 0}}},
|
||||
{LdFuncCachedU, (TCA)FixedFuncCache::lookupUnknownFunc, DSSA, SSync,
|
||||
{{SSA, 0}}},
|
||||
{CreateCl, (TCA)createClHelper, DSSA, SSync,
|
||||
{{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}},
|
||||
{ArrayIdx, {FSSA, 0}, DTV, SSync,
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
CASE(UnsetM) \
|
||||
CASE(BindM) \
|
||||
CASE(FPushFuncD) \
|
||||
CASE(FPushFuncU) \
|
||||
CASE(FPushFunc) \
|
||||
CASE(FPushClsMethodD) \
|
||||
CASE(FPushClsMethodF) \
|
||||
|
||||
@@ -2036,7 +2036,7 @@ void Translator::getOutputs(/*inout*/ Tracelet& t,
|
||||
// Pseudo-outputs that affect translator state
|
||||
case FStack: {
|
||||
currentStackOffset += kNumActRecCells;
|
||||
if (op == OpFPushFuncD) {
|
||||
if (op == OpFPushFuncD || op == OpFPushFuncU) {
|
||||
const Unit& cu = *ni->unit();
|
||||
Id funcId = ni->imm[1].u_SA;
|
||||
const NamedEntityPair &nep = cu.lookupNamedEntityPairId(funcId);
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário