StatementPtr ForEachStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_array); ar->preOptimize(m_name); ar->preOptimize(m_value); ar->preOptimize(m_stmt); return StatementPtr(); }
ExpressionPtr FunctionCall::preOptimize(AnalysisResultPtr ar) { if (m_class) { ar->preOptimize(m_class); updateClassName(); } ar->preOptimize(m_nameExp); ar->preOptimize(m_params); return ExpressionPtr(); }
StatementPtr WhileStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_condition); if (m_stmt) { ar->getScope()->incLoopNestedLevel(); ar->preOptimize(m_stmt); ar->getScope()->decLoopNestedLevel(); } return StatementPtr(); }
ExpressionPtr AssignmentExpression::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_variable); ar->preOptimize(m_value); if (Option::EliminateDeadCode && ar->getPhase() >= AnalysisResult::FirstPreOptimize) { // otherwise used & needed flags may not be up to date yet return optimize(ar); } return ExpressionPtr(); }
StatementPtr ForStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_exp1); ar->preOptimize(m_exp2); ar->preOptimize(m_exp3); if (m_stmt) { ar->getScope()->incLoopNestedLevel(); ar->preOptimize(m_stmt); ar->getScope()->decLoopNestedLevel(); } return StatementPtr(); }
ExpressionPtr QOpExpression::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_condition); ar->preOptimize(m_expYes); ar->preOptimize(m_expNo); Variant value; if (m_condition->getScalarValue(value)) { if (value.toBoolean()) return m_expYes; else return m_expNo; } else { return ExpressionPtr(); } }
StatementPtr InterfaceStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_base); if (m_stmt) { ClassScopePtr classScope = m_classScope.lock(); ar->pushScope(classScope); ar->preOptimize(m_stmt); ar->popScope(); } if (ar->getPhase() >= AnalysisResult::AnalyzeAll) { checkVolatile(ar); } return StatementPtr(); }
StatementPtr StatementList::preOptimize(AnalysisResultPtr ar) { bool del = false; bool changed = false; for (unsigned int i = 0; i < m_stmts.size(); i++) { StatementPtr &s = m_stmts[i]; if (del) { switch (s->getKindOf()) { case Statement::KindOfBlockStatement: case Statement::KindOfIfBranchStatement: case Statement::KindOfIfStatement: case Statement::KindOfWhileStatement: case Statement::KindOfDoStatement: case Statement::KindOfForStatement: case Statement::KindOfSwitchStatement: case Statement::KindOfCaseStatement: case Statement::KindOfBreakStatement: case Statement::KindOfContinueStatement: case Statement::KindOfReturnStatement: case Statement::KindOfGlobalStatement: case Statement::KindOfStaticStatement: case Statement::KindOfEchoStatement: case Statement::KindOfUnsetStatement: case Statement::KindOfExpStatement: case Statement::KindOfForEachStatement: case Statement::KindOfCatchStatement: case Statement::KindOfTryStatement: case Statement::KindOfThrowStatement: removeElement(i--); changed = true; continue; default: break; } } if (s) { ar->preOptimize(s); if (ar->getPhase() != AnalysisResult::AnalyzeInclude && Option::EliminateDeadCode) { if (s->is(KindOfBreakStatement) || s->is(KindOfContinueStatement) || s->is(KindOfReturnStatement) || s->is(KindOfThrowStatement)) { del = true; } else if (s->is(KindOfExpStatement)) { ExpressionPtr e = dynamic_pointer_cast<ExpStatement>(s)->getExpression(); if (!e->hasEffect()) { removeElement(i--); changed = true; } } } } } if (mergeConcatAssign(ar)) changed = true; return changed ? static_pointer_cast<Statement>(shared_from_this()) : StatementPtr(); }
ExpressionPtr ExpressionList::preOptimize(AnalysisResultPtr ar) { for (unsigned int i = 0; i < m_exps.size(); i++) { ar->preOptimize(m_exps[i]); } return optimize(ar) ? static_pointer_cast<Expression>(shared_from_this()) : ExpressionPtr(); }
ExpressionPtr UnaryOpExpression::preOptimize(AnalysisResultPtr ar) { Variant value; Variant result; ar->preOptimize(m_exp); if (m_exp && ar->getPhase() >= AnalysisResult::FirstPreOptimize) { if (m_op == '(') { return m_exp; } if (m_op == T_UNSET) { if (m_exp->isScalar() || (m_exp->is(KindOfExpressionList) && static_pointer_cast<ExpressionList>(m_exp)->getCount() == 0)) { return CONSTANT("null"); } return ExpressionPtr(); } } if (m_op != T_ARRAY && m_exp && m_exp->isScalar() && m_exp->getScalarValue(value) && preCompute(value, result)) { return replaceValue(MakeScalarExpression(ar, getLocation(), result)); } return ExpressionPtr(); }
ExpressionPtr UnaryOpExpression::preOptimize(AnalysisResultPtr ar) { Variant value; Variant result; bool hasResult; ar->preOptimize(m_exp); if (!m_exp || !m_exp->isScalar()) return ExpressionPtr(); if (!m_exp->getScalarValue(value)) return ExpressionPtr(); hasResult = preCompute(ar, value, result); if (hasResult) { if (result.isNull()) { return CONSTANT("null"); } else if (result.isBoolean()) { return CONSTANT(result ? "true" : "false"); } else if (result.isDouble() && !finite(result.getDouble())) { return ExpressionPtr(); } else if (result.isArray()) { return ExpressionPtr(); } else { return ScalarExpressionPtr (new ScalarExpression(m_exp->getLocation(), Expression::KindOfScalarExpression, result)); } } return ExpressionPtr(); }
StatementPtr ExpStatement::preOptimize(AnalysisResultPtr ar) { if (ar->getPhase() != AnalysisResult::AnalyzeInclude) { m_exp = m_exp->unneeded(ar); } ar->preOptimize(m_exp); return StatementPtr(); }
StatementPtr MethodStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_modifiers); ar->preOptimize(m_params); FunctionScopePtr funcScope = m_funcScope.lock(); ar->pushScope(funcScope); if (ar->getPhase() != AnalysisResult::AnalyzeInclude && AliasManager::doLocalCopyProp()) { bool flag; do { AliasManager am; MethodStatementPtr self = static_pointer_cast<MethodStatement>(shared_from_this()); flag = am.optimize(ar, self); ar->preOptimize(m_stmt); } while (flag); } else { ar->preOptimize(m_stmt); } ar->popScope(); return StatementPtr(); }
ExpressionPtr BinaryOpExpression::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_exp1); ar->preOptimize(m_exp2); if (!m_exp2->isScalar()) { if (!m_exp1->isScalar()) return ExpressionPtr(); } ExpressionPtr optExp; try { optExp = foldConst(ar); } catch (Exception &e) { // runtime/base threw an exception, perhaps bad operands } if (optExp) return optExp; if (isShortCircuitOperator()) return simplifyLogical(ar); return ExpressionPtr(); }
ExpressionPtr DynamicVariable::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_exp); return ExpressionPtr(); }
StatementPtr CatchStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_stmt); return StatementPtr(); }
StatementPtr ClassVariable::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_modifiers); ar->preOptimize(m_declaration); return StatementPtr(); }
ExpressionPtr ParameterExpression::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_defaultValue); return ExpressionPtr(); }
ExpressionPtr ArrayPairExpression::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_name); ar->preOptimize(m_value); return ExpressionPtr(); }
StatementPtr BlockStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_stmts); return StatementPtr(); }
StatementPtr IfBranchStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_condition); ar->preOptimize(m_stmt); return StatementPtr(); }
ExpressionPtr AssignmentExpression::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_variable); ar->preOptimize(m_value); return ExpressionPtr(); }
StatementPtr SwitchStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_exp); ar->preOptimize(m_cases); return StatementPtr(); }
ExpressionPtr ObjectPropertyExpression::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_object); ar->preOptimize(m_property); return ExpressionPtr(); }
StatementPtr StaticStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_exp); return StatementPtr(); }
ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_nameExp); ar->preOptimize(m_params); if (ar->getPhase() != AnalysisResult::SecondPreOptimize) { return ExpressionPtr(); } // optimize away various "exists" functions, this may trigger // dead code elimination and improve type-inference. if (m_className.empty() && (m_type == DefinedFunction || m_type == FunctionExistsFunction || m_type == ClassExistsFunction || m_type == InterfaceExistsFunction) && m_params && m_params->getCount() == 1) { ExpressionPtr value = (*m_params)[0]; if (value->isScalar()) { ScalarExpressionPtr name = dynamic_pointer_cast<ScalarExpression>(value); if (name && name->isLiteralString()) { string symbol = name->getLiteralString(); switch (m_type) { case DefinedFunction: { ConstantTablePtr constants = ar->getConstants(); // system constant if (constants->isPresent(symbol)) { return CONSTANT("true"); } // user constant BlockScopePtr block = ar->findConstantDeclarer(symbol); // not found (i.e., undefined) if (!block) { if (symbol.find("::") == std::string::npos) { return CONSTANT("false"); } else { // e.g., defined("self::ZERO") return ExpressionPtr(); } } constants = block->getConstants(); // already set to be dynamic if (constants->isDynamic(symbol)) return ExpressionPtr(); ConstructPtr decl = constants->getValue(symbol); ExpressionPtr constValue = dynamic_pointer_cast<Expression>(decl); if (constValue->isScalar()) { return CONSTANT("true"); } else { return ExpressionPtr(); } break; } case FunctionExistsFunction: { const std::string &lname = Util::toLower(symbol); if (Option::DynamicInvokeFunctions.find(lname) == Option::DynamicInvokeFunctions.end()) { FunctionScopePtr func = ar->findFunction(lname); if (!func) { return CONSTANT("false"); } else if (!func->isVolatile()) { return CONSTANT("true"); } } break; } case InterfaceExistsFunction: { ClassScopePtr cls = ar->findClass(Util::toLower(symbol)); if (!cls || !cls->isInterface()) { return CONSTANT("false"); } else if (!cls->isVolatile()) { return CONSTANT("true"); } break; } case ClassExistsFunction: { ClassScopePtr cls = ar->findClass(Util::toLower(symbol)); if (!cls || cls->isInterface()) { return CONSTANT("false"); } else if (!cls->isVolatile()) { return CONSTANT("true"); } break; } default: ASSERT(false); } } } } return ExpressionPtr(); }
ExpressionPtr ListAssignment::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_variables); ar->preOptimize(m_array); return ExpressionPtr(); }
StatementPtr EchoStatement::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_exp); m_exp->stripConcat(); return StatementPtr(); }
ExpressionPtr ArrayElementExpression::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_variable); ar->preOptimize(m_offset); return ExpressionPtr(); }
ExpressionPtr ObjectMethodExpression::preOptimize(AnalysisResultPtr ar) { ar->preOptimize(m_object); return FunctionCall::preOptimize(ar); }