bool AliasManager::optimize(AnalysisResultPtr ar, MethodStatementPtr m) { m_arp = ar; m_variables = ar->getScope()->getVariables(); if (!m_variables->isPseudoMainTable()) { m_variables->clearUsed(); } if (ExpressionListPtr pPtr = m->getParams()) { ExpressionList ¶ms = *pPtr; for (int i = params.getCount(); i--; ) { ParameterExpressionPtr p = spc(ParameterExpression, params[i]); AliasInfo &ai = m_aliasInfo[p->getName()]; if (p->isRef()) { ai.setIsRefTo(); } } } collectAliasInfoRecur(m->getStmts()); for (AliasInfoMap::iterator it = m_aliasInfo.begin(), end = m_aliasInfo.end(); it != end; ++it) { if (m_variables->isGlobal(it->first) || m_variables->isStatic(it->first)) { it->second.setIsGlobal(); } } canonicalizeRecur(m->getStmts()); return m_changed; }
void FunctionScope::init(AnalysisResultConstPtr ar) { m_dynamicInvoke = false; if (isNamed("__autoload")) { setVolatile(); } // FileScope's flags are from parser, but VariableTable has more flags // coming from type inference phase. So we are tranferring these flags // just for better modularization between FileScope and VariableTable. if (m_attribute & FileScope::ContainsDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsDynamicVariable); } if (m_attribute & FileScope::ContainsLDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsLDynamicVariable); } if (m_attribute & FileScope::ContainsExtract) { m_variables->setAttribute(VariableTable::ContainsExtract); } if (m_attribute & FileScope::ContainsAssert) { m_variables->setAttribute(VariableTable::ContainsAssert); } if (m_attribute & FileScope::ContainsCompact) { m_variables->setAttribute(VariableTable::ContainsCompact); } if (m_attribute & FileScope::ContainsUnset) { m_variables->setAttribute(VariableTable::ContainsUnset); } if (m_attribute & FileScope::ContainsGetDefinedVars) { m_variables->setAttribute(VariableTable::ContainsGetDefinedVars); } if (m_stmt && Option::AllVolatile && !m_pseudoMain && !m_method) { m_volatile = true; } if (!m_method && Option::DynamicInvokeFunctions.find(m_scopeName) != Option::DynamicInvokeFunctions.end()) { setDynamicInvoke(); } if (m_modifiers) { m_virtual = m_modifiers->isAbstract(); } if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); StatementListPtr stmts = stmt->getStmts(); if (stmts) { for (int i = 0; i < stmts->getCount(); i++) { StatementPtr stmt = (*stmts)[i]; stmt->setFileLevel(); if (stmt->is(Statement::KindOfExpStatement)) { ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt); ExpressionPtr exp = expStmt->getExpression(); exp->setTopLevel(); } } } } }
bool FunctionScope::hasImpl() const { if (!isUserFunction()) { return !isAbstract(); } if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); return stmt->getStmts() != nullptr; } return false; }
ExpressionPtr FunctionCall::inliner(AnalysisResultConstPtr ar, ExpressionPtr obj, std::string localThis) { FunctionScopePtr fs = getFunctionScope(); if (m_noInline || !fs || fs == m_funcScope || !m_funcScope->getStmt()) { return ExpressionPtr(); } BlockScope::s_jobStateMutex.lock(); if (m_funcScope->getMark() == BlockScope::MarkProcessing) { fs->setForceRerun(true); BlockScope::s_jobStateMutex.unlock(); return ExpressionPtr(); } ReadLock lock(m_funcScope->getInlineMutex()); BlockScope::s_jobStateMutex.unlock(); if (!m_funcScope->getInlineAsExpr()) { return ExpressionPtr(); } if (m_funcScope->getInlineSameContext() && m_funcScope->getContainingClass() && m_funcScope->getContainingClass() != getClassScope()) { /* The function contains a context sensitive construct such as call_user_func (context sensitive because it could call array('parent', 'foo')) so its not safe to inline it into a different context. */ return ExpressionPtr(); } MethodStatementPtr m (dynamic_pointer_cast<MethodStatement>(m_funcScope->getStmt())); VariableTablePtr vt = fs->getVariables(); int nAct = m_params ? m_params->getCount() : 0; int nMax = m_funcScope->getMaxParamCount(); if (nAct < m_funcScope->getMinParamCount() || !m->getStmts()) { return ExpressionPtr(); } InlineCloneInfo info(m_funcScope); info.elist = ExpressionListPtr(new ExpressionList( getScope(), getLocation(), ExpressionList::ListKindWrapped)); std::ostringstream oss; oss << fs->nextInlineIndex() << "_" << m_name << "_"; std::string prefix = oss.str(); if (obj) { info.callWithThis = true; if (!obj->isThis()) { SimpleVariablePtr var (new SimpleVariable(getScope(), obj->getLocation(), prefix + "this")); var->updateSymbol(SimpleVariablePtr()); var->getSymbol()->setHidden(); var->getSymbol()->setUsed(); var->getSymbol()->setReferenced(); AssignmentExpressionPtr ae (new AssignmentExpression(getScope(), obj->getLocation(), var, obj, false)); info.elist->addElement(ae); info.sepm[var->getName()] = var; info.localThis = var->getName(); } } else { if (m_classScope) { if (!m_funcScope->isStatic()) { ClassScopeRawPtr oCls = getOriginalClass(); FunctionScopeRawPtr oFunc = getOriginalFunction(); if (oCls && !oFunc->isStatic() && (oCls == m_classScope || oCls->derivesFrom(ar, m_className, true, false))) { info.callWithThis = true; info.localThis = localThis; } } if (!isSelf() && !isParent() && !isStatic()) { info.staticClass = m_className; } } } ExpressionListPtr plist = m->getParams(); int i; for (i = 0; i < nMax || i < nAct; i++) { ParameterExpressionPtr param (i < nMax ? dynamic_pointer_cast<ParameterExpression>((*plist)[i]) : ParameterExpressionPtr()); ExpressionPtr arg = i < nAct ? (*m_params)[i] : Clone(param->defaultValue(), getScope()); SimpleVariablePtr var (new SimpleVariable(getScope(), (i < nAct ? arg.get() : this)->getLocation(), prefix + (param ? param->getName() : lexical_cast<string>(i)))); var->updateSymbol(SimpleVariablePtr()); var->getSymbol()->setHidden(); var->getSymbol()->setUsed(); var->getSymbol()->setReferenced(); bool ref = (i < nMax && m_funcScope->isRefParam(i)) || arg->hasContext(RefParameter); arg->clearContext(RefParameter); AssignmentExpressionPtr ae (new AssignmentExpression(getScope(), arg->getLocation(), var, arg, ref)); info.elist->addElement(ae); if (i < nAct && (ref || !arg->isScalar())) { info.sepm[var->getName()] = var; } } if (cloneStmtsForInline(info, m->getStmts(), prefix, ar, getFunctionScope()) <= 0) { info.elist->addElement(makeConstant(ar, "null")); } if (info.sepm.size()) { ExpressionListPtr unset_list (new ExpressionList(getScope(), getLocation())); for (StringToExpressionPtrMap::iterator it = info.sepm.begin(), end = info.sepm.end(); it != end; ++it) { ExpressionPtr var = it->second->clone(); var->clearContext((Context)(unsigned)-1); unset_list->addElement(var); } ExpressionPtr unset( new UnaryOpExpression(getScope(), getLocation(), unset_list, T_UNSET, true)); i = info.elist->getCount(); ExpressionPtr ret = (*info.elist)[--i]; if (ret->isScalar()) { info.elist->insertElement(unset, i); } else { ExpressionListPtr result_list (new ExpressionList(getScope(), getLocation(), ExpressionList::ListKindLeft)); if (ret->hasContext(LValue)) { result_list->setContext(LValue); result_list->setContext(ReturnContext); } result_list->addElement(ret); result_list->addElement(unset); (*info.elist)[i] = result_list; } } recomputeEffects(); return replaceValue(info.elist); }
void Dictionary::build(MethodStatementPtr m) { if (StatementPtr s = m->getStmts()) { build(s); } }
void FunctionScope::init(AnalysisResultConstPtr ar) { m_dynamicInvoke = false; bool canInline = true; if (m_pseudoMain) { canInline = false; m_variables->forceVariants(ar, VariableTable::AnyVars); setReturnType(ar, Type::Variant); } if (m_refReturn) { m_returnType = Type::Variant; } if (!strcasecmp(m_name.c_str(), "__autoload")) { setVolatile(); } // FileScope's flags are from parser, but VariableTable has more flags // coming from type inference phase. So we are tranferring these flags // just for better modularization between FileScope and VariableTable. if (m_attribute & FileScope::ContainsDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsDynamicVariable); } if (m_attribute & FileScope::ContainsLDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsLDynamicVariable); } if (m_attribute & FileScope::ContainsExtract) { m_variables->setAttribute(VariableTable::ContainsExtract); } if (m_attribute & FileScope::ContainsAssert) { m_variables->setAttribute(VariableTable::ContainsAssert); } if (m_attribute & FileScope::ContainsCompact) { m_variables->setAttribute(VariableTable::ContainsCompact); } if (m_attribute & FileScope::ContainsUnset) { m_variables->setAttribute(VariableTable::ContainsUnset); } if (m_attribute & FileScope::ContainsGetDefinedVars) { m_variables->setAttribute(VariableTable::ContainsGetDefinedVars); } if (m_stmt && Option::AllVolatile && !m_pseudoMain && !m_method) { m_volatile = true; } m_dynamic = Option::IsDynamicFunction(m_method, m_name) || Option::EnableEval == Option::FullEval || Option::AllDynamic; if (!m_method && Option::DynamicInvokeFunctions.find(m_name) != Option::DynamicInvokeFunctions.end()) { setDynamicInvoke(); } if (m_modifiers) { m_virtual = m_modifiers->isAbstract(); } if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); StatementListPtr stmts = stmt->getStmts(); if (stmts) { if (stmts->getRecursiveCount() > Option::InlineFunctionThreshold) canInline = false; for (int i = 0; i < stmts->getCount(); i++) { StatementPtr stmt = (*stmts)[i]; stmt->setFileLevel(); if (stmt->is(Statement::KindOfExpStatement)) { ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt); ExpressionPtr exp = expStmt->getExpression(); exp->setTopLevel(); } } } } else { canInline = false; } m_inlineable = canInline; }
FunctionScope::FunctionScope(AnalysisResultPtr ar, bool method, const std::string &name, StatementPtr stmt, bool reference, int minParam, int maxParam, ModifierExpressionPtr modifiers, int attribute, const std::string &docComment, FileScopePtr file, bool inPseudoMain /* = false */) : BlockScope(name, docComment, stmt, BlockScope::FunctionScope), m_method(method), m_file(file), m_minParam(0), m_maxParam(0), m_attribute(attribute), m_refReturn(reference), m_modifiers(modifiers), m_virtual(false), m_overriding(false), m_redeclaring(-1), m_volatile(false), m_ignored(false), m_pseudoMain(inPseudoMain), m_magicMethod(false), m_system(false), m_inlineable(false), m_sep(false), m_containsThis(false), m_staticMethodAutoFixed(false), m_callTempCountMax(0), m_callTempCountCurrent(0) { bool canInline = true; if (inPseudoMain) { canInline = false; m_variables->forceVariants(ar); setReturnType(ar, Type::Variant); } setParamCounts(ar, minParam, maxParam); if (m_refReturn) { m_returnType = Type::Variant; } // FileScope's flags are from parser, but VariableTable has more flags // coming from type inference phase. So we are tranferring these two // flags just for better modularization between FileScope and VariableTable. if (m_attribute & FileScope::ContainsDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsDynamicVariable); } if (m_attribute & FileScope::ContainsLDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsLDynamicVariable); } if (m_attribute & FileScope::ContainsExtract) { m_variables->setAttribute(VariableTable::ContainsExtract); } if (m_attribute & FileScope::ContainsCompact) { m_variables->setAttribute(VariableTable::ContainsCompact); } if (m_attribute & FileScope::ContainsUnset) { m_variables->setAttribute(VariableTable::ContainsUnset); } if (m_attribute & FileScope::ContainsGetDefinedVars) { m_variables->setAttribute(VariableTable::ContainsGetDefinedVars); } if (m_stmt && Option::AllVolatile) { m_volatile = true; } m_dynamic = Option::IsDynamicFunction(method, m_name) || Option::EnableEval == Option::FullEval; if (modifiers) { m_virtual = modifiers->isAbstract(); } if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); StatementListPtr stmts = stmt->getStmts(); if (stmts) { if (stmts->getRecursiveCount() > Option::InlineFunctionThreshold) canInline = false; for (int i = 0; i < stmts->getCount(); i++) { StatementPtr stmt = (*stmts)[i]; stmt->setFileLevel(); if (stmt->is(Statement::KindOfExpStatement)) { ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt); ExpressionPtr exp = expStmt->getExpression(); exp->setTopLevel(); } } } } else { canInline = false; } m_inlineable = canInline; }