[Pcre-svn] [677] code/trunk: Adjust JIT limit code; make JI…

トップ ページ
このメッセージを削除
著者: Subversion repository
日付:  
To: pcre-svn
題目: [Pcre-svn] [677] code/trunk: Adjust JIT limit code; make JIT test return 1 if not successful.
Revision: 677
          http://vcs.pcre.org/viewvc?view=rev&revision=677
Author:   ph10
Date:     2011-08-28 11:50:07 +0100 (Sun, 28 Aug 2011)


Log Message:
-----------
Adjust JIT limit code; make JIT test return 1 if not successful.

Modified Paths:
--------------
    code/trunk/pcre_exec.c
    code/trunk/pcre_internal.h
    code/trunk/pcre_jit_compile.c
    code/trunk/pcre_jit_test.c


Modified: code/trunk/pcre_exec.c
===================================================================
--- code/trunk/pcre_exec.c    2011-08-27 15:53:04 UTC (rev 676)
+++ code/trunk/pcre_exec.c    2011-08-28 10:50:07 UTC (rev 677)
@@ -5844,8 +5844,9 @@
     && extra_data->executable_jit != NULL
     && (options & ~(PCRE_NO_UTF8_CHECK | PCRE_NOTBOL | PCRE_NOTEOL |
                     PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART)) == 0)
-  return _pcre_jit_exec(re, extra_data->executable_jit, subject, length, 
-    start_offset, options, offsets, offsetcount);
+  return _pcre_jit_exec(re, extra_data->executable_jit, subject, length,
+    start_offset, options, ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0)
+    ? MATCH_LIMIT : extra_data->match_limit, offsets, offsetcount);
 #endif


/* Carry on with non-JIT matching. This information is for finding all the

Modified: code/trunk/pcre_internal.h
===================================================================
--- code/trunk/pcre_internal.h    2011-08-27 15:53:04 UTC (rev 676)
+++ code/trunk/pcre_internal.h    2011-08-28 10:50:07 UTC (rev 677)
@@ -1944,7 +1944,7 @@
 #ifdef SUPPORT_JIT
 extern void          _pcre_jit_compile(const real_pcre *, pcre_extra *);
 extern int           _pcre_jit_exec(const real_pcre *, void *, PCRE_SPTR, 
-                        int, int, int, int *, int);
+                        int, int, int, int, int *, int);
 extern void          _pcre_jit_free(void *);
 #endif



Modified: code/trunk/pcre_jit_compile.c
===================================================================
--- code/trunk/pcre_jit_compile.c    2011-08-27 15:53:04 UTC (rev 676)
+++ code/trunk/pcre_jit_compile.c    2011-08-28 10:50:07 UTC (rev 677)
@@ -152,6 +152,7 @@
   uschar *ptr;
   /* Everything else after. */
   int offsetcount;
+  int calllimit;
   uschar notbol;
   uschar noteol;
   uschar notempty;
@@ -280,6 +281,7 @@
   recurse_entry *entries;
   recurse_entry *currententry;
   jump_list *accept;
+  jump_list *calllimit;
   jump_list *stackalloc;
   jump_list *revertframes;
   jump_list *wordboundary;
@@ -355,15 +357,19 @@
 #define LOCALS_HEAD      (4 * sizeof(sljit_w))
 /* Head of the last recursion. */
 #define RECURSIVE_HEAD   (5 * sizeof(sljit_w))
+/* Number of recursions. */
+#define CALL_COUNT       (6 * sizeof(sljit_w))
+/* Max limit of recursions. */
+#define CALL_LIMIT       (7 * sizeof(sljit_w))
 /* Last known position of the requested byte. */
-#define REQ_BYTE_PTR     (6 * sizeof(sljit_w))
+#define REQ_BYTE_PTR     (8 * sizeof(sljit_w))
 /* End pointer of the first line. */
-#define FIRSTLINE_END    (7 * sizeof(sljit_w))
+#define FIRSTLINE_END    (9 * sizeof(sljit_w))
 /* The output vector is stored on the stack, and contains pointers
 to characters. The vector data is divided into two groups: the first
 group contains the start / end character pointers, and the second is
 the start pointers when the end of the capturing group has not yet reached. */
-#define OVECTOR_START    (8 * sizeof(sljit_w))
+#define OVECTOR_START    (10 * sizeof(sljit_w))
 #define OVECTOR(i)       (OVECTOR_START + (i) * sizeof(sljit_w))
 #define OVECTOR_PRIV(i)  (common->cbraptr + (i) * sizeof(sljit_w))
 #define PRIV(cc)         (common->localptrs[(cc) - common->start])
@@ -1175,6 +1181,14 @@
 common->stubs = NULL;
 }


+static SLJIT_INLINE void decrease_call_count(compiler_common *common)
+{
+DEFINE_COMPILER;
+
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_COUNT, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_COUNT, SLJIT_IMM, 1);
+add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));
+}
+
static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
{
/* May destroy all locals and registers except TMP2. */
@@ -3455,6 +3469,8 @@

JUMPHERE(zerolength);
FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
+
+ decrease_call_count(common);
return cc;
}

