bool breaksRegion(SrcKey sk) { switch (sk.op()) { case Op::SSwitch: case Op::CreateCont: case Op::Yield: case Op::YieldK: case Op::RetC: case Op::RetV: case Op::Exit: case Op::Fatal: case Op::Throw: case Op::Unwind: case Op::Eval: case Op::NativeImpl: return true; case Op::Await: // We break regions at resumed Await instructions, to avoid // duplicating the translation of the resumed SrcKey after the // Await. return sk.resumed(); default: return false; } }
bool InliningDecider::canInlineAt(SrcKey callSK, const Func* callee) const { if (m_disabled || !callee || !RuntimeOption::EvalHHIREnableGenTimeInlining || RuntimeOption::EvalJitEnableRenameFunction || callee->attrs() & AttrInterceptable) { return false; } // We can only inline at normal FCalls. if (callSK.op() != Op::FCall && callSK.op() != Op::FCallD) { return false; } // Don't inline from resumed functions. The inlining mechanism doesn't have // support for these---it has no way to redefine stack pointers relative to // the frame pointer, because in a resumed function the frame pointer points // into the heap instead of into the eval stack. if (callSK.resumed()) return false; // TODO(#4238160): Inlining into pseudomain callsites is still buggy. if (callSK.func()->isPseudoMain()) return false; if (!isCalleeInlinable(callSK, callee) || !checkNumArgs(callSK, callee)) { return false; } return true; }
bool InliningDecider::canInlineAt(SrcKey callSK, const Func* callee) const { if (!callee || !RuntimeOption::EvalHHIREnableGenTimeInlining || RuntimeOption::EvalJitEnableRenameFunction || callee->attrs() & AttrInterceptable) { return false; } if (callee->cls()) { if (!classHasPersistentRDS(callee->cls())) { // if the callee's class is not persistent, its still ok // to use it if we're jitting into a method of a subclass auto ctx = callSK.func()->cls(); if (!ctx || !ctx->classof(callee->cls())) { return false; } } } else { auto const handle = callee->funcHandle(); if (handle == rds::kInvalidHandle || !rds::isPersistentHandle(handle)) { // if the callee isn't persistent, its still ok to // use it if its defined at the top level in the same // unit as the caller if (callee->unit() != callSK.unit() || !callee->top()) { return false; } } } // If inlining was disabled... don't inline. if (m_disabled) return false; // TODO(#3331014): We have this hack until more ARM codegen is working. if (arch() == Arch::ARM) return false; // We can only inline at normal FCalls. if (callSK.op() != Op::FCall && callSK.op() != Op::FCallD) { return false; } // Don't inline from resumed functions. The inlining mechanism doesn't have // support for these---it has no way to redefine stack pointers relative to // the frame pointer, because in a resumed function the frame pointer points // into the heap instead of into the eval stack. if (callSK.resumed()) return false; // TODO(#4238160): Inlining into pseudomain callsites is still buggy. if (callSK.func()->isPseudoMain()) return false; if (!isCalleeInlinable(callSK, callee) || !checkNumArgs(callSK, callee)) { return false; } return true; }
/* * Check that we don't have any missing or extra arguments. */ bool checkNumArgs(SrcKey callSK, const Func* callee, Annotations& annotations) { assertx(callSK.op() == Op::FCall); assertx(callee); auto refuse = [&] (const char* why) { return traceRefusal(callSK, callee, why, annotations); }; auto pc = callSK.pc(); auto const fca = getImm(pc, 0).u_FCA; auto const numParams = callee->numParams(); if (fca.numArgs > numParams) { return refuse("callee called with too many arguments"); } if (fca.hasUnpack) { return refuse("callee called with variadic arguments"); } if (fca.numRets != 1) { return refuse("callee with multiple returns"); } // It's okay if we passed fewer arguments than there are parameters as long // as the gap can be filled in by DV funclets. for (auto i = fca.numArgs; i < numParams; ++i) { auto const& param = callee->params()[i]; if (!param.hasDefaultValue() && (i < numParams - 1 || !callee->hasVariadicCaptureParam())) { return refuse("callee called with too few arguments"); } } return true; }
bool InliningDecider::canInlineAt(SrcKey callSK, const Func* callee, const RegionDesc& region) const { if (!RuntimeOption::RepoAuthoritative || !RuntimeOption::EvalHHIREnableGenTimeInlining) { return false; } // If inlining was disabled... don't inline. if (m_disabled) return false; // TODO(#3331014): We have this hack until more ARM codegen is working. if (arch() == Arch::ARM) return false; // We can only inline at normal FCalls. if (callSK.op() != Op::FCall && callSK.op() != Op::FCallD) { return false; } // Don't inline from resumed functions. The inlining mechanism doesn't have // support for these---it has no way to redefine stack pointers relative to // the frame pointer, because in a resumed function the frame pointer points // into the heap instead of into the eval stack. if (callSK.resumed()) return false; // TODO(#4238160): Inlining into pseudomain callsites is still buggy. if (callSK.func()->isPseudoMain()) return false; if (!isCalleeInlinable(callSK, callee) || !checkNumArgs(callSK, callee) || !checkFPIRegion(callSK, callee, region)) { return false; } return true; }