You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by db...@apache.org on 2001/11/08 04:44:57 UTC
cvs commit: xml-xalan/c/src/XPath XPath.cpp
dbertoni 01/11/07 19:44:57
Modified: c/src/XPath XPath.cpp
Log:
Optimize predicates with numeric literals.
Revision Changes Path
1.65 +86 -30 xml-xalan/c/src/XPath/XPath.cpp
Index: XPath.cpp
===================================================================
RCS file: /home/cvs/xml-xalan/c/src/XPath/XPath.cpp,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -r1.64 -r1.65
--- XPath.cpp 2001/11/01 15:57:13 1.64
+++ XPath.cpp 2001/11/08 03:44:57 1.65
@@ -1609,18 +1609,27 @@
while(XPathExpression::eOP_PREDICATE == nextStepType)
{
- const XObjectPtr pred(predicate(context, opPos, executionContext));
- assert(pred.get() != 0);
-
- if(XObject::eTypeNumber == pred->getType())
+ // This is a quick hack to look ahead and see if we have
+ // number literal as the predicate, i.e. match="foo[1]".
+ if (m_expression.getOpCodeMapValue(opPos + 2) == XPathExpression::eOP_NUMBERLIT)
{
score = handleFoundIndex(executionContext, context, startOpPos);
}
- else if(pred->boolean() == false)
+ else
{
- score = eMatchScoreNone;
+ const XObjectPtr pred(predicate(context, opPos, executionContext));
+ assert(pred.get() != 0);
- break;
+ if(XObject::eTypeNumber == pred->getType())
+ {
+ score = handleFoundIndex(executionContext, context, startOpPos);
+ }
+ else if(pred->boolean() == false)
+ {
+ score = eMatchScoreNone;
+
+ break;
+ }
}
opPos = currentExpression.getNextOpCodePosition(opPos);
@@ -2877,33 +2886,84 @@
while(XPathExpression::eOP_PREDICATE == nextStepType)
{
- NodeRefListBase::size_type i = 0;
-
const NodeRefListBase::size_type theLength = subQueryResults.getLength();
- while(i < theLength)
- {
- XalanNode* const theNode = subQueryResults.item(i);
- assert(theNode != 0);
+ // If we have no nodes left, then there's no point in executing any
+ // predicates. However, we will continue to loop, since we need to
+ // update endPredicatePos.
+ if (theLength > 0)
+ {
+ const int predOpPos = opPos + 2;
+
+ // OK, this is a huge hack/optimization. If the predicate is
+ // simple a number, such as [2], we can just get the
+ // numeric value from the expression, and not bother executing
+ // the predicate. Furthermore, we don't need to execute the
+ // predicate for each node, since the evaluation is no dependent
+ // on the context node. All we really have to do is remove all
+ // nodes from subQueryResults, _except_ for the node at that
+ // position. The only trick is that XPath indexes from 1, while
+ // our node lists index from 0.
+ if (m_expression.getOpCodeMapValue(predOpPos) == XPathExpression::eOP_NUMBERLIT)
+ {
+ assert(m_expression.m_tokenQueue.size() > unsigned(m_expression.m_opMap[predOpPos + 3]));
+
+ // Get the value of the number...
+ const double theIndex =
+ m_expression.getNumberLiteral(m_expression.getOpCodeMapValue(predOpPos + 2));
+
+ // If the index is out of range, or not an integer, just clear subQueryResults...
+ if (theIndex <= 0.0 ||
+ NodeRefListBase::size_type(theIndex) > theLength ||
+ double(NodeRefListBase::size_type(theIndex)) != theIndex)
+ {
+ subQueryResults.clear();
+ }
+ else if (theLength > 1)
+ {
+ // Save the matching node...
+ XalanNode* const theNode =
+ subQueryResults.item(NodeRefListBase::size_type(theIndex) - 1);
- const XObjectPtr pred(predicate(theNode, opPos, executionContext));
- assert(pred.get() != 0);
+ // Clear the list...
+ subQueryResults.clear();
- // Remove any node that doesn't satisfy the predicate.
- if((XObject::eTypeNumber == pred->getType() && i + 1 != pred->num()) ||
- pred->boolean() == false)
- {
- // Set the node to 0. After we're done,
- // we'll clear it out.
- subQueryResults.setNode(i, 0);
+ // Add the node back in...
+ subQueryResults.addNode(theNode);
+ }
+ else
+ {
+ // OK, if there's only 1 node in the list, then
+ // we don't need to bother modifying the list.
+ // Just assert that theIndex == 1.0...
+ assert(theIndex == 1.0);
+ }
}
+ else
+ {
+ for(NodeRefListBase::size_type i = 0; i < theLength; ++i)
+ {
+ XalanNode* const theNode = subQueryResults.item(i);
+ assert(theNode != 0);
- ++i;
- }
+ const XObjectPtr pred(predicate(theNode, opPos, executionContext));
+ assert(pred.get() != 0);
- // Clear out any null entries...
- subQueryResults.clearNulls();
+ // Remove any node that doesn't satisfy the predicate.
+ if((XObject::eTypeNumber == pred->getType() && i + 1 != pred->num()) ||
+ pred->boolean() == false)
+ {
+ // Set the node to 0. After we're done,
+ // we'll clear it out.
+ subQueryResults.setNode(i, 0);
+ }
+ }
+ // Clear out any null entries...
+ subQueryResults.clearNulls();
+ }
+ }
+
opPos = currentExpression.getNextOpCodePosition(opPos);
nextStepType = currentExpression.getOpCodeMapValue(opPos);
@@ -2911,10 +2971,6 @@
if(XPathExpression::eOP_PREDICATE == nextStepType)
{
executionContext.setContextNodeList(subQueryResults);
-
- // Don't break, loop 'till end so that opPos will be set to end.
- // if(0 == subQueryResults.getLength())
- // break;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org