From b94ab7709f69cafd296d9027975ba1f324a590cd Mon Sep 17 00:00:00 2001 From: Eric Caruso Date: Thu, 11 Jul 2013 13:18:30 -0700 Subject: [PATCH] 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 --- hphp/runtime/vm/jit/code-gen.cpp | 37 +++++++++++++++++++ hphp/runtime/vm/jit/hhbc-translator.cpp | 49 ++++++++++++++++--------- hphp/runtime/vm/jit/hhbc-translator.h | 4 ++ hphp/runtime/vm/jit/ir-translator.cpp | 5 +++ hphp/runtime/vm/jit/ir.h | 1 + hphp/runtime/vm/jit/native-calls.cpp | 2 + hphp/runtime/vm/jit/translator-instrs.h | 1 + hphp/runtime/vm/jit/translator.cpp | 2 +- 8 files changed, 82 insertions(+), 19 deletions(-) diff --git a/hphp/runtime/vm/jit/code-gen.cpp b/hphp/runtime/vm/jit/code-gen.cpp index 3d2bd5c46..e6bcd4a04 100644 --- a/hphp/runtime/vm/jit/code-gen.cpp +++ b/hphp/runtime/vm/jit/code-gen.cpp @@ -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()) { diff --git a/hphp/runtime/vm/jit/hhbc-translator.cpp b/hphp/runtime/vm/jit/hhbc-translator.cpp index 858b254dc..67b9d0990 100644 --- a/hphp/runtime/vm/jit/hhbc-translator.cpp +++ b/hphp/runtime/vm/jit/hhbc-translator.cpp @@ -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) { diff --git a/hphp/runtime/vm/jit/hhbc-translator.h b/hphp/runtime/vm/jit/hhbc-translator.h index aa07e4e58..42d75c41d 100644 --- a/hphp/runtime/vm/jit/hhbc-translator.h +++ b/hphp/runtime/vm/jit/hhbc-translator.h @@ -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, diff --git a/hphp/runtime/vm/jit/ir-translator.cpp b/hphp/runtime/vm/jit/ir-translator.cpp index 2bfbaa1a7..40a46746d 100644 --- a/hphp/runtime/vm/jit/ir-translator.cpp +++ b/hphp/runtime/vm/jit/ir-translator.cpp @@ -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(); diff --git a/hphp/runtime/vm/jit/ir.h b/hphp/runtime/vm/jit/ir.h index 3eede77b7..eb8dd2145 100644 --- a/hphp/runtime/vm/jit/ir.h +++ b/hphp/runtime/vm/jit/ir.h @@ -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) \ diff --git a/hphp/runtime/vm/jit/native-calls.cpp b/hphp/runtime/vm/jit/native-calls.cpp index 85a3f67a5..e9a6f2a2a 100644 --- a/hphp/runtime/vm/jit/native-calls.cpp +++ b/hphp/runtime/vm/jit/native-calls.cpp @@ -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, diff --git a/hphp/runtime/vm/jit/translator-instrs.h b/hphp/runtime/vm/jit/translator-instrs.h index aa81249be..0774595dd 100644 --- a/hphp/runtime/vm/jit/translator-instrs.h +++ b/hphp/runtime/vm/jit/translator-instrs.h @@ -88,6 +88,7 @@ CASE(UnsetM) \ CASE(BindM) \ CASE(FPushFuncD) \ + CASE(FPushFuncU) \ CASE(FPushFunc) \ CASE(FPushClsMethodD) \ CASE(FPushClsMethodF) \ diff --git a/hphp/runtime/vm/jit/translator.cpp b/hphp/runtime/vm/jit/translator.cpp index 8e7b3578e..5838cfa0c 100644 --- a/hphp/runtime/vm/jit/translator.cpp +++ b/hphp/runtime/vm/jit/translator.cpp @@ -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);