[Pcre-svn] [221] code/trunk/src: Assertion code generator in…

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [221] code/trunk/src: Assertion code generator in JIT has been optimized.
Revision: 221
          http://www.exim.org/viewvc/pcre2?view=rev&revision=221
Author:   zherczeg
Date:     2015-03-12 11:21:38 +0000 (Thu, 12 Mar 2015)


Log Message:
-----------
Assertion code generator in JIT has been optimized.

Modified Paths:
--------------
    code/trunk/src/pcre2_jit_compile.c
    code/trunk/src/pcre2_jit_test.c


Modified: code/trunk/src/pcre2_jit_compile.c
===================================================================
--- code/trunk/src/pcre2_jit_compile.c    2015-03-11 17:44:16 UTC (rev 220)
+++ code/trunk/src/pcre2_jit_compile.c    2015-03-12 11:21:38 UTC (rev 221)
@@ -1393,6 +1393,9 @@
     case OP_NCLASS:
     case OP_XCLASS:


+    case OP_CALLOUT:
+    case OP_CALLOUT_STR:
+
     cc = next_opcode(common, cc);
     SLJIT_ASSERT(cc != NULL);
     break;
@@ -2092,6 +2095,7 @@
 /* May destroy all locals and registers except TMP2. */
 DEFINE_COMPILER;


+SLJIT_ASSERT(size > 0);
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
#ifdef DESTROY_REGISTERS
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
@@ -2106,6 +2110,7 @@
static SLJIT_INLINE void free_stack(compiler_common *common, int size)
{
DEFINE_COMPILER;
+SLJIT_ASSERT(size > 0);
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
}

@@ -6401,6 +6406,32 @@
#undef CALLOUT_ARG_SIZE
#undef CALLOUT_ARG_OFFSET

+static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(PCRE2_SPTR cc)
+{
+while (TRUE)
+  {
+  switch (*cc)
+    {
+    case OP_CALLOUT_STR:
+    cc += GET(cc, 1 + 2*LINK_SIZE);
+    break;
+
+    case OP_NOT_WORD_BOUNDARY:
+    case OP_WORD_BOUNDARY:
+    case OP_CALLOUT:
+    case OP_ALT:
+    cc += PRIV(OP_lengths)[*cc];
+    break;
+
+    case OP_KET:
+    return FALSE;
+
+    default:
+    return TRUE;
+    }
+  }
+}
+
 static PCRE2_SPTR compile_assert_matchingpath(compiler_common *common, PCRE2_SPTR cc, assert_backtrack *backtrack, BOOL conditional)
 {
 DEFINE_COMPILER;
@@ -6457,15 +6488,28 @@


 if (framesize < 0)
   {
-  extrasize = needs_control_head ? 2 : 1;
+  extrasize = 1;
+  if (bra == OP_BRA && !assert_needs_str_ptr_saving(ccbegin + 1 + LINK_SIZE))
+    extrasize = 0;
+
+  if (needs_control_head)
+    extrasize++;
+
   if (framesize == no_frame)
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);
-  allocate_stack(common, extrasize);
+
+  if (extrasize > 0)
+    allocate_stack(common, extrasize);
+
   if (needs_control_head)
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
-  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+
+  if (extrasize > 0)
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+
   if (needs_control_head)
     {
+    SLJIT_ASSERT(extrasize == 2);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
     }
@@ -6474,12 +6518,14 @@
   {
   extrasize = needs_control_head ? 3 : 2;
   allocate_stack(common, framesize + extrasize);
+
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
   OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);
   if (needs_control_head)
     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+
   if (needs_control_head)
     {
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
@@ -6488,6 +6534,7 @@
     }
   else
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
+
   init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE);
   }


@@ -6511,7 +6558,7 @@
altbacktrack.top = NULL;
altbacktrack.topbacktracks = NULL;

-  if (*ccbegin == OP_ALT)
+  if (*ccbegin == OP_ALT && extrasize > 0)
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));


   altbacktrack.cc = ccbegin;
