void emitContEnter(IRGS& env) { auto const returnOffset = nextBcOff(env); assertx(curClass(env)); assertx(curClass(env)->classof(c_AsyncGenerator::classof()) || curClass(env)->classof(c_Generator::classof())); assertx(curFunc(env)->contains(returnOffset)); auto isAsync = curClass(env)->classof(c_AsyncGenerator::classof()); // Load generator's FP and resume address. auto const genObj = ldThis(env); auto const genFp = gen(env, LdContActRec, IsAsyncData(isAsync), genObj); auto resumeAddr = gen(env, LdContResumeAddr, IsAsyncData(isAsync), genObj); // Make sure function enter hook is called if needed. auto const exitSlow = makeExitSlow(env); gen(env, CheckSurpriseFlags, exitSlow, fp(env)); // Exit to interpreter if resume address is not known. resumeAddr = gen(env, CheckNonNull, exitSlow, resumeAddr); spillStack(env); env.irb->exceptionStackBoundary(); auto returnBcOffset = returnOffset - curFunc(env)->base(); gen( env, ContEnter, ContEnterData { offsetFromIRSP(env, BCSPOffset{0}), returnBcOffset }, sp(env), fp(env), genFp, resumeAddr ); }
void emitContEnter(HTS& env) { auto const returnOffset = nextBcOff(env); assert(curClass(env)); assert(curClass(env)->classof(c_AsyncGenerator::classof()) || curClass(env)->classof(c_Generator::classof())); assert(curFunc(env)->contains(returnOffset)); // Load generator's FP and resume address. auto const genObj = ldThis(env); auto const genFp = gen(env, LdContActRec, genObj); auto resumeAddr = gen(env, LdContResumeAddr, genObj); // Make sure function enter hook is called if needed. auto const exitSlow = makeExitSlow(env); gen(env, CheckSurpriseFlags, exitSlow); // Exit to interpreter if resume address is not known. resumeAddr = gen(env, CheckNonNull, exitSlow, resumeAddr); // Sync stack. auto const stack = spillStack(env); // Enter generator. auto returnBcOffset = returnOffset - curFunc(env)->base(); gen(env, ContEnter, stack, fp(env), genFp, resumeAddr, cns(env, returnBcOffset)); }
void emitContValid(IRGS& env) { assertx(curClass(env)); assertx(curClass(env)->classof(c_AsyncGenerator::classof()) || curClass(env)->classof(c_Generator::classof())); auto const cont = ldThis(env); push(env, gen(env, ContValid, IsAsyncData(curClass(env)->classof(c_AsyncGenerator::classof())), cont)); }
void emitContCurrent(HTS& env) { assert(curClass(env)); auto const cont = ldThis(env); gen(env, ContStartedCheck, makeExitSlow(env), cont); auto const offset = cns(env, offsetof(c_Generator, m_value)); auto const value = gen(env, LdContField, Type::Cell, cont, offset); pushIncRef(env, value); }
void emitContCheck(HTS& env, int32_t checkStarted) { assert(curClass(env)); assert(curClass(env)->classof(c_AsyncGenerator::classof()) || curClass(env)->classof(c_Generator::classof())); auto const cont = ldThis(env); gen(env, ContPreNext, makeExitSlow(env), cont, cns(env, static_cast<bool>(checkStarted))); }
void emitContCurrent(IRGS& env) { assertx(curClass(env)); auto const cont = ldThis(env); gen(env, ContStartedCheck, IsAsyncData(false), makeExitSlow(env), cont); auto const offset = cns(env, offsetof(Generator, m_value) - Generator::objectOff()); auto const value = gen(env, LdContField, TCell, cont, offset); pushIncRef(env, value); }
void emitContValid(HTS& env) { assert(curClass(env)); auto const cont = ldThis(env); push(env, gen(env, ContValid, cont)); }