Func* FuncEmitter::create(Unit& unit, PreClass* preClass /* = NULL */) const { bool isGenerated = isdigit(name->data()[0]) || ParserBase::IsClosureName(name->toCppString()); Attr attrs = this->attrs; if (preClass && preClass->attrs() & AttrInterface) { attrs |= AttrAbstract; } if (attrs & AttrPersistent && ((RuntimeOption::EvalJitEnableRenameFunction && !isGenerated) || (!RuntimeOption::RepoAuthoritative && SystemLib::s_inited) || attrs & AttrInterceptable)) { if (attrs & AttrBuiltin) { SystemLib::s_anyNonPersistentBuiltins = true; } attrs = Attr(attrs & ~AttrPersistent); } if (RuntimeOption::EvalJitEnableRenameFunction && !name->empty() && !Func::isSpecial(name) && !isClosureBody) { // intercepted functions need to pass all args through // to the interceptee attrs |= AttrMayUseVV; } if (isVariadic()) { attrs |= AttrVariadicParam; } if (!containsCalls) { attrs |= AttrPhpLeafFn; } assert(!m_pce == !preClass); Func* f = m_ue.newFunc(this, unit, preClass, line1, line2, base, past, name, attrs, top, docComment, params.size(), isClosureBody); f->shared()->m_info = m_info; f->shared()->m_returnType = returnType; std::vector<Func::ParamInfo> fParams; for (unsigned i = 0; i < params.size(); ++i) { Func::ParamInfo pi = params[i]; f->appendParam(params[i].byRef, pi, fParams); } f->shared()->m_localNames.create(m_localNames); f->shared()->m_numLocals = m_numLocals; f->shared()->m_numIterators = m_numIterators; f->m_maxStackCells = maxStackCells; f->shared()->m_staticVars = staticVars; f->shared()->m_ehtab = ehtab; f->shared()->m_fpitab = fpitab; f->shared()->m_isClosureBody = isClosureBody; f->shared()->m_isAsync = isAsync; f->shared()->m_isGenerator = isGenerator; f->shared()->m_isPairGenerator = isPairGenerator; f->shared()->m_userAttributes = userAttributes; f->shared()->m_builtinFuncPtr = m_builtinFuncPtr; f->shared()->m_nativeFuncPtr = m_nativeFuncPtr; f->shared()->m_retTypeConstraint = retTypeConstraint; f->shared()->m_retUserType = retUserType; f->shared()->m_originalFilename = originalFilename; f->shared()->m_isGenerated = isGenerated; f->finishedEmittingParams(fParams); if (attrs & AttrNative) { auto nif = Native::GetBuiltinFunction(name, m_pce ? m_pce->name() : nullptr, f->isStatic()); if (nif) { Attr dummy = AttrNone; int nativeAttrs = parseNativeAttributes(dummy); if (nativeAttrs & Native::AttrZendCompat) { f->shared()->m_nativeFuncPtr = nif; f->shared()->m_builtinFuncPtr = zend_wrap_func; } else { if (parseNativeAttributes(dummy) & Native::AttrActRec) { f->shared()->m_builtinFuncPtr = nif; f->shared()->m_nativeFuncPtr = nullptr; } else { f->shared()->m_nativeFuncPtr = nif; f->shared()->m_builtinFuncPtr = m_pce ? Native::methodWrapper : Native::functionWrapper; } } } else { f->shared()->m_builtinFuncPtr = Native::unimplementedWrapper; } } return f; }