@@ -6540,8 +6587,9 @@
     {
     if (framesize == no_frame)
       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
-    else
+    else if (extrasize > 0)
       free_stack(common, extrasize);
+
     if (needs_control_head)
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0);
     }
@@ -6567,7 +6615,10 @@
     {
     /* We know that STR_PTR was stored on the top of the stack. */
     if (conditional)
-      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0);
+      {
+      if (extrasize > 0)
+        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0);
+      }
     else if (bra == OP_BRAZERO)
       {
       if (framesize < 0)
@@ -6644,7 +6695,7 @@
 if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
   {
   /* Assert is failed. */
-  if (conditional || bra == OP_BRAZERO)
+  if ((conditional && extrasize > 0) || bra == OP_BRAZERO)
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));


   if (framesize < 0)
@@ -6656,7 +6707,7 @@
         free_stack(common, 1);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
       }
-    else
+    else if (extrasize > 0)
       free_stack(common, extrasize);
     }
   else
@@ -6681,7 +6732,9 @@
   if (framesize < 0)
     {
     /* We know that STR_PTR was stored on the top of the stack. */
-    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw));
+    if (extrasize > 0)
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw));
+
     /* Keep the STR_PTR on the top of the stack. */
     if (bra == OP_BRAZERO)
       {
@@ -6744,14 +6797,16 @@
   /* AssertNot is successful. */
   if (framesize < 0)
     {
-    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+    if (extrasize > 0)
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+
     if (bra != OP_BRA)
       {
       if (extrasize == 2)
         free_stack(common, 1);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
       }
-    else
+    else if (extrasize > 0)
       free_stack(common, extrasize);
     }
   else
@@ -6813,7 +6868,9 @@
     stacksize = needs_control_head ? 1 : 0;
     if (ket != OP_KET || has_alternatives)
       stacksize++;
-    free_stack(common, stacksize);
+
+    if (stacksize > 0)
+      free_stack(common, stacksize);
     }


   if (needs_control_head)
@@ -9203,8 +9260,10 @@
     /* The STR_PTR must be released. */
     stacksize++;
     }
-  free_stack(common, stacksize);


+  if (stacksize > 0)
+    free_stack(common, stacksize);
+
   JUMPHERE(once);
   /* Restore previous private_data_ptr */
   if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)


Modified: code/trunk/src/pcre2_jit_test.c
===================================================================
--- code/trunk/src/pcre2_jit_test.c    2015-03-11 17:44:16 UTC (rev 220)
+++ code/trunk/src/pcre2_jit_test.c    2015-03-12 11:21:38 UTC (rev 221)
@@ -579,6 +579,16 @@
     { MU, A, 0, 0, "(?:(?=.)??[a-c])+m", "abacdcbacacdcaccam" },
     { MU, A, 0, 0, "((?!a)?(?!([^a]))?)+$", "acbab" },
     { MU, A, 0, 0, "((?!a)?\?(?!([^a]))?\?)+$", "acbab" },
+    { MU, A, 0, 0, "a(?=(?C)\\B(?C`x`))b", "ab" },
+    { MU, A, 0, 0, "a(?!(?C)\\B(?C`x`))bb|ab", "abb" },
+    { MU, A, 0, 0, "a(?=\\b|(?C)\\B(?C`x`))b", "ab" },
+    { MU, A, 0, 0, "a(?!\\b|(?C)\\B(?C`x`))bb|ab", "abb" },
+    { MU, A, 0, 0, "c(?(?=(?C)\\B(?C`x`))ab|a)", "cab" },
+    { MU, A, 0, 0, "c(?(?!(?C)\\B(?C`x`))ab|a)", "cab" },
+    { MU, A, 0, 0, "c(?(?=\\b|(?C)\\B(?C`x`))ab|a)", "cab" },
+    { MU, A, 0, 0, "c(?(?!\\b|(?C)\\B(?C`x`))ab|a)", "cab" },
+    { MU, A, 0, 0, "a(?=)b", "ab" },
+    { MU, A, 0, 0 | F_NOMATCH, "a(?!)b", "ab" },


     /* Not empty, ACCEPT, FAIL */
     { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a*", "bcx" },