RFC: Pass the assembler to use to unlikelyIfBlock

In tx64, a common bug (for me) was to accidentally type "a."
instead of "astubs." when writing code inside an UnlikelyIfBlock,
since your fingers get used to the former.  More generally, it seems
like we should abstract the target assembler from actual codegen in
most cases (we currently really do this in the IR only insofar as
"m_a" might be pointing at "m_astubs", but it's only safe sometimes).

This is just an RFC, because otoh there are less significant chunks of
direct assembler code in codegen.cpp, and maybe it doesn't matter much
unless we also switch "m_as" to be "a".  Thoughts?
Esse commit está contido em:
jdelong
2013-04-05 19:54:30 -07:00
commit de Sara Golemon
commit 96d22113c9
2 arquivos alterados com 35 adições e 33 exclusões
+31 -31
Ver Arquivo
@@ -1886,9 +1886,9 @@ void CodeGenerator::cgLdFixedFunc(IRInstruction* inst) {
m_as. testq (dstReg, dstReg);
}
// jz off to the helper call in astubs
unlikelyIfBlock(CC_Z, [&] {
unlikelyIfBlock(CC_Z, [&] (Asm& a) {
// this helper tries the autoload map, and fatals on failure
cgCallHelper(m_astubs, (TCA)FixedFuncCache::lookupUnknownFunc,
cgCallHelper(a, (TCA)FixedFuncCache::lookupUnknownFunc,
dstReg, kSyncPoint, ArgGroup().immPtr(name));
});
}
@@ -2846,10 +2846,10 @@ void CodeGenerator::cgDecRefStaticType(Type type,
// release call
if (genZeroCheck && exit == nullptr) {
// Emit jump to m_astubs (to call release) if count got down to zero
unlikelyIfBlock(CC_Z, [&] {
if (slowPathWork) slowPathWork(m_astubs);
unlikelyIfBlock(CC_Z, [&] (Asm& a) {
if (slowPathWork) slowPathWork(a);
// Emit the call to release in m_astubs
cgCallHelper(m_astubs, m_tx64->getDtorCall(type.toDataType()),
cgCallHelper(a, m_tx64->getDtorCall(type.toDataType()),
InvalidReg, InvalidReg, kSyncPoint,
ArgGroup().reg(dataReg));
});
@@ -2881,9 +2881,9 @@ void CodeGenerator::cgDecRefDynamicType(PhysReg typeReg,
// If not exiting on count down to zero, emit the zero-check and release call
if (genZeroCheck && exit == nullptr) {
// Emit jump to m_astubs (to call release) if count got down to zero
unlikelyIfBlock(CC_Z, [&] {
unlikelyIfBlock(CC_Z, [&] (Asm& a) {
// Emit call to release in m_astubs
cgCallHelper(m_astubs, getDtorTyped(), InvalidReg, kSyncPoint,
cgCallHelper(a, getDtorTyped(), InvalidReg, kSyncPoint,
ArgGroup().reg(dataReg).reg(typeReg));
});
}
@@ -2944,10 +2944,10 @@ void CodeGenerator::cgDecRefDynamicTypeMem(PhysReg baseReg,
// If not exiting on count down to zero, emit the zero-check and release call
if (exit == nullptr) {
// Emit jump to m_astubs (to call release) if count got down to zero
unlikelyIfBlock(CC_Z, [&] {
unlikelyIfBlock(CC_Z, [&] (Asm& a) {
// Emit call to release in m_astubs
m_astubs.lea(baseReg[offset], scratchReg);
cgCallHelper(m_astubs, getDtorGeneric(), InvalidReg, kSyncPoint,
a.lea(baseReg[offset], scratchReg);
cgCallHelper(a, getDtorGeneric(), InvalidReg, kSyncPoint,
ArgGroup().reg(scratchReg));
});
}
@@ -3947,12 +3947,12 @@ void CodeGenerator::cgLdClsMethodCache(IRInstruction* inst) {
m_as.testq(funcDestReg, funcDestReg);
// May have retrieved a NULL from the cache
// handle case where method is not entered in the cache
unlikelyIfBlock(CC_E, [&] {
unlikelyIfBlock(CC_E, [&] (Asm& a) {
if (false) { // typecheck
const UNUSED Func* f = StaticMethodCache::lookupIR(ch, ne, cls, method);
}
// can raise an error if class is undefined
cgCallHelper(m_astubs,
cgCallHelper(a,
(TCA)StaticMethodCache::lookupIR,
funcDestReg,
kSyncPoint,
@@ -3962,10 +3962,10 @@ void CodeGenerator::cgLdClsMethodCache(IRInstruction* inst) {
.immPtr(method) // methodName
);
// recordInstrCall is done in cgCallHelper
m_astubs.testq(funcDestReg, funcDestReg);
m_astubs.loadq(rVmTl[ch + offsetof_cls], classDestReg);
a.testq(funcDestReg, funcDestReg);
a.loadq(rVmTl[ch + offsetof_cls], classDestReg);
// if StaticMethodCache::lookupIR() returned NULL, jmp to label
emitFwdJcc(m_astubs, CC_Z, label);
emitFwdJcc(a, CC_Z, label);
});
}
@@ -4058,13 +4058,13 @@ void CodeGenerator::cgLdClsMethodFCache(IRInstruction* inst) {
Label End;
// Handle case where method is not entered in the cache
unlikelyIfBlock(CC_E, [&] {
unlikelyIfBlock(CC_E, [&] (Asm& a) {
if (false) { // typecheck
const UNUSED Func* f = StaticMethodFCache::lookupIR(ch, cls, methName);
}
// preserve destCtxReg across the call since it wouldn't be otherwise
inst->setLiveRegs(inst->getLiveRegs().add(destCtxReg));
cgCallHelper(m_astubs,
cgCallHelper(a,
(TCA)StaticMethodFCache::lookupIR,
funcDestReg,
kSyncPoint,
@@ -4073,8 +4073,8 @@ void CodeGenerator::cgLdClsMethodFCache(IRInstruction* inst) {
.immPtr(methName));
// If entry found in target cache, jump back to m_as.
// Otherwise, bail to exit label
m_astubs.testq(funcDestReg, funcDestReg);
emitFwdJcc(m_astubs, CC_Z, exitLabel);
a.testq(funcDestReg, funcDestReg);
emitFwdJcc(a, CC_Z, exitLabel);
});
auto t = srcCtxTmp->getType();
@@ -4129,16 +4129,16 @@ void CodeGenerator::cgLdClsPropAddrCached(IRInstruction* inst) {
// Could be optimized to cmp against zero when !label && dstReg == InvalidReg
m_as.loadq(rVmTl[ch], tmpReg);
m_as.testq(tmpReg, tmpReg);
unlikelyIfBlock(CC_E, [&] {
cgCallHelper(m_astubs,
unlikelyIfBlock(CC_E, [&] (Asm& a) {
cgCallHelper(a,
target ? (TCA)SPropCache::lookupIR<false>
: (TCA)SPropCache::lookupIR<true>, // raise on error
tmpReg,
kSyncPoint, // could re-enter to initialize properties
ArgGroup().imm(ch).ssa(cls).ssa(propName).ssa(cxt));
if (target) {
m_astubs.testq(tmpReg, tmpReg);
emitFwdJcc(m_astubs, CC_Z, target);
a.testq(tmpReg, tmpReg);
emitFwdJcc(a, CC_Z, target);
}
});
if (dstReg != InvalidReg) {
@@ -4189,10 +4189,10 @@ void CodeGenerator::cgLdClsCached(IRInstruction* inst) {
m_as. loadq (rVmTl[ch], dstReg);
m_as. testq (dstReg, dstReg);
}
unlikelyIfBlock(CC_E, [&] {
unlikelyIfBlock(CC_E, [&] (Asm& a) {
// Passing only two arguments to lookupKnownClass, since the
// third is ignored in the checkOnly==false case.
cgCallHelper(m_astubs,
cgCallHelper(a,
(TCA)TargetCache::lookupKnownClass<false>,
dst,
kSyncPoint,
@@ -4464,11 +4464,11 @@ void CodeGenerator::cgReleaseVVOrExit(IRInstruction* inst) {
auto const rFp = inst->getSrc(0)->getReg();
m_as. cmpq (0, rFp[AROFF(m_varEnv)]);
unlikelyIfBlock(CC_NZ, [&] {
m_astubs. testl (ActRec::kExtraArgsBit, rFp[AROFF(m_varEnv)]);
emitFwdJcc(m_astubs, CC_Z, label);
unlikelyIfBlock(CC_NZ, [&] (Asm& a) {
a. testl (ActRec::kExtraArgsBit, rFp[AROFF(m_varEnv)]);
emitFwdJcc(a, CC_Z, label);
cgCallHelper(
m_astubs,
a,
TCA(static_cast<void (*)(ActRec*)>(ExtraArgs::deallocate)),
nullptr,
kSyncPoint,
@@ -4657,8 +4657,8 @@ void CodeGenerator::emitContVarEnvHelperCall(SSATmp* fp, TCA helper) {
m_as. loadq (fp->getReg()[AROFF(m_varEnv)], scratch);
m_as. testq (scratch, scratch);
unlikelyIfBlock(CC_NZ, [&] {
cgCallHelper(m_astubs, helper, InvalidReg, kNoSyncPoint,
unlikelyIfBlock(CC_NZ, [&] (Asm& a) {
cgCallHelper(a, helper, InvalidReg, kNoSyncPoint,
ArgGroup().ssa(fp));
});
}
+4 -2
Ver Arquivo
@@ -282,19 +282,21 @@ private:
* Generate an if-block that branches around some unlikely code, handling
* the cases when a == astubs and a != astubs. cc is the branch condition
* to run the unlikely block.
*
* Passes the proper assembler to use to the unlikely function.
*/
template <class Block>
void unlikelyIfBlock(ConditionCode cc, Block unlikely) {
if (&m_as == &m_astubs) {
Label done;
m_as.jcc(ccNegate(cc), done);
unlikely();
unlikely(m_as);
asm_label(m_as, done);
} else {
Label unlikelyLabel, done;
m_as.jcc(cc, unlikelyLabel);
asm_label(m_astubs, unlikelyLabel);
unlikely();
unlikely(m_astubs);
m_astubs.jmp(done);
asm_label(m_as, done);
}