Eliminate IncRef/DecRef pair when a method returns $this

Instead of generating IR like:

   t1:Obj = LdThis t0:StkPtr
   t2:Obj = IncRef t1:Obj
   ...
   DecRef t1:Obj
   RetVal t2:Obj
   ...

This diff changes HhbcTranslator to produce:

   t1:Obj = LdThis t0:StkPtr
   t2:Obj = IncRef t1:Obj
   ...
   DecRefNZ t2:Obj
   RetVal t1:Obj
   ...

This enables the ref-counting optimization to kick in.
Esse commit está contido em:
ottoni
2013-03-20 19:17:18 -07:00
commit de Sara Golemon
commit 56cfa9c73c
@@ -1629,9 +1629,6 @@ void HhbcTranslator::emitRet(Type type, bool freeInline) {
m_tb->genReleaseVVOrExit(getExitSlowTrace());
}
SSATmp* retVal = pop(type);
if (mayHaveThis) {
m_tb->genDecRefThis();
}
SSATmp* sp;
if (freeInline) {
@@ -1642,14 +1639,26 @@ void HhbcTranslator::emitRet(Type type, bool freeInline) {
* IncRef/DecRef pair in the main trace.
*/
SSATmp* retValSrcLoc = nullptr;
Opcode retValSrcOpc = Nop; // Nop flags the ref-count opti is impossible
IRInstruction* retValSrcInstr = retVal->getInstruction();
if (retValSrcInstr->getOpcode() == IncRef) {
retValSrcLoc = retValSrcInstr->getSrc(0);
if (retValSrcLoc->getInstruction()->getOpcode() != LdLoc) {
retValSrcOpc = retValSrcLoc->getInstruction()->getOpcode();
if (retValSrcOpc != LdLoc && retValSrcOpc != LdThis) {
retValSrcLoc = nullptr;
retValSrcOpc = Nop;
}
}
int retValLocId = retValSrcLoc ?
if (mayHaveThis) {
if (retValSrcLoc && retValSrcOpc == LdThis) {
m_tb->genDecRef(retVal);
} else {
m_tb->genDecRefThis();
}
}
int retValLocId = (retValSrcLoc && retValSrcOpc == LdLoc) ?
retValSrcLoc->getInstruction()->getExtra<LocalId>()->locId : -1;
for (int id = curFunc->numLocals() - 1; id >= 0; --id) {
/*
@@ -1665,6 +1674,9 @@ void HhbcTranslator::emitRet(Type type, bool freeInline) {
m_tb->genRetVal(retValSrcLoc ? retValSrcLoc : retVal);
sp = m_tb->genRetAdjustStack();
} else {
if (mayHaveThis) {
m_tb->genDecRefThis();
}
sp = m_tb->genGenericRetDecRefs(retVal, curFunc->numLocals());
m_tb->genRetVal(retVal);
}