예제 #1
0
ExpressionPtr Expression::unneededHelper() {
  ExpressionListPtr elist = ExpressionListPtr
    (new ExpressionList(getScope(), getRange(),
                        ExpressionList::ListKindWrapped));

  bool change = false;
  for (int i=0, n = getKidCount(); i < n; i++) {
    ExpressionPtr kid = getNthExpr(i);
    if (kid && kid->getContainedEffects()) {
      ExpressionPtr rep = kid->unneeded();
      if (rep != kid) change = true;
      if (rep->is(Expression::KindOfExpressionList)) {
        for (int j=0, m = rep->getKidCount(); j < m; j++) {
          elist->addElement(rep->getNthExpr(j));
        }
      } else {
        elist->addElement(rep);
      }
    }
  }

  if (change) {
    getScope()->addUpdates(BlockScope::UseKindCaller);
  }

  int n = elist->getCount();
  assert(n);
  if (n == 1) {
    return elist->getNthExpr(0);
  } else {
    return elist;
  }
}
예제 #2
0
ExpressionPtr AliasManager::canonicalizeRecur(ExpressionPtr e) {
  switch (e->getKindOf()) {
  case Expression::KindOfQOpExpression:
    canonicalizeKid(e, e->getNthExpr(0), 0);
    beginScope();
    canonicalizeKid(e, e->getNthExpr(1), 1);
    resetScope();
    canonicalizeKid(e, e->getNthExpr(2), 2);
    endScope();
    return canonicalizeNode(e);

  case Expression::KindOfBinaryOpExpression:
    if (spc(BinaryOpExpression,e)->isShortCircuitOperator()) {
      canonicalizeKid(e, e->getNthExpr(0), 0);
      beginScope();
      canonicalizeKid(e, e->getNthExpr(1), 1);
      endScope();
      return canonicalizeNode(e);
    }
    break;

  default:
    break;
  }

  for (int i = 0, n = e->getKidCount(); i < n; i++) {
    canonicalizeKid(e, e->getNthExpr(i), i);
  }

  return canonicalizeNode(e);
}
예제 #3
0
void Dictionary::build(ExpressionPtr e) {
  for (int i = 0, n = e->getKidCount(); i < n; i++) {
    if (ExpressionPtr kid = e->getNthExpr(i)) {
      build(kid);
    }
  }
  visit(e);
}
예제 #4
0
/*
 * We can end up with chains of canonPtrs keeping the
 * elements of an ExpressionList alive, with the result
 * that when they are finally destroyed, they are destroyed
 * one by one, recursively.
 * This proactively clears them.
 */
static void clearCanonPtrs(ExpressionPtr e) {
  e->setCanonPtr(ExpressionPtr{});
  for (int i = e->getKidCount(); i--; ) {
    ExpressionPtr kid = e->getNthExpr(i);
    if (kid && !kid->is(Expression::KindOfExpressionList)) {
      clearCanonPtrs(kid);
    }
  }
}
예제 #5
0
void DataFlowWalker::processAccessChain(ExpressionPtr e) {
  if (!e) return;
  if (!e->is(Expression::KindOfObjectPropertyExpression) &&
      !e->is(Expression::KindOfArrayElementExpression)) {
    return;
  }
  for (int i = 0, n = e->getKidCount(); i < n; ++i) {
    ExpressionPtr kid(e->getNthExpr(i));
    if (kid && kid->hasContext(Expression::AccessContext)) {
      processAccessChain(kid);
      process(kid, true);
      break;
    }
  }
}
예제 #6
0
/**
 * Traverses the expression tree rooted at e and returns true if
 * any node in the tree is a simple variable that references a
 * name in m_boundVars.
 */
