]> granicus.if.org Git - apache/commitdiff
Merge r1657685 from trunk:
authorRainer Jung <rjung@apache.org>
Tue, 24 Feb 2015 18:25:26 +0000 (18:25 +0000)
committerRainer Jung <rjung@apache.org>
Tue, 24 Feb 2015 18:25:26 +0000 (18:25 +0000)
core: Optimize string concatenation in expression
parser when evaluating a string expression.

We have a relatively small recursion limit of
about 10 operations. This is a compilation
limit (a define). It can be hit if many expr
vars or function calls are concatenated in an
expression that is evaluated as a string not as
a boolean.

The new optimization uses iteration instead of
recursion and is very similar to the
existing one, which optimizes consecutive
concatenations in node2 of the tree. The new
one optimizes consecutive concatenations in
node 1.

Submitted by: rjung
Reviewed by: rjung, ylavic, covener
Backported by: rjung

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1662075 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
server/util_expr_eval.c

diff --git a/CHANGES b/CHANGES
index ef32d263841b2dcab31da1f176d3fae1a6ccb52d..54f0c3b9914814e66e222fe56528e35f064d8013 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,9 @@
 
 Changes with Apache 2.4.13
 
+  *) core: Optimize string concatenation in expression parser when evaluating
+     a string expression. [Rainer Jung]
+
   *) acinclude.m4: Generate #LoadModule directive in default httpd.conf for
      every --enable-mpms-shared. PR 53882.  [olli hauer <ohauer gmx.de>,
      Yann Ylavic]
diff --git a/STATUS b/STATUS
index c623baaa0a54634322eae64b86b7623b10f2791a..05162f2978cefafe97d2dc8bf82360c915640e35 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -112,17 +112,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
      2.4.x patch: trunk works (module CHANGES)
      +1: ylavic, wrowe, minfrin
 
-   * Expression parser: Optimize another concatenation case by using iteration
-     instead of recursion.
-     We have a relatively small recursion limit of about 10 operations. This
-     is a compilation limit (a define). It can be hit if many expr vars or
-     function calls are concatenated. The new optimization is very similar to
-     the existing one, which optimizes consecutive concatenations in node2 of
-     the tree. The new one optimizes consecutive concatenations in node 1.
-     trunk patch: http://svn.apache.org/r1657685
-     2.4.x patch: trunk works (modulo CHANGES)
-     +1: rjung, ylavic, covener
-
    * Save a few bytes in conf pool when parsing some directives. Use temp_pool
      when applicable.
      trunk patch: http://svn.apache.org/r1657692
index ebdbe2ae2029cd1747a9a70ffd11661283b4d47c..1038e7aeed9c74c6161aa7d9d56d7cb329b35160 100644 (file)
@@ -96,7 +96,8 @@ static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
                                   node->node_arg2);
         break;
     case op_Concat:
-        if (((ap_expr_t *)node->node_arg2)->node_op != op_Concat) {
+        if (((ap_expr_t *)node->node_arg2)->node_op != op_Concat &&
+            ((ap_expr_t *)node->node_arg1)->node_op != op_Concat) {
             const char *s1 = ap_expr_eval_word(ctx, node->node_arg1);
             const char *s2 = ap_expr_eval_word(ctx, node->node_arg2);
             if (!*s1)
@@ -106,6 +107,30 @@ static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
             else
                 result = apr_pstrcat(ctx->p, s1, s2, NULL);
         }
+        else if (((ap_expr_t *)node->node_arg1)->node_op == op_Concat) {
+            const ap_expr_t *nodep = node;
+            int n;
+            int i = 1;
+            struct iovec *vec;
+            do {
+                nodep = nodep->node_arg1;
+                i++;
+            } while (nodep->node_op == op_Concat);
+            vec = apr_palloc(ctx->p, i * sizeof(struct iovec));
+            n = i;
+            nodep = node;
+            i--;
+            do {
+                vec[i].iov_base = (void *)ap_expr_eval_word(ctx,
+                                                            nodep->node_arg2);
+                vec[i].iov_len = strlen(vec[i].iov_base);
+                i--;
+                nodep = nodep->node_arg1;
+            } while (nodep->node_op == op_Concat);
+            vec[i].iov_base = (void *)ap_expr_eval_word(ctx, nodep);
+            vec[i].iov_len = strlen(vec[i].iov_base);
+            result = apr_pstrcatv(ctx->p, vec, n, NULL);
+        }
         else {
             const ap_expr_t *nodep = node;
             int i = 1;