[xslt] speeding up xslt in gtk-doc



hi,

I am still not happy with the time it takes for gtk-doc to generate the
html. I did some profiling and tired various changes. Its not too
impressive. Just posting them here for feedback and comment on the
directions of what would be acceptable or not. I technically have commit
rights, so I can push things once they are ready. If patch 0002 looks
like a good idea, I can extend it for other accessors.

Stefan

Test case was generating the html for gstreamer-core api docs

real       user       sys
------------------------------ before
1m22.872s  1m17.317s  0m1.444s
1m19.261s  1m17.437s  0m1.384s
1m19.770s  1m17.417s  0m1.264s
------------------------------ 0001-xpath-annotate-branch-prediction.patch
1m18.123s  1m16.677s  0m1.256s
1m18.684s  1m17.181s  0m1.292s
1m18.887s  1m17.217s  0m1.364s
------------------------------
0002-xpath-split-traversal-into-init-and-next-functions.patch
1m18.537s  1m16.925s  0m1.388s
1m18.616s  1m16.913s  0m1.412s
1m18.249s  1m16.653s  0m1.328s
------------------------------
0003-xpath-avoid-a-memcpy-on-the-expense-of-temporarily-w.patch
1m17.481s  1m16.137s  0m1.208s
1m17.977s  1m16.481s  0m1.328s
1m17.791s  1m16.413s  0m1.232s

>From 144d36fbdd4ff3fec27f50189617bdeb8979a4bf Mon Sep 17 00:00:00 2001
From: Stefan Kost <ensonic users sf net>
Date: Tue, 3 May 2011 17:21:57 +0300
Subject: [PATCH 1/4] xpath: annotate branch prediction

---
 include/libxml/xpathInternals.h |   29 ++++++++++++++------
 xpath.c                         |   56 ++++++++++++++++++++------------------
 2 files changed, 49 insertions(+), 36 deletions(-)

diff --git a/include/libxml/xpathInternals.h b/include/libxml/xpathInternals.h
index dcd5243..f384e1a 100644
--- a/include/libxml/xpathInternals.h
+++ b/include/libxml/xpathInternals.h
@@ -21,6 +21,17 @@
 extern "C" {
 #endif
 
+/*
+ * Ideally have this for whole libxml2
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
+#define XML_LIKELY(expr) (__builtin_expect ((expr), 1))
+#define XML_UNLIKELY(expr) (__builtin_expect ((expr), 0))
+#else
+#define XML_LIKELY(expr) (expr)
+#define XML_UNLIKELY(expr) (expr)
+#endif
+
 /************************************************************************
  *									*
  *			Helpers						*
@@ -237,7 +248,7 @@ XMLPUBFUN void * XMLCALL
  * Macro to return from the function if an XPath error was detected.
  */
 #define CHECK_ERROR							\
-    if (ctxt->error != XPATH_EXPRESSION_OK) return
+    if (XML_UNLIKELY (ctxt->error != XPATH_EXPRESSION_OK)) return
 
 /**
  * CHECK_ERROR0:
@@ -245,7 +256,7 @@ XMLPUBFUN void * XMLCALL
  * Macro to return 0 from the function if an XPath error was detected.
  */
 #define CHECK_ERROR0							\
-    if (ctxt->error != XPATH_EXPRESSION_OK) return(0)
+    if (XML_UNLIKELY (ctxt->error != XPATH_EXPRESSION_OK)) return(0)
 
 /**
  * XP_ERROR:
@@ -273,7 +284,7 @@ XMLPUBFUN void * XMLCALL
  * type.
  */
 #define CHECK_TYPE(typeval)						\
-    if ((ctxt->value == NULL) || (ctxt->value->type != typeval))	\
+    if (XML_UNLIKELY ((ctxt->value == NULL) || (ctxt->value->type != typeval)))	\
         XP_ERROR(XPATH_INVALID_TYPE)
 
 /**
@@ -284,7 +295,7 @@ XMLPUBFUN void * XMLCALL
  * type. Return(0) in case of failure
  */
 #define CHECK_TYPE0(typeval)						\
-    if ((ctxt->value == NULL) || (ctxt->value->type != typeval))	\
+    if (XML_UNLIKELY ((ctxt->value == NULL) || (ctxt->value->type != typeval)))	\
         XP_ERROR0(XPATH_INVALID_TYPE)
 
 /**
@@ -294,8 +305,8 @@ XMLPUBFUN void * XMLCALL
  * Macro to check that the number of args passed to an XPath function matches.
  */
 #define CHECK_ARITY(x)							\
-    if (ctxt == NULL) return;						\
-    if (nargs != (x))							\
+    if (XML_UNLIKELY (ctxt == NULL)) return;						\
+    if (XML_UNLIKELY (nargs != (x)))							\
         XP_ERROR(XPATH_INVALID_ARITY);
 
 /**
@@ -304,7 +315,7 @@ XMLPUBFUN void * XMLCALL
  * Macro to try to cast the value on the top of the XPath stack to a string.
  */
 #define CAST_TO_STRING							\
-    if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_STRING))	\
+    if (XML_LIKELY ((ctxt->value != NULL) && (ctxt->value->type != XPATH_STRING)))	\
         xmlXPathStringFunction(ctxt, 1);
 
 /**
@@ -313,7 +324,7 @@ XMLPUBFUN void * XMLCALL
  * Macro to try to cast the value on the top of the XPath stack to a number.
  */
 #define CAST_TO_NUMBER							\