@@ -3492,6 +3508,8 @@
if (jump != NULL)
JUMPHERE(jump);
JUMPHERE(zerolength);
+
+decrease_call_count(common);
return cc;
}

@@ -4212,6 +4230,9 @@
/* Continue to the normal fallback. */
}

+if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
+ decrease_call_count(common);
+
/* Skip the other alternatives. */
while (*cc == OP_ALT)
cc += GET(cc, 1);
@@ -4436,6 +4457,7 @@

/* None of them matched. */
set_jumps(emptymatch, LABEL());
+decrease_call_count(common);
return cc + 1 + LINK_SIZE;
}

@@ -4696,6 +4718,7 @@
break;
}

+decrease_call_count(common);
return end;
}

@@ -4939,6 +4962,8 @@
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);
       }
     FALLBACK_AS(braminzero_fallback)->hotpath = LABEL();
+    if (cc[1] > OP_ASSERTBACK_NOT)
+      decrease_call_count(common);
     break;


     case OP_ONCE:
@@ -5969,6 +5994,7 @@
 common->entries = NULL;
 common->currententry = NULL;
 common->accept = NULL;
+common->calllimit = NULL;
 common->stackalloc = NULL;
 common->revertframes = NULL;
 common->wordboundary = NULL;
@@ -6025,8 +6051,10 @@
 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
 OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
+OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, calllimit));
 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
 OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0);


/* Main part of the matching */
if ((re->options & PCRE_ANCHORED) == 0)
@@ -6043,8 +6071,11 @@
if ((re->flags & PCRE_REQCHSET) != 0)
reqbyte_notfound = search_requested_char(common, re->req_byte, (re->flags & PCRE_FIRSTSET) != 0);

+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT);
/* Store the current STR_PTR in OVECTOR(0). */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
+/* Copy the limit of allowed recursions. */
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_COUNT, TMP1, 0);

compile_hotpath(common, rootfallback.cc, ccend, &rootfallback);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
@@ -6171,6 +6202,11 @@
OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);
JUMPTO(SLJIT_JUMP, leave);

+/* Call limit reached. */
+set_jumps(common->calllimit, LABEL());
+OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
+JUMPTO(SLJIT_JUMP, leave);
+
if (common->revertframes != NULL)
{
set_jumps(common->revertframes, LABEL());
@@ -6268,8 +6304,8 @@

int
_pcre_jit_exec(const real_pcre *re, void *executable_func,
- PCRE_SPTR subject, int length, int start_offset, int options, int *offsets,
- int offsetcount)
+ PCRE_SPTR subject, int length, int start_offset, int options,
+ int match_limit, int *offsets, int offsetcount)
{
executable_function *function = (executable_function*)executable_func;
union {
@@ -6285,6 +6321,7 @@
arguments.str = subject + start_offset;
arguments.begin = subject;
arguments.end = subject + length;
+arguments.calllimit = match_limit; /* JIT decreases this value less times. */
arguments.notbol = (options & PCRE_NOTBOL) != 0;
arguments.noteol = (options & PCRE_NOTEOL) != 0;
arguments.notempty = (options & PCRE_NOTEMPTY) != 0;

Modified: code/trunk/pcre_jit_test.c
===================================================================
--- code/trunk/pcre_jit_test.c    2011-08-27 15:53:04 UTC (rev 676)
+++ code/trunk/pcre_jit_test.c    2011-08-28 10:50:07 UTC (rev 677)
@@ -60,12 +60,11 @@
 */  


static void setstack(pcre_extra *extra);
-static void regression_tests(void);
+static int regression_tests(void);

 int main(void)
 {
-        regression_tests();
-    return 0;
+        return regression_tests();
 }


static pcre_jit_stack* callback(void *arg)
@@ -567,12 +566,20 @@

     /* Deep recursion. */
     { MUA, 0, "((((?:(?:(?:\\w)+)?)*|(?>\\w)+?)+|(?>\\w)?\?)*)?\\s", "aaaaa+ " },
-    { MUA, 0, "(?:((?:(?:(?:\\w*?)+)??|(?>\\w)?|\\w*+)*)+)+?\\s", "aaa+ " },
+        { MUA, 0, "(?:((?:(?:(?:\\w*?)+)??|(?>\\w)?|\\w*+)*)+)+?\\s", "aa+ " },
+    { MUA, 0, "((a?)+)+b", "aaaaaaaaaaaaa b" },
+ 
+    /* Deep recursion: Stack limit reached. */
+    { MA, 0, "a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaa" },
+    { MA, 0, "(?:a+)+b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },
+    { MA, 0, "(?:a+?)+?b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },
+    { MA, 0, "(?:a*)*b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },
+    { MA, 0, "(?:a*?)*?b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },


     { 0, 0, NULL, NULL }
 };


-static void regression_tests(void)
+static int regression_tests(void)
 {
     pcre *re;
     struct regression_test_case *current = regression_test_cases;
@@ -659,10 +666,13 @@
         succesful++;
     }


-    if (total == succesful)
+    if (total == succesful) {
         printf("\nAll JIT regression tests are successfully passed.\n");
-    else
+        return 0;
+        } else {
         printf("\nSuccessful test ratio: %d%%\n", succesful * 100 / total);
+                return 1;
+        }         
 }


/* End of pcre_jit_test.c */