diff --git a/hphp/runtime/vm/translator/hopt/codegen.cpp b/hphp/runtime/vm/translator/hopt/codegen.cpp index e14b094c4..180c8cb24 100644 --- a/hphp/runtime/vm/translator/hopt/codegen.cpp +++ b/hphp/runtime/vm/translator/hopt/codegen.cpp @@ -4651,27 +4651,40 @@ void CodeGenerator::cgAKExists(IRInstruction* inst) { ArgGroup(m_regs).ssa(key).ssa(arr)); } -HOT_FUNC_VM static TypedValue* ldGblAddrHelper(StringData* name) { - return g_vmContext->m_globalVarEnv->lookup(name); -} - -HOT_FUNC_VM static TypedValue* ldGblAddrDefHelper(StringData* name) { - TypedValue* r = g_vmContext->m_globalVarEnv->lookupAdd(name); - decRefStr(name); - return r; -} - void CodeGenerator::cgLdGblAddr(IRInstruction* inst) { auto dstReg = m_regs[inst->getDst()].getReg(); - cgCallHelper(m_as, (TCA)ldGblAddrHelper, dstReg, kNoSyncPoint, - ArgGroup(m_regs).ssa(inst->getSrc(0))); + auto rEC = rScratch; + // TODO(#2384005): If we create separate opcodes for loading the VM + // context and the global variable environment we may find some CSE + // opportunities that aren't currently exploited. + emitGetGContext(m_as, rEC); + m_as.loadq(rEC[offsetof(VMExecutionContext, m_globalVarEnv)], rEC); + ArgGroup args = ArgGroup(m_regs) + .reg(rEC) + .ssa(inst->getSrc(0)); + cgCallHelper(m_as, + (TCA)getMethodPtr(&VarEnv::lookup), + dstReg, + kNoSyncPoint, + args); m_as.testq(dstReg, dstReg); emitFwdJcc(CC_Z, inst->getTaken()); } void CodeGenerator::cgLdGblAddrDef(IRInstruction* inst) { - cgCallHelper(m_as, (TCA)ldGblAddrDefHelper, inst->getDst(), kNoSyncPoint, - ArgGroup(m_regs).ssa(inst->getSrc(0))); + auto dstReg = m_regs[inst->getDst()].getReg(); + auto rEC = rScratch; + // TODO(#2384005): see LdGblAddr + emitGetGContext(m_as, rEC); + m_as.loadq(rEC[offsetof(VMExecutionContext, m_globalVarEnv)], rEC); + ArgGroup args = ArgGroup(m_regs) + .reg(rEC) + .ssa(inst->getSrc(0)); + cgCallHelper(m_as, + (TCA)getMethodPtr(&VarEnv::lookupAdd), + dstReg, + kNoSyncPoint, + args); } void CodeGenerator::cgJmpZeroHelper(IRInstruction* inst, diff --git a/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp b/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp index ac8d184e3..80e39da88 100644 --- a/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp +++ b/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp @@ -1200,7 +1200,10 @@ SSATmp* HhbcTranslator::emitLdGblAddr(const StringData* gblName, Block* block) { } SSATmp* HhbcTranslator::emitLdGblAddrDef(const StringData* gblName) { - return gen(LdGblAddrDef, getStrName(gblName)); + SSATmp* name = getStrName(gblName); + SSATmp* addr = gen(LdGblAddrDef, name); + gen(DecRef, name); + return addr; } void HhbcTranslator::emitIncDecS(bool pre, bool inc) { diff --git a/hphp/runtime/vm/translator/translator-x64.cpp b/hphp/runtime/vm/translator/translator-x64.cpp index 68f95a0db..3b30d8b02 100644 --- a/hphp/runtime/vm/translator/translator-x64.cpp +++ b/hphp/runtime/vm/translator/translator-x64.cpp @@ -891,7 +891,7 @@ void TranslatorX64::emitIncRefGeneric(PhysReg base, int disp) { emitIncRefGenericRegSafe(base, disp, r(tmpReg)); } -static void emitGetGContext(X64Assembler& a, PhysReg dest) { +void emitGetGContext(X64Assembler& a, PhysReg dest) { emitTLSLoad(a, g_context, dest); } diff --git a/hphp/runtime/vm/translator/translator-x64.h b/hphp/runtime/vm/translator/translator-x64.h index 556e85ead..cbbdd3409 100644 --- a/hphp/runtime/vm/translator/translator-x64.h +++ b/hphp/runtime/vm/translator/translator-x64.h @@ -1186,6 +1186,8 @@ bool classIsUnique(const Class* cls); bool classIsUniqueOrCtxParent(const Class* cls); bool classIsUniqueNormalClass(const Class* cls); +void emitGetGContext(X64Assembler& a, PhysReg dest); + // SpaceRecorder is used in translator-x64.cpp and in hopt/irtranslator.cpp // RAII logger for TC space consumption. struct SpaceRecorder {