void IRTranslator::translateInstr(const NormalizedInstruction& ni) { auto& ht = m_hhbcTrans; ht.setBcOff(ni.source.offset(), ni.endsRegion && !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(mcg->tx().mode() == TransKind::Profile, !ni.outputPredicted)); ht.emitRB(RBTypeBytecodeStart, ni.source, 2); ht.emitIncStat(Stats::Instr_TC, 1, false); 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 (isAlwaysNop(ni.op())) { // Do nothing } else if (instrMustInterp(ni) || ni.interp) { interpretInstr(ni); } else { translateInstrWork(ni); } }
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() == TransKind::Profile, !ni.outputPredicted)); if (ni.guardedThis) { // Task #2067635: This should really generate an AssertThis ht.setThisAvailable(); } 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 translateInstr( IRGS& irgs, const NormalizedInstruction& ni, bool checkOuterTypeOnly, bool firstInst ) { irgen::prepareForNextHHBC( irgs, &ni, ni.source, ni.endsRegion && !irgen::isInlining(irgs) ); const Func* builtinFunc = nullptr; if (ni.op() == OpFCallBuiltin) { auto str = ni.m_unit->lookupLitstrId(ni.imm[2].u_SA); builtinFunc = Unit::lookupFunc(str); } auto pc = ni.pc(); for (auto i = 0, num = instrNumPops(pc); i < num; ++i) { auto const type = !builtinFunc ? flavorToType(instrInputFlavor(pc, i)) : builtinFunc->byRef(num - i - 1) ? TGen : TCell; // TODO(#5706706): want to use assertTypeLocation, but Location::Stack // is a little unsure of itself. irgen::assertTypeStack(irgs, BCSPOffset{i}, type); } FTRACE(1, "\nTranslating {}: {} with state:\n{}\n", ni.offset(), ni, show(irgs)); irgen::ringbufferEntry(irgs, Trace::RBTypeBytecodeStart, ni.source, 2); irgen::emitIncStat(irgs, Stats::Instr_TC, 1); if (Stats::enableInstrCount()) { irgen::emitIncStat(irgs, Stats::opToTranslStat(ni.op()), 1); } if (Trace::moduleEnabledRelease(Trace::llvm_count, 1) || RuntimeOption::EvalJitLLVMCounters) { irgen::gen(irgs, CountBytecode); } if (isAlwaysNop(ni.op())) return; if (ni.interp || RuntimeOption::EvalJitAlwaysInterpOne) { irgen::interpOne(irgs, ni); return; } translateDispatch(irgs, ni); FTRACE(3, "\nTranslated {}: {} with state:\n{}\n", ni.offset(), ni, show(irgs)); }