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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]