From c6ca429a5e9a6a86526ff779df6f17a0ad0eb018 Mon Sep 17 00:00:00 2001 From: Paul Bissonnette Date: Mon, 10 Jun 2013 12:52:54 -0700 Subject: [PATCH] Changed lookupIR in targetcache.cpp to not require a VMRegAnchor Updated lookupIR functions in StaticMethodCache and StaticMethodFCache to accept the FP as an argument. --- hphp/doc/ir.specification | 8 ++++-- hphp/runtime/base/execution_context.h | 1 + hphp/runtime/vm/bytecode.cpp | 5 ++-- hphp/runtime/vm/jit/codegen.cpp | 25 ++++++++++++------ hphp/runtime/vm/jit/hhbctranslator.cpp | 8 ++++-- hphp/runtime/vm/jit/ir.h | 9 +++++-- hphp/runtime/vm/jit/targetcache.cpp | 36 +++++--------------------- hphp/runtime/vm/jit/targetcache.h | 7 +++-- hphp/runtime/vm/jit/translator.cpp | 3 ++- 9 files changed, 52 insertions(+), 50 deletions(-) diff --git a/hphp/doc/ir.specification b/hphp/doc/ir.specification index 1a2bd3a7d..0f8ade512 100644 --- a/hphp/doc/ir.specification +++ b/hphp/doc/ir.specification @@ -782,14 +782,15 @@ D:T = LookupClsCns undefined constant error if autoload cannot define the constant. D:FuncCtx = LdClsMethodFCache S0:ConstStr S1:ConstStr - S2:{Obj|Cls|Ctx} L:Label + S2:{Obj|Cls|Ctx} S3:FramePtr L:Label Loads from the MethodFCache a pointer to the callee function and the context (ActRec's m_this/m_cls slot) into D. S0 and S1 hold the names of the callee's class and method, respectively. S2 is the current context. This instruction loads the corresponding entry in the MethodFCache if needed. In case the given method is not found, - control is transferred to label L. + control is transferred to label L. The current frame pointer is + passed in S3. D:Ctx = GetCtxFwdCall S0:Ctx S1:Func @@ -798,6 +799,7 @@ D:Ctx = GetCtxFwdCall S0:Ctx S1:Func S0 and returns it. If S0 is a Cctx, this opcode returns S0. D:FuncCls = LdClsMethodCache S0:ConstStr S1:ConstStr S2:ConstNamedEntity* + S3:FramePtr S4:StkPtr Lookup a function and class in the class method targetcache. The sources to this instruction are: @@ -805,6 +807,8 @@ D:FuncCls = LdClsMethodCache S0:ConstStr S1:ConstStr S2:ConstNamedEntity* S0 - class name S1 - method name S2 - the NamedEntity* for the class + S3 - the current frame pointer + S4 - the current stack pointer D:Func = LdClsMethod S0:Cls S1:ConstInt diff --git a/hphp/runtime/base/execution_context.h b/hphp/runtime/base/execution_context.h index 6407d23f5..8ba7f9a05 100644 --- a/hphp/runtime/base/execution_context.h +++ b/hphp/runtime/base/execution_context.h @@ -530,6 +530,7 @@ public: const HPHP::Class* cls, const StringData* methodName, ObjectData* this_, + ActRec* vmfp, bool raise = false); MethodLookup::LookupResult lookupCtorMethod(const HPHP::Func*& f, const HPHP::Class* cls, diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index ff531fa84..96fe030dc 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -1108,8 +1108,9 @@ VMExecutionContext::lookupClsMethod(const Func*& f, const Class* cls, const StringData* methodName, ObjectData* obj, + ActRec* vmfp, bool raise /* = false */) { - Class* ctx = arGetContextClass(getFP()); + Class* ctx = arGetContextClass(vmfp); f = lookupMethodCtx(cls, methodName, ctx, ClsMethod, false); if (!f) { if (obj && obj->instanceof(cls)) { @@ -5347,7 +5348,7 @@ void VMExecutionContext::pushClsMethodImpl(Class* cls, ObjectData* obj, int numArgs) { const Func* f; - LookupResult res = lookupClsMethod(f, cls, name, obj, true); + LookupResult res = lookupClsMethod(f, cls, name, obj, getFP(), true); if (res == MethodFoundNoThis || res == MagicCallStaticFound) { obj = nullptr; } else { diff --git a/hphp/runtime/vm/jit/codegen.cpp b/hphp/runtime/vm/jit/codegen.cpp index c53e044b5..f605d03fc 100644 --- a/hphp/runtime/vm/jit/codegen.cpp +++ b/hphp/runtime/vm/jit/codegen.cpp @@ -4367,6 +4367,8 @@ void CodeGenerator::cgLdClsMethodCache(IRInstruction* inst) { SSATmp* className = inst->src(0); SSATmp* methodName = inst->src(1); SSATmp* baseClass = inst->src(2); + SSATmp* fp = inst->src(3); + SSATmp* sp = inst->src(4); Block* label = inst->taken(); // Stats::emitInc(a, Stats::TgtCache_StaticMethodHit); @@ -4391,17 +4393,22 @@ void CodeGenerator::cgLdClsMethodCache(IRInstruction* inst) { // handle case where method is not entered in the cache unlikelyIfBlock(CC_E, [&] (Asm& a) { if (false) { // typecheck - const UNUSED Func* f = StaticMethodCache::lookupIR(ch, ne, cls, method); + UNUSED TypedValue* fake_fp = nullptr; + UNUSED TypedValue* fake_sp = nullptr; + const UNUSED Func* f = StaticMethodCache::lookupIR(ch, ne, cls, method, + fake_fp, fake_sp); } // can raise an error if class is undefined cgCallHelper(a, (TCA)StaticMethodCache::lookupIR, funcDestReg, kSyncPoint, - ArgGroup(m_regs).imm(ch) // Handle ch - .immPtr(ne) // NamedEntity* np.second - .immPtr(cls) // className - .immPtr(method) // methodName + ArgGroup(m_regs).imm(ch) // Handle ch + .immPtr(ne) // NamedEntity* np.second + .immPtr(cls) // className + .immPtr(method) // methodName + .reg(m_regs[fp].reg()) // frame pointer + .reg(m_regs[sp].reg()) // stack pointer ); // recordInstrCall is done in cgCallHelper a.testq(funcDestReg, funcDestReg); @@ -4487,6 +4494,7 @@ void CodeGenerator::cgLdClsMethodFCache(IRInstruction* inst) { const Class* cls = inst->src(0)->getValClass(); const StringData* methName = inst->src(1)->getValStr(); SSATmp* srcCtxTmp = inst->src(2); + SSATmp* fp = inst->src(3); PhysReg srcCtxReg = m_regs[srcCtxTmp].reg(0); Block* exitLabel = inst->taken(); const StringData* clsName = cls->name(); @@ -4502,8 +4510,8 @@ void CodeGenerator::cgLdClsMethodFCache(IRInstruction* inst) { // Handle case where method is not entered in the cache unlikelyIfBlock(CC_E, [&] (Asm& a) { - const Func* (*lookup)(CacheHandle, const Class*, const StringData*) = - StaticMethodFCache::lookupIR; + const Func* (*lookup)(CacheHandle, const Class*, + const StringData*, TypedValue*) = StaticMethodFCache::lookupIR; // preserve destCtxReg across the call since it wouldn't be otherwise RegSet toSave = m_state.liveRegs[inst] | RegSet(destCtxReg); cgCallHelper(a, Transl::CppCall((TCA)lookup), @@ -4511,7 +4519,8 @@ void CodeGenerator::cgLdClsMethodFCache(IRInstruction* inst) { kSyncPoint, ArgGroup(m_regs).imm(ch) .immPtr(cls) - .immPtr(methName), + .immPtr(methName) + .reg(m_regs[fp].reg()), toSave); // If entry found in target cache, jump back to m_as. // Otherwise, bail to exit label diff --git a/hphp/runtime/vm/jit/hhbctranslator.cpp b/hphp/runtime/vm/jit/hhbctranslator.cpp index da55c3d00..62ab8462e 100644 --- a/hphp/runtime/vm/jit/hhbctranslator.cpp +++ b/hphp/runtime/vm/jit/hhbctranslator.cpp @@ -1947,13 +1947,16 @@ void HhbcTranslator::emitFPushClsMethodD(int32_t numParams, func && magicCall ? methodName : nullptr); } else { // lookup static method & class in the target cache + SSATmp* stack = spillStack(); IRTrace* exitTrace = getExitSlowTrace(); SSATmp* funcClassTmp = gen(LdClsMethodCache, exitTrace, cns(className), cns(methodName), - cns(np.second)); + cns(np.second), + m_tb->fp(), + stack); emitFPushActRec(funcClassTmp, m_tb->genDefInitNull(), numParams, @@ -1988,7 +1991,8 @@ void HhbcTranslator::emitFPushClsMethodF(int32_t numParams, SSATmp* funcCtxTmp = gen(LdClsMethodFCache, exitBlock, cns(cls), cns(methName), - curCtxTmp); + curCtxTmp, + m_tb->fp()); emitFPushActRec(funcCtxTmp, m_tb->genDefInitNull(), numParams, diff --git a/hphp/runtime/vm/jit/ir.h b/hphp/runtime/vm/jit/ir.h index 054e30975..6b504c43f 100644 --- a/hphp/runtime/vm/jit/ir.h +++ b/hphp/runtime/vm/jit/ir.h @@ -308,8 +308,13 @@ O(LdCns, DParam, CStr, NF) \ O(LookupCns, DParam, CStr, E|Refs|Er|N|Mem) \ O(LdClsMethodCache, D(FuncCls), C(Str) \ C(Str) \ - C(NamedEntity), N|C|E|Refs|Er|Mem) \ -O(LdClsMethodFCache, D(FuncCtx), C(Cls) CStr S(Obj,Cls,Ctx), N|C|E|Er) \ + C(NamedEntity) \ + S(FramePtr) \ + S(StkPtr), N|C|E|Refs|Er|Mem) \ +O(LdClsMethodFCache, D(FuncCtx), C(Cls) \ + CStr \ + S(Obj,Cls,Ctx) \ + S(FramePtr), N|C|E|Er) \ O(GetCtxFwdCall, D(Ctx), S(Ctx) S(Func), C) \ O(LdClsMethod, D(Func), S(Cls) C(Int), C) \ O(LdPropAddr, D(PtrToGen), S(Obj) C(Int), C) \ diff --git a/hphp/runtime/vm/jit/targetcache.cpp b/hphp/runtime/vm/jit/targetcache.cpp index 6a9898b5b..00b2afc3f 100644 --- a/hphp/runtime/vm/jit/targetcache.cpp +++ b/hphp/runtime/vm/jit/targetcache.cpp @@ -1008,16 +1008,16 @@ StaticMethodFCache::alloc(const StringData* clsName, const Func* StaticMethodCache::lookupIR(Handle handle, const NamedEntity *ne, const StringData* clsName, - const StringData* methName) { + const StringData* methName, TypedValue* vmfp, + TypedValue* vmsp) { StaticMethodCache* thiz = static_cast (handleToPtr(handle)); Stats::inc(Stats::TgtCache_StaticMethodMiss); Stats::inc(Stats::TgtCache_StaticMethodHit, -1); TRACE(1, "miss %s :: %s caller %p\n", clsName->data(), methName->data(), __builtin_return_address(0)); - VMRegAnchor _; // needed for lookupClsMethod. - ActRec* ar = reinterpret_cast(vmsp() - kNumActRecCells); + ActRec* ar = reinterpret_cast(vmsp - kNumActRecCells); const Func* f; VMExecutionContext* ec = g_vmContext; const Class* cls = Unit::loadClass(ne, clsName); @@ -1028,6 +1028,7 @@ StaticMethodCache::lookupIR(Handle handle, const NamedEntity *ne, nullptr, // there may be an active this, // but we can just fall through // in that case. + (ActRec*)vmfp, false /*raise*/); if (LIKELY(res == MethodFoundNoThis && !f->isAbstract() && @@ -1042,9 +1043,6 @@ StaticMethodCache::lookupIR(Handle handle, const NamedEntity *ne, return f; } assert(res != MethodFoundWithThis); // Not possible: no this supplied. - // We've already sync'ed regs; this is some hard case, we might as well - // just let the interpreter handle this entirely. - assert(*vmpc() == OpFPushClsMethodD); // Indicate to the IR that it should take even slower path return nullptr; @@ -1073,6 +1071,7 @@ StaticMethodCache::lookup(Handle handle, const NamedEntity *ne, nullptr, // there may be an active this, // but we can just fall through // in that case. + ec->getFP(), false /*raise*/); if (LIKELY(res == MethodFoundNoThis && !f->isAbstract() && @@ -1106,18 +1105,18 @@ StaticMethodCache::lookup(Handle handle, const NamedEntity *ne, const Func* StaticMethodFCache::lookupIR(Handle handle, const Class* cls, - const StringData* methName) { + const StringData* methName, TypedValue* vmfp) { assert(cls); StaticMethodFCache* thiz = static_cast (handleToPtr(handle)); Stats::inc(Stats::TgtCache_StaticMethodFMiss); Stats::inc(Stats::TgtCache_StaticMethodFHit, -1); - VMRegAnchor _; // needed for lookupClsMethod. const Func* f; VMExecutionContext* ec = g_vmContext; LookupResult res = ec->lookupClsMethod(f, cls, methName, nullptr, + (ActRec*)vmfp, false /*raise*/); assert(res != MethodFoundWithThis); // Not possible: no this supplied. if (LIKELY(res == MethodFoundNoThis && !f->isAbstract())) { @@ -1143,25 +1142,4 @@ StaticMethodFCache::lookupIR(Handle handle, const Class* cls, return nullptr; } -const Func* -StaticMethodFCache::lookup(Handle handle, const Class* cls, - const StringData* methName) { - const Func* f = lookupIR(handle, cls, methName); - if (f) return f; - - VMRegAnchor _; // needed for opFPushClsMethodF - - // We've already sync'ed regs; this is some hard case, we might as well - // just let the interpreter handle this entirely. - assert(*vmpc() == OpFPushClsMethodF); - Stats::inc(Stats::Instr_TC, -1); - Stats::inc(Stats::Instr_InterpOneFPushClsMethodF); - g_vmContext->opFPushClsMethodF(); - - // We already did all the work so tell our caller to do nothing. - TRACE(1, "miss staticfcache %s :: %s -> intractable null\n", - cls->name()->data(), methName->data()); - return nullptr; -} - } } } // HPHP::Transl::TargetCache diff --git a/hphp/runtime/vm/jit/targetcache.h b/hphp/runtime/vm/jit/targetcache.h index d73f70b11..424d62112 100644 --- a/hphp/runtime/vm/jit/targetcache.h +++ b/hphp/runtime/vm/jit/targetcache.h @@ -243,7 +243,8 @@ struct StaticMethodCache { const char* ctxName); static const Func* lookupIR(CacheHandle chand, const NamedEntity* ne, const StringData* cls, - const StringData* meth); + const StringData* meth, TypedValue* vmfp, + TypedValue* vmsp); static const Func* lookup(CacheHandle chand, const NamedEntity* ne, const StringData* cls, const StringData* meth); @@ -255,10 +256,8 @@ struct StaticMethodFCache { static CacheHandle alloc(const StringData* cls, const StringData* meth, const char* ctxName); - static const Func* lookup(CacheHandle chand, const Class* cls, - const StringData* meth); static const Func* lookupIR(CacheHandle chand, const Class* cls, - const StringData* meth); + const StringData* meth, TypedValue* vmfp); }; typedef Cache diff --git a/hphp/runtime/vm/jit/translator.cpp b/hphp/runtime/vm/jit/translator.cpp index 2a1c66aec..ee0fe90df 100644 --- a/hphp/runtime/vm/jit/translator.cpp +++ b/hphp/runtime/vm/jit/translator.cpp @@ -4077,7 +4077,8 @@ const Func* lookupImmutableMethod(const Class* cls, const StringData* name, const Func* func; MethodLookup::LookupResult res = staticLookup ? - g_vmContext->lookupClsMethod(func, cls, name, 0, false) : + g_vmContext->lookupClsMethod(func, cls, name, 0, + g_vmContext->getFP(), false) : g_vmContext->lookupObjMethod(func, cls, name, false); if (res == MethodLookup::MethodNotFound) return nullptr;