Esempio n. 1
0
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 (isThisAvailable()) {
    auto const thiss = gen(LdThis, m_fpValue);
    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 &&
        callerHasValueAvailable(thisInst->src(0))) {
      gen(DecRefNZ, thiss);
      inst->convertToNop();
      return nullptr;
    }

    assert(inst->src(0) == m_fpValue);
    gen(DecRef, thiss);
    inst->convertToNop();
    return nullptr;
  }

  return nullptr;
}
Esempio n. 2
0
SSATmp* TraceBuilder::preOptimizeLdThis(IRInstruction* inst) {
  if (isThisAvailable()) {
    auto fpInst = inst->src(0)->inst();
    if (fpInst->op() == DefInlineFP) {
      if (!m_frameSpansCall) { // check that we haven't nuked the SSATmp
        auto spInst = fpInst->src(0)->inst();
        if (spInst->op() == SpillFrame && spInst->src(3)->isA(Type::Obj)) {
          return spInst->src(3);
        }
      }
    }
    inst->setTaken(nullptr);
  }
  return nullptr;
}
Esempio n. 3
0
SSATmp* TraceBuilder::preOptimizeLdCtx(IRInstruction* inst) {
  if (isThisAvailable()) return gen(LdThis, m_fpValue);
  return nullptr;
}
Esempio n. 4
0
SSATmp* TraceBuilder::preOptimizeLdThis(IRInstruction* inst) {
  if (isThisAvailable()) inst->setTaken(nullptr);
  return nullptr;
}