diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | pcre_jit_compile.c | 73 | ||||
-rw-r--r-- | pcre_jit_test.c | 13 |
3 files changed, 55 insertions, 37 deletions
@@ -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+ " }, |