| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005 Frerich Raabe <raabe@kde.org> | 2 * Copyright (C) 2005 Frerich Raabe <raabe@kde.org> |
| 3 * Copyright (C) 2006, 2009 Apple Inc. All rights reserved. | 3 * Copyright (C) 2006, 2009 Apple Inc. All rights reserved. |
| 4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> | 4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * | 9 * |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 #include "core/dom/Attr.h" | 32 #include "core/dom/Attr.h" |
| 33 #include "core/dom/Document.h" | 33 #include "core/dom/Document.h" |
| 34 #include "core/dom/Element.h" | 34 #include "core/dom/Element.h" |
| 35 #include "core/dom/NodeTraversal.h" | 35 #include "core/dom/NodeTraversal.h" |
| 36 #include "core/xml/XPathParser.h" | 36 #include "core/xml/XPathParser.h" |
| 37 #include "core/xml/XPathUtil.h" | 37 #include "core/xml/XPathUtil.h" |
| 38 | 38 |
| 39 namespace WebCore { | 39 namespace WebCore { |
| 40 namespace XPath { | 40 namespace XPath { |
| 41 | 41 |
| 42 Step::Step(Axis axis, const NodeTest& nodeTest, const Vector<Predicate*>& predic
ates) | 42 Step::Step(Axis axis, const NodeTest& nodeTest) |
| 43 : m_axis(axis) | 43 : m_axis(axis) |
| 44 , m_nodeTest(nodeTest) | 44 , m_nodeTest(nodeTest) |
| 45 , m_predicates(predicates) | |
| 46 { | 45 { |
| 47 } | 46 } |
| 48 | 47 |
| 48 Step::Step(Axis axis, const NodeTest& nodeTest, Vector<OwnPtr<Predicate> >& pred
icates) |
| 49 : m_axis(axis) |
| 50 , m_nodeTest(nodeTest) |
| 51 { |
| 52 m_predicates.swap(predicates); |
| 53 } |
| 54 |
| 49 Step::~Step() | 55 Step::~Step() |
| 50 { | 56 { |
| 51 deleteAllValues(m_predicates); | |
| 52 deleteAllValues(m_nodeTest.mergedPredicates()); | |
| 53 } | 57 } |
| 54 | 58 |
| 55 void Step::optimize() | 59 void Step::optimize() |
| 56 { | 60 { |
| 57 // Evaluate predicates as part of node test if possible to avoid building un
necessary NodeSets. | 61 // Evaluate predicates as part of node test if possible to avoid building un
necessary NodeSets. |
| 58 // 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. | 62 // 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. |
| 59 // 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]. | 63 // 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]. |
| 60 Vector<Predicate*> remainingPredicates; | 64 Vector<OwnPtr<Predicate> > remainingPredicates; |
| 61 for (size_t i = 0; i < m_predicates.size(); ++i) { | 65 for (size_t i = 0; i < m_predicates.size(); ++i) { |
| 62 Predicate* predicate = m_predicates[i]; | 66 OwnPtr<Predicate> predicate(m_predicates[i].release()); |
| 63 if ((!predicate->isContextPositionSensitive() || m_nodeTest.mergedPredic
ates().isEmpty()) && !predicate->isContextSizeSensitive() && remainingPredicates
.isEmpty()) { | 67 if ((!predicate->isContextPositionSensitive() || m_nodeTest.mergedPredic
ates().isEmpty()) && !predicate->isContextSizeSensitive() && remainingPredicates
.isEmpty()) { |
| 64 m_nodeTest.mergedPredicates().append(predicate); | 68 m_nodeTest.mergedPredicates().append(predicate.release()); |
| 65 } else | 69 } else { |
| 66 remainingPredicates.append(predicate); | 70 remainingPredicates.append(predicate.release()); |
| 71 } |
| 67 } | 72 } |
| 68 swap(remainingPredicates, m_predicates); | 73 swap(remainingPredicates, m_predicates); |
| 69 } | 74 } |
| 70 | 75 |
| 71 void optimizeStepPair(Step* first, Step* second, bool& dropSecondStep) | 76 void optimizeStepPair(Step* first, Step* second, bool& dropSecondStep) |
| 72 { | 77 { |
| 73 dropSecondStep = false; | 78 dropSecondStep = false; |
| 74 | 79 |
| 75 if (first->m_axis == Step::DescendantOrSelfAxis | 80 if (first->m_axis == Step::DescendantOrSelfAxis |
| 76 && first->m_nodeTest.kind() == Step::NodeTest::AnyNodeTest | 81 && first->m_nodeTest.kind() == Step::NodeTest::AnyNodeTest |
| (...skipping 11 matching lines...) Expand all Loading... |
| 88 swap(second->m_predicates, first->m_predicates); | 93 swap(second->m_predicates, first->m_predicates); |
| 89 first->optimize(); | 94 first->optimize(); |
| 90 dropSecondStep = true; | 95 dropSecondStep = true; |
| 91 } | 96 } |
| 92 } | 97 } |
| 93 } | 98 } |
| 94 | 99 |
| 95 bool Step::predicatesAreContextListInsensitive() const | 100 bool Step::predicatesAreContextListInsensitive() const |
| 96 { | 101 { |
| 97 for (size_t i = 0; i < m_predicates.size(); ++i) { | 102 for (size_t i = 0; i < m_predicates.size(); ++i) { |
| 98 Predicate* predicate = m_predicates[i]; | 103 Predicate* predicate = m_predicates[i].get(); |
| 99 if (predicate->isContextPositionSensitive() || predicate->isContextSizeS
ensitive()) | 104 if (predicate->isContextPositionSensitive() || predicate->isContextSizeS
ensitive()) |
| 100 return false; | 105 return false; |
| 101 } | 106 } |
| 102 | 107 |
| 103 for (size_t i = 0; i < m_nodeTest.mergedPredicates().size(); ++i) { | 108 for (size_t i = 0; i < m_nodeTest.mergedPredicates().size(); ++i) { |
| 104 Predicate* predicate = m_nodeTest.mergedPredicates()[i]; | 109 Predicate* predicate = m_nodeTest.mergedPredicates()[i].get(); |
| 105 if (predicate->isContextPositionSensitive() || predicate->isContextSizeS
ensitive()) | 110 if (predicate->isContextPositionSensitive() || predicate->isContextSizeS
ensitive()) |
| 106 return false; | 111 return false; |
| 107 } | 112 } |
| 108 | 113 |
| 109 return true; | 114 return true; |
| 110 } | 115 } |
| 111 | 116 |
| 112 void Step::evaluate(Node* context, NodeSet& nodes) const | 117 void Step::evaluate(Node* context, NodeSet& nodes) const |
| 113 { | 118 { |
| 114 EvaluationContext& evaluationContext = Expression::evaluationContext(); | 119 EvaluationContext& evaluationContext = Expression::evaluationContext(); |
| 115 evaluationContext.position = 0; | 120 evaluationContext.position = 0; |
| 116 | 121 |
| 117 nodesInAxis(context, nodes); | 122 nodesInAxis(context, nodes); |
| 118 | 123 |
| 119 // Check predicates that couldn't be merged into node test. | 124 // Check predicates that couldn't be merged into node test. |
| 120 for (unsigned i = 0; i < m_predicates.size(); i++) { | 125 for (unsigned i = 0; i < m_predicates.size(); i++) { |
| 121 Predicate* predicate = m_predicates[i]; | 126 Predicate* predicate = m_predicates[i].get(); |
| 122 | 127 |
| 123 NodeSet newNodes; | 128 NodeSet newNodes; |
| 124 if (!nodes.isSorted()) | 129 if (!nodes.isSorted()) |
| 125 newNodes.markSorted(false); | 130 newNodes.markSorted(false); |
| 126 | 131 |
| 127 for (unsigned j = 0; j < nodes.size(); j++) { | 132 for (unsigned j = 0; j < nodes.size(); j++) { |
| 128 Node* node = nodes[j]; | 133 Node* node = nodes[j]; |
| 129 | 134 |
| 130 evaluationContext.node = node; | 135 evaluationContext.node = node; |
| 131 evaluationContext.size = nodes.size(); | 136 evaluationContext.size = nodes.size(); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 static inline bool nodeMatches(Node* node, Step::Axis axis, const Step::NodeTest
& nodeTest) | 215 static inline bool nodeMatches(Node* node, Step::Axis axis, const Step::NodeTest
& nodeTest) |
| 211 { | 216 { |
| 212 if (!nodeMatchesBasicTest(node, axis, nodeTest)) | 217 if (!nodeMatchesBasicTest(node, axis, nodeTest)) |
| 213 return false; | 218 return false; |
| 214 | 219 |
| 215 EvaluationContext& evaluationContext = Expression::evaluationContext(); | 220 EvaluationContext& evaluationContext = Expression::evaluationContext(); |
| 216 | 221 |
| 217 // Only the first merged predicate may depend on position. | 222 // Only the first merged predicate may depend on position. |
| 218 ++evaluationContext.position; | 223 ++evaluationContext.position; |
| 219 | 224 |
| 220 const Vector<Predicate*>& mergedPredicates = nodeTest.mergedPredicates(); | 225 const Vector<OwnPtr<Predicate> >& mergedPredicates = nodeTest.mergedPredicat
es(); |
| 221 for (unsigned i = 0; i < mergedPredicates.size(); i++) { | 226 for (unsigned i = 0; i < mergedPredicates.size(); i++) { |
| 222 Predicate* predicate = mergedPredicates[i]; | 227 Predicate* predicate = mergedPredicates[i].get(); |
| 223 | 228 |
| 224 evaluationContext.node = node; | 229 evaluationContext.node = node; |
| 225 // No need to set context size - we only get here when evaluating predic
ates that do not depend on it. | 230 // No need to set context size - we only get here when evaluating predic
ates that do not depend on it. |
| 226 if (!predicate->evaluate()) | 231 if (!predicate->evaluate()) |
| 227 return false; | 232 return false; |
| 228 } | 233 } |
| 229 | 234 |
| 230 return true; | 235 return true; |
| 231 } | 236 } |
| 232 | 237 |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 nodes.markSorted(false); | 392 nodes.markSorted(false); |
| 388 return; | 393 return; |
| 389 } | 394 } |
| 390 } | 395 } |
| 391 ASSERT_NOT_REACHED(); | 396 ASSERT_NOT_REACHED(); |
| 392 } | 397 } |
| 393 | 398 |
| 394 | 399 |
| 395 } | 400 } |
| 396 } | 401 } |
| OLD | NEW |