Changed lookupIR in targetcache.cpp to not require a VMRegAnchor
Updated lookupIR functions in StaticMethodCache and StaticMethodFCache to accept the FP as an argument.
Esse commit está contido em:
@@ -782,14 +782,15 @@ D:T = LookupClsCns<T,className,constName>
|
||||
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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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<StaticMethodCache*>
|
||||
(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<ActRec*>(vmsp() - kNumActRecCells);
|
||||
ActRec* ar = reinterpret_cast<ActRec*>(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<StaticMethodFCache*>
|
||||
(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
|
||||
|
||||
@@ -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<const StringData*, const Func*, StringData*, NSDynFunction>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário