void IRTranslator::translateBranchOp(const NormalizedInstruction& i) { auto const op = i.op(); assert(op == OpJmpZ || op == OpJmpNZ); Offset takenOffset = i.offset() + i.imm[0].u_BA; Offset fallthruOffset = i.offset() + instrLen((Op*)(i.pc())); auto jmpFlags = instrJmpFlags(i); if (i.nextOffset == takenOffset) { always_assert(RuntimeOption::EvalJitPGORegionSelector == "hottrace"); // invert the branch if (op == OpJmpZ) { HHIR_EMIT(JmpNZ, fallthruOffset, jmpFlags); } else { HHIR_EMIT(JmpZ, fallthruOffset, jmpFlags); } return; } if (op == OpJmpZ) { HHIR_EMIT(JmpZ, takenOffset, jmpFlags); } else { HHIR_EMIT(JmpNZ, takenOffset, jmpFlags); } }
void IRTranslator::translateMIterInit(const NormalizedInstruction& i) { HHIR_EMIT(MIterInit, i.imm[0].u_IVA, i.offset() + i.imm[1].u_BA, i.imm[2].u_IVA, instrJmpFlags(i)); }
void IRTranslator::translateWIterNext(const NormalizedInstruction& i) { bool invertCond = false; Offset targetOffset = getBranchTarget(i, invertCond); HHIR_EMIT(WIterNext, i.imm[0].u_IVA, targetOffset, i.imm[2].u_IVA, invertCond, instrJmpFlags(i)); }
void implCondJmp(HTS& env, Offset taken, bool negate, SSATmp* src) { auto const flags = instrJmpFlags(*env.currentNormalizedInstruction); if (flags & JmpFlagEndsRegion) { spillStack(env); } if ((flags & JmpFlagNextIsMerge) != 0) { prepareForHHBCMergePoint(env); } auto const target = getBlock(env, taken); assertx(target != nullptr); auto const boolSrc = gen(env, ConvCellToBool, src); gen(env, DecRef, src); gen(env, negate ? JmpZero : JmpNZero, target, boolSrc); }
void implCondJmp(HTS& env, Offset taken, bool negate, SSATmp* src) { auto const flags = instrJmpFlags(*env.currentNormalizedInstruction); if (flags & JmpFlagEndsRegion) { spillStack(env); } if (env.mode == IRGenMode::CFG && (flags & JmpFlagNextIsMerge)) { spillStack(env); bccfMergeSPHack(env); } auto const target = getBlock(env, taken); assert(target != nullptr); auto const boolSrc = gen(env, ConvCellToBool, src); gen(env, DecRef, src); gen(env, negate ? JmpZero : JmpNZero, target, boolSrc); }
void implCondJmp(HTS& env, Offset taken, bool negate, SSATmp* src) { auto const flags = instrJmpFlags(*env.currentNormalizedInstruction); if (flags & JmpFlagEndsRegion) { spillStack(env); } if (env.mode == IRGenMode::CFG && (flags & JmpFlagNextIsMerge)) { // Before jumping to a merge point we have to ensure that the // stack pointer is sync'ed. Without an ExceptionBarrier the // SpillStack can be removed by DCE (especially since merge points // start with a DefSP to block SP-chain walking). gen(env, ExceptionBarrier, spillStack(env)); } auto const target = getBlock(env, taken); assert(target != nullptr); auto const boolSrc = gen(env, ConvCellToBool, src); gen(env, DecRef, src); gen(env, negate ? JmpZero : JmpNZero, target, boolSrc); }
void emitDecodeCufIter(IRGS& env, int32_t iterId, Offset relOffset) { auto const src = popC(env); auto const type = src->type(); if (type.subtypeOfAny(Type::Arr, Type::Str, Type::Obj)) { auto const res = gen( env, DecodeCufIter, Type::Bool, IterId(iterId), src, fp(env) ); gen(env, DecRef, src); implCondJmp(env, bcOff(env) + relOffset, true, res); } else { gen(env, DecRef, src); jmpImpl(env, bcOff(env) + relOffset, instrJmpFlags(*env.currentNormalizedInstruction)); } }
void emitJmpNS(HTS& env, Offset relOffset) { jmpImpl(env, bcOff(env) + relOffset, instrJmpFlags(*env.currentNormalizedInstruction)); }
void emitJmp(HTS& env, Offset relOffset) { surpriseCheck(env, relOffset); auto const offset = bcOff(env) + relOffset; jmpImpl(env, offset, instrJmpFlags(*env.currentNormalizedInstruction)); }
void IRTranslator::translateDecodeCufIter(const NormalizedInstruction& i) { HHIR_EMIT(DecodeCufIter, i.imm[0].u_IVA, i.offset() + i.imm[1].u_BA, instrJmpFlags(i)); }
void IRTranslator::translateJmpNS(const NormalizedInstruction& i) { HHIR_EMIT(JmpNS, i.offset() + i.imm[0].u_BA, instrJmpFlags(i)); }