void IRTranslator::translateInstr(const NormalizedInstruction& ni) { auto& ht = m_hhbcTrans; ht.setBcOff(ni.source.offset(), ni.breaksTracelet && !m_hhbcTrans.isInlining()); FTRACE(1, "\n{:-^60}\n", folly::format("Translating {}: {} with stack:\n{}", ni.offset(), ni.toString(), ht.showStack())); // When profiling, we disable type predictions to avoid side exits assert(IMPLIES(JIT::tx->mode() == TransProfile, !ni.outputPredicted)); if (ni.guardedThis) { // Task #2067635: This should really generate an AssertThis ht.setThisAvailable(); } if (moduleEnabled(HPHP::Trace::stats, 2)) { ht.emitIncStat(Stats::opcodeToIRPreStatCounter(ni.op()), 1, false); } if (RuntimeOption::EnableInstructionCounts || moduleEnabled(HPHP::Trace::stats, 3)) { // If the instruction takes a slow exit, the exit trace will // decrement the post counter for that opcode. ht.emitIncStat(Stats::opcodeToIRPostStatCounter(ni.op()), 1, true); } ht.emitRB(RBTypeBytecodeStart, ni.source, 2); auto pc = reinterpret_cast<const Op*>(ni.pc()); for (auto i = 0, num = instrNumPops(pc); i < num; ++i) { auto const type = flavorToType(instrInputFlavor(pc, i)); if (type != Type::Gen) m_hhbcTrans.assertTypeStack(i, type); } if (RuntimeOption::EvalHHIRGenerateAsserts >= 2) { ht.emitDbgAssertRetAddr(); } if (instrMustInterp(ni) || ni.interp) { interpretInstr(ni); } else { translateInstrWork(ni); } passPredictedAndInferredTypes(ni); }
void initInstructions(Trace* trace, IRInstruction::List& wl) { IRInstruction::List instructions = trace->getInstructionList(); IRInstruction::Iterator it; bool unreachable = false; TRACE(5, "DCE:vvvvvvvvvvvvvvvvvvvv\n"); for (it = instructions.begin(); it != instructions.end(); it++) { IRInstruction* inst = *it; ASSERT(inst->getParent() == trace); Simplifier::copyProp(inst); // if this is a load that does not generate a guard, then get rid // of its label so that its not an essential control-flow // instruction if (isUnguardedLoad(inst)) { // LdStack and LdLoc instructions that produce generic types // and LdStack instruction that produce Cell types will not // generate guards, so remove the label from this instruction so // that its no longer an essential control-flow instruction inst->setLabel(NULL); } Opcode opc = inst->getOpcode(); // decref of anything that isn't ref counted is a nop if ((opc == DecRef || opc == DecRefNZ) && !isRefCounted(inst->getSrc(0))) { inst->setId(DEAD); continue; } if (!unreachable && inst->isControlFlowInstruction()) { // mark the destination label so that the destination trace // is marked reachable inst->getLabel()->setId(LIVE); } if (!unreachable && isEssential(inst)) { inst->setId(LIVE); wl.push_back(inst); } else { if (moduleEnabled(HPHP::Trace::hhir, 5)) { std::ostringstream ss1; inst->printSrcs(ss1); TRACE(5, "DCE: %s\n", ss1.str().c_str()); std::ostringstream ss2; inst->print(ss2); TRACE(5, "DCE: %s\n", ss2.str().c_str()); } inst->setId(DEAD); } if (inst->getOpcode() == Jmp_) { unreachable = true; } } TRACE(5, "DCE:^^^^^^^^^^^^^^^^^^^^\n"); }