SSATmp* TraceBuilder::preOptimizeDecRefThis(IRInstruction* inst) { /* * If $this is available, convert to an instruction sequence that * doesn't need to test if it's already live. */ if (thisAvailable()) { auto const thiss = gen(LdThis, m_state.fp()); auto const thisInst = thiss->inst(); /* * DecRef optimization for $this in an inlined frame: if a caller * local contains the $this, we know it can't go to zero and can * switch DecRef to DecRefNZ. * * It's ok not to do DecRefThis (which normally nulls out the ActRec * $this), because there is still a reference to it in the caller * frame, so debug_backtrace() can't see a non-live pointer value. */ if (thisInst->op() == IncRef && m_state.callerHasValueAvailable(thisInst->src(0))) { gen(DecRefNZ, thiss); inst->convertToNop(); return nullptr; } assert(inst->src(0) == m_state.fp()); gen(DecRef, thiss); inst->convertToNop(); return nullptr; } return nullptr; }
SSATmp* IRBuilder::preOptimizeDecRefThis(IRInstruction* inst) { /* * If $this is available, convert to an instruction sequence that * doesn't need to test if it's already live. */ if (thisAvailable()) { auto const thiss = gen(LdThis, m_state.fp()); gen(DecRef, thiss); inst->convertToNop(); } return nullptr; }