bool Step::predicatesAreContextListInsensitive() const { for (size_t i = 0; i < m_predicates.size(); ++i) { Predicate* predicate = m_predicates[i].get(); if (predicate->isContextPositionSensitive() || predicate->isContextSizeSensitive()) return false; } for (size_t i = 0; i < m_nodeTest.mergedPredicates().size(); ++i) { Predicate* predicate = m_nodeTest.mergedPredicates()[i].get(); if (predicate->isContextPositionSensitive() || predicate->isContextSizeSensitive()) return false; } return true; }
void Step::optimize() { // Evaluate predicates as part of node test if possible to avoid building unnecessary NodeSets. // E.g., there is no need to build a set of all "foo" nodes to evaluate "foo[@bar]", we can check the predicate while enumerating. // This optimization can be applied to predicates that are not context node list sensitive, or to first predicate that is only context position sensitive, e.g. foo[position() mod 2 = 0]. Vector<Predicate*> remainingPredicates; for (size_t i = 0; i < m_predicates.size(); ++i) { Predicate* predicate = m_predicates[i]; if ((!predicate->isContextPositionSensitive() || m_nodeTest.mergedPredicates().isEmpty()) && !predicate->isContextSizeSensitive() && remainingPredicates.isEmpty()) { m_nodeTest.mergedPredicates().append(predicate); } else remainingPredicates.append(predicate); } swap(remainingPredicates, m_predicates); }