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 &params = *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;
}
Exemple #2
0
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();
                }
            }
        }
    }
}
Exemple #3
0
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);
}
Exemple #5
0
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;
}