bool CaptureExtractor::dependsOnQueryOnlyState(ExpressionPtr e) {
  assert(e != nullptr);
  if (e->getKindOf() == Expression::KindOfSimpleVariable) {
    auto sv = static_pointer_cast<SimpleVariable>(e);
    auto varName = sv->getName();
    for (auto &boundVar : m_boundVars) {
      if (varName == boundVar) return true;
    }
    return false;
  }
  auto numKids = e->getKidCount();
  for (int i = 0; i < numKids; i++) {
    auto ei = e->getNthExpr(i);
    if (ei == nullptr) return false; //Default param
    if (dependsOnQueryOnlyState(ei)) return true;
  }
  return false;
}
예제 #7
0
static ExpressionPtr cloneForInlineRecur(InlineCloneInfo &info,
                                         ExpressionPtr exp,
                                         const std::string &prefix,
                                         AnalysisResultConstPtr ar,
                                         FunctionScopePtr scope) {
  exp->getOriginalScope(); // make sure to cache the original scope
  exp->setBlockScope(scope);
  for (int i = 0, n = exp->getKidCount(); i < n; i++) {
    if (ExpressionPtr k = exp->getNthExpr(i)) {
      exp->setNthKid(i, cloneForInlineRecur(info, k, prefix, ar, scope));
    }
  }
  StaticClassName *scn = dynamic_cast<StaticClassName*>(exp.get());
  if (scn && scn->isStatic() && !info.staticClass.empty()) {
    scn->resolveStatic(info.staticClass);
  }
  switch (exp->getKindOf()) {
  case Expression::KindOfSimpleVariable:
    {
      SimpleVariablePtr sv(dynamic_pointer_cast<SimpleVariable>(exp));
      if (sv->isSuperGlobal()) break;
      string name;
      if (sv->isThis()) {
        if (!info.callWithThis) {
          if (!sv->hasContext(Expression::ObjectContext)) {
            exp = sv->makeConstant(ar, "null");
          } else {
            // This will produce the wrong error
            // we really want a "throw_fatal" ast node.
            exp = sv->makeConstant(ar, "null");
          }
          break;
        }
        if (info.localThis.empty()) break;
        name = info.localThis;
      } else {
        name = prefix + sv->getName();
      }
      SimpleVariablePtr rep(new SimpleVariable(
                              exp->getScope(), exp->getLocation(), name));
      rep->copyContext(sv);
      rep->updateSymbol(SimpleVariablePtr());
      rep->getSymbol()->setHidden();
      // Conservatively set flags to prevent
      // the alias manager from getting confused.
      // On the next pass, it will correct the values,
      // and optimize appropriately.
      rep->getSymbol()->setUsed();
      rep->getSymbol()->setReferenced();
      if (exp->getContext() & (Expression::LValue|
                               Expression::RefValue|
                               Expression::RefParameter)) {
        info.sepm[name] = rep;
      }
      exp = rep;
    }
    break;
  case Expression::KindOfObjectMethodExpression:
  {
    FunctionCallPtr call(
      static_pointer_cast<FunctionCall>(exp));
    if (call->getFuncScope() == info.func) {
      call->setNoInline();
    }
    break;
  }
  case Expression::KindOfSimpleFunctionCall:
    {
      SimpleFunctionCallPtr call(static_pointer_cast<SimpleFunctionCall>(exp));
      call->addLateDependencies(ar);
      call->setLocalThis(info.localThis);
      if (call->getFuncScope() == info.func) {
        call->setNoInline();
      }
    }
  default:
    break;
  }
  return exp;
}
예제 #8
0
void ExprDict::updateAccess(ExpressionPtr e) {
  int cls = e->getExprClass();
  int eid = e->getCanonID();
  e->clearAnticipated();
  e->clearAvailable();

  // bail on non-canonical expressions
  if (!isCanonicalStructure(eid)) {
    // but record we saw a type assertion belonging to this block
    m_avlTypeAsserts.push_back(eid);
    return;
  }

  if (m_anticipated &&
      (cls & Expression::Update ?
       !BitOps::get_bit(eid, m_altered) : !e->getLocalEffects())) {
    /*
      Anticipated can be computed bottom up as we go. But note that we
      only know altered for Load/Store expressions.
    */
    int i = e->getKidCount();
    while (true) {
      if (!i--) {
        e->setAnticipated();
        if (!e->hasContext(Expression::AssignmentLHS)) {
          setStructureOps(eid, m_anticipated, true);
        }
        break;
      }
      if (ExpressionPtr k = e->getNthExpr(i)) {
        if (!isCanonicalStructure(k->getCanonID())) continue;
        if (!k->isAnticipated()) {
          break;
        }
      }
    }
  }

  if (m_available) {
    /*
      Available has to be computed optimistically, because we dont yet
      know what is going to be altered between here and the end of the block
      So keep a list of the potentially-available accesses (avlAccess), and
      for each id, the last potentially-available expression (avlExpr).
      For each modifying expression that we process, we remove expressions
      from avlAccess, and at the end, we build up the available expressions
      bottom up.
    */
    if ((cls & (Expression::Store|Expression::Call)) ||
        (cls & Expression::Load &&
         e->getContext() & (Expression::LValue|
                            Expression::RefValue|
                            Expression::UnsetContext|
                            Expression::DeepReference))) {
      bool isLoad;
      int depth = 0, effects = 0;
      for (int i = 0, n = m_avlAccess.size(); i < n; ) {
        ExpressionRawPtr a = m_avlAccess[i];
        if (m_am.checkAnyInterf(e, a, isLoad, depth, effects) !=
            AliasManager::DisjointAccess) {
          int aid = a->getCanonID();
          assert(isCanonicalStructure(aid));
          if (eid != aid || cls == Expression::Load) {
            BitOps::set_bit(aid, m_altered, true);
          }
          if (!(cls & Expression::Store) ||
              a != e->getStoreVariable()) {
            a->clearAvailable();
            m_avlAccess[i] = m_avlAccess[--n];
            m_avlAccess.resize(n);
            continue;
          }
        }
        i++;
      }
    }
    if (cls & Expression::Update ||
        !e->getContainedEffects()) {
      int i = e->getKidCount();
      while (true) {
        if (!i--) {
          e->setAvailable();
          if (cls & Expression::Update) {
            m_avlAccess.push_back(e);
          }
          m_avlExpr[eid] = e;
          break;
        }
        if (ExpressionPtr k = e->getNthExpr(i)) {
          if (!isCanonicalStructure(k->getCanonID())) continue;
          if (!k->isAvailable()) {
            break;
          }
        }
      }
    }
  }

  if ((cls & (Expression::Store|Expression::Call)) ||
      (cls & Expression::Load &&
       e->getContext() & (Expression::LValue|
                          Expression::RefValue|
                          Expression::UnsetContext|
                          Expression::DeepReference))) {
    ExpressionPtr cur = m_active, prev;
    bool isLoad;
    int depth = 0, effects = 0;
    while (cur) {
      ExpressionPtr next = cur->getCanonLVal();
      int cid = cur->getCanonID();
      assert(isCanonicalStructure(cid));
      if ((cid != eid || cls == Expression::Load) &&
          (BitOps::get_bit(cid, m_altered) ||
           m_am.checkAnyInterf(e, cur, isLoad, depth, effects) !=
           AliasManager::DisjointAccess)) {
        BitOps::set_bit(cid, m_altered, true);
        if (!prev) {
          m_active = next;
        } else {
          prev->setCanonPtr(next);
        }
      } else {
        prev = cur;
      }
      cur = next;
    }
  }
}