-    if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_NUMBER))	\
+    if (XML_LIKELY ((ctxt->value != NULL) && (ctxt->value->type != XPATH_NUMBER)))	\
         xmlXPathNumberFunction(ctxt, 1);
 
 /**
@@ -322,7 +333,7 @@ XMLPUBFUN void * XMLCALL
  * Macro to try to cast the value on the top of the XPath stack to a boolean.
  */
 #define CAST_TO_BOOLEAN							\
-    if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_BOOLEAN))	\
+    if (XML_LIKELY ((ctxt->value != NULL) && (ctxt->value->type != XPATH_BOOLEAN)))	\
         xmlXPathBooleanFunction(ctxt, 1);
 
 /*
diff --git a/xpath.c b/xpath.c
index 608fe00..579db1b 100644
--- a/xpath.c
+++ b/xpath.c
@@ -2410,7 +2410,7 @@ valuePop(xmlXPathParserContextPtr ctxt)
 {
     xmlXPathObjectPtr ret;
 
-    if ((ctxt == NULL) || (ctxt->valueNr <= 0))
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->valueNr <= 0)))
         return (NULL);
     ctxt->valueNr--;
     if (ctxt->valueNr > 0)
@@ -2433,8 +2433,9 @@ valuePop(xmlXPathParserContextPtr ctxt)
 int
 valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
 {
-    if ((ctxt == NULL) || (value == NULL)) return(-1);
-    if (ctxt->valueNr >= ctxt->valueMax) {
+    if (XML_UNLIKELY((ctxt == NULL) || (value == NULL)))
+        return(-1);
+    if (XML_UNLIKELY(ctxt->valueNr >= ctxt->valueMax)) {
         xmlXPathObjectPtr *tmp;
 
         tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
@@ -7524,7 +7525,7 @@ typedef xmlNodeSetPtr (*xmlXPathNodeSetMergeFunction)
  */
 xmlNodePtr
 xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if (cur == NULL)
         return(ctxt->context->node);
     return(NULL);
@@ -7542,10 +7543,11 @@ xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 xmlNodePtr
 xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
-    if (cur == NULL) {
-	if (ctxt->context->node == NULL) return(NULL);
-	switch (ctxt->context->node->type) {
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
+    if (XML_UNLIKELY(cur == NULL)) {
+        cur = ctxt->context->node;
+	if (XML_UNLIKELY(cur == NULL)) return(NULL);
+	switch (cur->type) {
             case XML_ELEMENT_NODE:
             case XML_TEXT_NODE:
             case XML_CDATA_SECTION_NODE:
@@ -7555,7 +7557,7 @@ xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
             case XML_COMMENT_NODE:
             case XML_NOTATION_NODE:
             case XML_DTD_NODE:
-		return(ctxt->context->node->children);
+		return(cur->children);
             case XML_DOCUMENT_NODE:
             case XML_DOCUMENT_TYPE_NODE:
             case XML_DOCUMENT_FRAG_NODE:
@@ -7563,7 +7565,7 @@ xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
 #ifdef LIBXML_DOCB_ENABLED
 	    case XML_DOCB_DOCUMENT_NODE:
 #endif
-		return(((xmlDocPtr) ctxt->context->node)->children);
+		return(((xmlDocPtr) cur)->children);
 	    case XML_ELEMENT_DECL:
 	    case XML_ATTRIBUTE_DECL:
 	    case XML_ENTITY_DECL:
@@ -7575,8 +7577,8 @@ xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
 	}
 	return(NULL);
     }
-    if ((cur->type == XML_DOCUMENT_NODE) ||
-        (cur->type == XML_HTML_DOCUMENT_NODE))
+    if (XML_UNLIKELY((cur->type == XML_DOCUMENT_NODE) ||
+        (cur->type == XML_HTML_DOCUMENT_NODE)))
 	return(NULL);
     return(cur->next);
 }
@@ -7593,8 +7595,8 @@ xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 static xmlNodePtr
 xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
-    if (cur == NULL) {
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
+    if (XML_UNLIKELY(cur == NULL)) {
 	cur = ctxt->context->node;
 	if (cur == NULL) return(NULL);
 	/*
@@ -7745,7 +7747,7 @@ next_sibling:
  */
 xmlNodePtr
 xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if (cur == NULL) {
 	if (ctxt->context->node == NULL)
 	    return(NULL);
@@ -7808,7 +7810,7 @@ xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 xmlNodePtr
 xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if (cur == NULL) {
 	if (ctxt->context->node == NULL)
 	    return(NULL);
@@ -7833,7 +7835,7 @@ xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 xmlNodePtr
 xmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     /*
      * the parent of an attribute or namespace node is the element
      * to which the attribute or namespace node is attached
@@ -7906,7 +7908,7 @@ xmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 xmlNodePtr
 xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     /*
      * the parent of an attribute or namespace node is the element
      * to which the attribute or namespace node is attached
@@ -8030,7 +8032,7 @@ xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 xmlNodePtr
 xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if (cur == NULL)
         return(ctxt->context->node);
     return(xmlXPathNextAncestor(ctxt, cur));
@@ -8049,7 +8051,7 @@ xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 xmlNodePtr
 xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
 	(ctxt->context->node->type == XML_NAMESPACE_DECL))
 	return(NULL);
@@ -8074,7 +8076,7 @@ xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 xmlNodePtr
 xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
 	(ctxt->context->node->type == XML_NAMESPACE_DECL))
 	return(NULL);
@@ -8105,7 +8107,7 @@ xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 xmlNodePtr
 xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if ((cur != NULL) && (cur->type  != XML_ATTRIBUTE_NODE) &&
         (cur->type != XML_NAMESPACE_DECL) && (cur->children != NULL))
         return(cur->children);
@@ -8169,7 +8171,7 @@ xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
 xmlNodePtr
 xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
 {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if (cur == NULL) {
         cur = ctxt->context->node;
         if (cur->type == XML_NAMESPACE_DECL)
@@ -8215,7 +8217,7 @@ static xmlNodePtr
 xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
                               xmlNodePtr cur)
 {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if (cur == NULL) {
         cur = ctxt->context->node;
         if (cur == NULL)
@@ -8258,7 +8260,7 @@ xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
  */
 xmlNodePtr
 xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
     if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNamespace) {
         if (ctxt->context->tmpNsList != NULL)
@@ -8295,7 +8297,7 @@ xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 xmlNodePtr
 xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
     if (ctxt->context->node == NULL)
 	return(NULL);
     if (ctxt->context->node->type != XML_ELEMENT_NODE)
@@ -9740,7 +9742,7 @@ xmlXPathParseNCName(xmlXPathParserContextPtr ctxt) {
     xmlChar *ret;
     int count = 0;
 
-    if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
+    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->cur == NULL))) return(NULL);
     /*
      * Accelerator for simple ASCII names
      */
-- 
1.7.1

>From c25ad12939a227dd0ae7cb0c4efd3e27f6e05e8b Mon Sep 17 00:00:00 2001
From: Stefan Kost <ensonic users sf net>
Date: Tue, 3 May 2011 17:22:40 +0300
Subject: [PATCH 2/4] xpath: split traversal into init and next functions

This avoid us checking cur=NULL in next().
---
 xpath.c |   98 ++++++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 57 insertions(+), 41 deletions(-)

diff --git a/xpath.c b/xpath.c
index 579db1b..476ac9d 100644
--- a/xpath.c
+++ b/xpath.c
@@ -7487,6 +7487,12 @@ xmlXPathModValues(xmlXPathParserContextPtr ctxt) {
  *									*
  ************************************************************************/
 
+ /*
+ * A function to initialize traversal.
+ */
+typedef xmlNodePtr (*xmlXPathTraversalStartFunction)
+                    (xmlXPathParserContextPtr ctxt);
+
 /*
  * A traversal function enumerates nodes along an axis.
  * Initially it must be called with NULL, and it indicates
@@ -7584,6 +7590,51 @@ xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
 }
 
 /**
+ * xmlXPathFirstChildElement:
+ * @ctxt:  the XPath Parser context
+ *
+ * Init traversal for the "child" direction and nodes of type element.
+ * The child axis contains the children of the context node in document order.
+ *
+ * Returns the first element following that axis
+ */
+static xmlNodePtr
+xmlXPathFirstChildElement(xmlXPathParserContextPtr ctxt) {
+    xmlNodePtr cur = ctxt->context->node;
+
+    if (XML_UNLIKELY(cur == NULL)) return(NULL);
+    /*
+    * Get the first element child.
+    */
+    switch (cur->type) {
+        case XML_ELEMENT_NODE:
+        case XML_DOCUMENT_FRAG_NODE:
+        case XML_ENTITY_REF_NODE: /* URGENT TODO: entify-refs as well? */
+        case XML_ENTITY_NODE:
+            cur = cur->children;
+            if (cur != NULL) {
+                if (cur->type == XML_ELEMENT_NODE)
+                    return(cur);
+                do {
+                    cur = cur->next;
+                } while ((cur != NULL) &&
+                    (cur->type != XML_ELEMENT_NODE));
+                return(cur);
+            }
+            return(NULL);
+        case XML_DOCUMENT_NODE:
+        case XML_HTML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+        case XML_DOCB_DOCUMENT_NODE:
+#endif
+            return(xmlDocGetRootElement((xmlDocPtr) cur));
+        default:
+            return(NULL);
+    }
+    return(NULL);
+}
+
+/**
  * xmlXPathNextChildElement:
  * @ctxt:  the XPath Parser context
  * @cur:  the current node in the traversal
@@ -7595,40 +7646,6 @@ xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
  */
 static xmlNodePtr
 xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if (XML_UNLIKELY((ctxt == NULL) || (ctxt->context == NULL))) return(NULL);
-    if (XML_UNLIKELY(cur == NULL)) {
-	cur = ctxt->context->node;
-	if (cur == NULL) return(NULL);
-	/*
-	* Get the first element child.
-	*/
-	switch (cur->type) {
-            case XML_ELEMENT_NODE:
-	    case XML_DOCUMENT_FRAG_NODE:
-	    case XML_ENTITY_REF_NODE: /* URGENT TODO: entify-refs as well? */
-            case XML_ENTITY_NODE:
-		cur = cur->children;
-		if (cur != NULL) {
-		    if (cur->type == XML_ELEMENT_NODE)
-			return(cur);
-		    do {
-			cur = cur->next;
-		    } while ((cur != NULL) &&
-			(cur->type != XML_ELEMENT_NODE));
-		    return(cur);
-		}
-		return(NULL);
-            case XML_DOCUMENT_NODE:
-            case XML_HTML_DOCUMENT_NODE:
-#ifdef LIBXML_DOCB_ENABLED
-	    case XML_DOCB_DOCUMENT_NODE:
-#endif
-		return(xmlDocGetRootElement((xmlDocPtr) cur));
-	    default:
-		return(NULL);
-	}
-	return(NULL);
-    }
     /*
     * Get the next sibling element node.
     */
@@ -11979,6 +11996,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
     int hasPredicateRange, hasAxisRange, pos, size, newSize;
     int breakOnFirstHit;
 
+    xmlXPathTraversalStartFunction next_i = NULL;
     xmlXPathTraversalFunction next = NULL;
     /* compound axis traversal */
     xmlXPathTraversalFunctionExt outerNext = NULL;
@@ -12044,6 +12062,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
 		/*
 		* Optimization if an element node type is 'element'.
 		*/
+		next_i = xmlXPathFirstChildElement;
 		next = xmlXPathNextChildElement;
 	    } else
 		next = xmlXPathNextChild;
@@ -12205,13 +12224,9 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
 	* Traverse the axis and test the nodes.
 	*/
 	pos = 0;
-	cur = NULL;
+	cur = next_i ? next_i(ctxt) : next(ctxt, NULL);
 	hasNsNodes = 0;
-        do {
-            cur = next(ctxt, cur);
-            if (cur == NULL)
-                break;
-
+        while (cur) {
 	    /*
 	    * QUESTION TODO: What does the "first" and "last" stuff do?
 	    */
@@ -12390,7 +12405,8 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
                     }
                     break;
 	    } /* switch(test) */
-        } while (cur != NULL);
+            cur = next(ctxt, cur);
+        };
 
 	goto apply_predicates;
 
-- 
1.7.1

>From 7066379eb1ef02f68f1cf66168771e13b39cc765 Mon Sep 17 00:00:00 2001
From: Stefan Kost <ensonic users sf net>
Date: Tue, 3 May 2011 17:25:39 +0300
Subject: [PATCH 4/4] xpath: avoid a memcpy on the expense of temporarily wasting memory

Just allocate a target buffer and fill, instead of printing to a temp buffer and
then dup'ing.
---
 xpath.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/xpath.c b/xpath.c
index 6b2f627..384a36c 100644
--- a/xpath.c
+++ b/xpath.c
@@ -5586,10 +5586,9 @@ xmlXPathCastNumberToString (double val) {
 	    ret = xmlStrdup((const xmlChar *) "0");
 	} else {
 	    /* could be improved */
-	    char buf[100];
-	    xmlXPathFormatNumber(val, buf, 99);
-	    buf[99] = 0;
-	    ret = xmlStrdup((const xmlChar *) buf);
+	    ret = xmlMalloc(100);
+	    xmlXPathFormatNumber(val, ret, 99);
+	    ret[99] = 0;
 	}
     }
     return(ret);
-- 
1.7.1



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]