summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15>2013-03-25 12:34:26 +0000
committerzherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15>2013-03-25 12:34:26 +0000
commit6469f5ed634524d61f03fd5b33048c93c39ee351 (patch)
tree5bb2ec943a080365cb974c3a900aadcb781b129f
parentdcc385a5c3dd9743e5dc63f99bb302be4cf51e80 (diff)
downloadpcre-6469f5ed634524d61f03fd5b33048c93c39ee351.tar.gz
Control verbs are handled in the same way in JIT and interpreter.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1300 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r--ChangeLog6
-rw-r--r--pcre_jit_compile.c73
-rw-r--r--pcre_jit_test.c13
3 files changed, 55 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index 50c70f1..3a2b342 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -104,9 +104,9 @@ Version 8.33 xx-xxxx-201x
27. Fix the case where there are two or more SKIPs with arguments that may be
ignored.
-28. Experimental support of (*SKIP) backtracking verb in the JIT compiler.
+28. (*SKIP) is now supported by the JIT compiler.
-29. Experimental support of (*THEN) backtracking verb in the JIT compiler.
+29. (*THEN) is now supported by the JIT compiler.
30. Update RunTest with additional test selector options.
@@ -125,6 +125,8 @@ Version 8.33 xx-xxxx-201x
have been moved to test 1, because either Perl or PCRE has changed, and
these tests are now compatible.
+32. Control verbs are handled in the same way in JIT and interpreter.
+
Version 8.32 30-November-2012
-----------------------------
diff --git a/pcre_jit_compile.c b/pcre_jit_compile.c
index 8b69471..f1d7352 100644
--- a/pcre_jit_compile.c
+++ b/pcre_jit_compile.c
@@ -356,8 +356,10 @@ typedef struct compiler_common {
BOOL has_then;
/* Needs to know the start position anytime. */
BOOL needs_start_ptr;
- /* Currently in recurse or assert. */
+ /* Currently in recurse. */
BOOL local_exit;
+ /* Currently in assert. */
+ int then_local_exit;
/* Newline control. */
int nltype;
int newline;
@@ -382,6 +384,7 @@ typedef struct compiler_common {
recurse_entry *currententry;
jump_list *partialmatch;
jump_list *quit;
+ jump_list *then_quit;
jump_list *forced_quit;
jump_list *accept;
jump_list *calllimit;
@@ -5500,11 +5503,10 @@ jump_list *tmp = NULL;
jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;
jump_list **found;
/* Saving previous accept variables. */
-BOOL save_local_exit = common->local_exit;
+int save_then_local_exit = common->then_local_exit;
then_trap_backtrack *save_then_trap = common->then_trap;
-struct sljit_label *save_quit_label = common->quit_label;
struct sljit_label *save_accept_label = common->accept_label;
-jump_list *save_quit = common->quit;
+jump_list *save_then_quit = common->then_quit;
jump_list *save_accept = common->accept;
struct sljit_jump *jump;
struct sljit_jump *brajump = NULL;
@@ -5574,9 +5576,8 @@ else
}
memset(&altbacktrack, 0, sizeof(backtrack_common));
-common->local_exit = TRUE;
-common->quit_label = NULL;
-common->quit = NULL;
+common->then_local_exit = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? 1 : -1;
+common->then_quit = NULL;
while (1)
{
common->accept_label = NULL;
@@ -5591,11 +5592,10 @@ while (1)
compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
{
- common->local_exit = save_local_exit;
+ common->then_local_exit = save_then_local_exit;
common->then_trap = save_then_trap;
- common->quit_label = save_quit_label;
common->accept_label = save_accept_label;
- common->quit = save_quit;
+ common->then_quit = save_then_quit;
common->accept = save_accept;
return NULL;
}
@@ -5660,11 +5660,10 @@ while (1)
compile_backtrackingpath(common, altbacktrack.top);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
{
- common->local_exit = save_local_exit;
+ common->then_local_exit = save_then_local_exit;
common->then_trap = save_then_trap;
- common->quit_label = save_quit_label;
common->accept_label = save_accept_label;
- common->quit = save_quit;
+ common->then_quit = save_then_quit;
common->accept = save_accept;
return NULL;
}
@@ -5678,10 +5677,10 @@ while (1)
}
/* None of them matched. */
-if (common->quit != NULL)
+if (common->then_quit != NULL)
{
jump = JUMP(SLJIT_JUMP);
- set_jumps(common->quit, LABEL());
+ set_jumps(common->then_quit, LABEL());
SLJIT_ASSERT(framesize != no_stack);
if (framesize < 0)
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));
@@ -5841,11 +5840,10 @@ else
}
}
-common->local_exit = save_local_exit;
+common->then_local_exit = save_then_local_exit;
common->then_trap = save_then_trap;
-common->quit_label = save_quit_label;
common->accept_label = save_accept_label;
-common->quit = save_quit;
+common->then_quit = save_then_quit;
common->accept = save_accept;
return cc + 1 + LINK_SIZE;
}
@@ -8326,22 +8324,35 @@ pcre_uchar opcode = *current->cc;
struct sljit_label *loop;
struct sljit_jump *jump;
-if ((opcode == OP_THEN || opcode == OP_THEN_ARG) && common->then_trap != NULL)
+if (opcode == OP_THEN || opcode == OP_THEN_ARG)
{
- SLJIT_ASSERT(common->control_head_ptr != 0);
+ if (common->then_trap != NULL)
+ {
+ SLJIT_ASSERT(common->control_head_ptr != 0);
- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap);
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start);
- jump = JUMP(SLJIT_JUMP);
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start);
+ jump = JUMP(SLJIT_JUMP);
- loop = LABEL();
- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw));
- JUMPHERE(jump);
- CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop);
- CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop);
- add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));
- return;
+ loop = LABEL();
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw));
+ JUMPHERE(jump);
+ CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop);
+ CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop);
+ add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));
+ return;
+ }
+ else if (common->then_local_exit != 0)
+ {
+ if (common->then_local_exit > 0)
+ add_jump(compiler, &common->then_quit, JUMP(SLJIT_JUMP));
+ else if (common->accept_label == NULL)
+ add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
+ else
+ JUMPTO(SLJIT_JUMP, common->accept_label);
+ return;
+ }
}
if (common->local_exit)
diff --git a/pcre_jit_test.c b/pcre_jit_test.c
index 536b40b..1860323 100644
--- a/pcre_jit_test.c
+++ b/pcre_jit_test.c
@@ -694,12 +694,9 @@ static struct regression_test_case regression_test_cases[] = {
{ MUA, 0 | F_NOMATCH, "a(*COMMIT)b", "ac" },
{ MUA, 0, "aa(*COMMIT)b", "xaxaab" },
{ MUA, 0 | F_NOMATCH, "a(*COMMIT)(*:msg)b|ac", "ac" },
- { MUA, 0, "(?=a(*COMMIT)b|ac)ac|(*:m)(a)c", "ac" },
- { MUA, 0, "(?!a(*COMMIT)(*:msg)b)a(c)|cd", "acd" },
- { MUA, 0, "(?=(a)(*COMMIT)b)|ac", "ac" },
- { MUA, 0, "(?=(a)+(*COMMIT)b)|ac", "ac" },
{ MUA, 0 | F_NOMATCH, "(a(*COMMIT)b)++", "abac" },
{ MUA, 0 | F_NOMATCH, "((a)(*COMMIT)b)++", "abac" },
+ { MUA, 0 | F_NOMATCH, "(?=a(*COMMIT)b)ab|ad", "ad" },
/* (*PRUNE) verb. */
{ MUA, 0, "aa\\K(*PRUNE)b", "aaab" },
@@ -708,6 +705,7 @@ static struct regression_test_case regression_test_cases[] = {
{ MUA, 0, "(a)(a)(a)(a)(a)(a)(a)(a)(*PRUNE)b|(a)", "aaaaaaaa" },
{ MUA | PCRE_PARTIAL_SOFT, 0, "a(*PRUNE)a|", "a" },
{ MUA | PCRE_PARTIAL_SOFT, 0, "a(*PRUNE)a|m", "a" },
+ { MUA, 0 | F_NOMATCH, "(?=a(*PRUNE)b)ab|ad", "ad" },
{ MUA, 0, "a(*COMMIT)(*PRUNE)d|bc", "abc" },
{ MUA, 0, "(?=a(*COMMIT)b)a(*PRUNE)c|bc", "abc" },
{ MUA, 0 | F_NOMATCH, "(*COMMIT)(?=a(*COMMIT)b)a(*PRUNE)c|bc", "abc" },
@@ -732,12 +730,19 @@ static struct regression_test_case regression_test_cases[] = {
{ MUA, 0, "(?>a(*COMMIT)b)??n(*PRUNE)d|bn", "abn" },
{ MUA, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)??n(*PRUNE)d|bn", "abn" },
+ /* (*SKIP) verb. */
+ { MUA, 0 | F_NOMATCH, "(?=a(*SKIP)b)ab|ad", "ad" },
+
/* (*THEN) verb. */
{ MUA, 0, "((?:a(*THEN)|aab)(*THEN)c|a+)+m", "aabcaabcaabcaabcnacm" },
{ MUA, 0 | F_NOMATCH, "((?:a(*THEN)|aab)(*THEN)c|a+)+m", "aabcm" },
{ MUA, 0, "((?:a(*THEN)|aab)c|a+)+m", "aabcaabcnmaabcaabcm" },
{ MUA, 0, "((?:a|aab)(*THEN)c|a+)+m", "aam" },
{ MUA, 0, "((?:a(*COMMIT)|aab)(*THEN)c|a+)+m", "aam" },
+ { MUA, 0, "(?(?=a(*THEN)b)ab|ad)", "ad" },
+ { MUA, 0, "(?(?!a(*THEN)b)ad|add)", "add" },
+ { MUA, 0 | F_NOMATCH, "(?(?=a)a(*THEN)b|ad)", "ad" },
+ { MUA, 0, "(?!(?(?=a)ab|b(*THEN)d))bn|bnn", "bnn" },
/* Deep recursion. */
{ MUA, 0, "((((?:(?:(?:\\w)+)?)*|(?>\\w)+?)+|(?>\\w)?\?)*)?\\s", "aaaaa+ " },