diff options
author | zherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2012-02-28 11:33:34 +0000 |
---|---|---|
committer | zherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2012-02-28 11:33:34 +0000 |
commit | 82e768d97aaa919496bc8c81924ef25045df5597 (patch) | |
tree | 05e16545265a0c437628e40d843c425149b958e4 | |
parent | 6ceabc3f2a47d73edeaf4bf0f2f3c9fea52dfb3d (diff) | |
download | pcre-82e768d97aaa919496bc8c81924ef25045df5597.tar.gz |
(COMMIT*) is now supported by the JIT compiler
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@941 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | pcre_exec.c | 7 | ||||
-rw-r--r-- | pcre_internal.h | 8 | ||||
-rw-r--r-- | pcre_jit_compile.c | 78 | ||||
-rw-r--r-- | pcre_jit_test.c | 7 | ||||
-rw-r--r-- | testdata/testinput12 | 2 | ||||
-rw-r--r-- | testdata/testoutput12 | 2 |
7 files changed, 79 insertions, 27 deletions
@@ -63,6 +63,8 @@ Version 8.31 15. It is now possible to link pcretest with libedit as an alternative to libreadline. +16. (*COMMIT) control verb is now supported by the JIT compiler. + Version 8.30 04-February-2012 ----------------------------- diff --git a/pcre_exec.c b/pcre_exec.c index 26f05d8..e7f0e30 100644 --- a/pcre_exec.c +++ b/pcre_exec.c @@ -6469,11 +6469,8 @@ if (extra_data != NULL PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD)) == 0) { - rc = PRIV(jit_exec)(re, extra_data->executable_jit, - (const pcre_uchar *)subject, length, start_offset, options, - ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) - ? MATCH_LIMIT : extra_data->match_limit, offsets, offsetcount, - ((extra_data->flags & PCRE_EXTRA_MARK) != 0) ? extra_data->mark : NULL); + rc = PRIV(jit_exec)(re, extra_data, (const pcre_uchar *)subject, length, + start_offset, options, offsets, offsetcount); /* PCRE_ERROR_NULL means that the selected normal or partial matching mode is not compiled. In this case we simply fallback to interpreter. */ diff --git a/pcre_internal.h b/pcre_internal.h index 3da9013..3e434ae 100644 --- a/pcre_internal.h +++ b/pcre_internal.h @@ -2296,10 +2296,10 @@ extern BOOL PRIV(was_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR, extern BOOL PRIV(xclass)(int, const pcre_uchar *, BOOL); #ifdef SUPPORT_JIT -extern void PRIV(jit_compile)(const REAL_PCRE *, PUBL(extra) *, int); -extern int PRIV(jit_exec)(const REAL_PCRE *, void *, - const pcre_uchar *, int, int, int, int, int *, int, - pcre_uchar **); +extern void PRIV(jit_compile)(const REAL_PCRE *, + PUBL(extra) *, int); +extern int PRIV(jit_exec)(const REAL_PCRE *, const PUBL(extra) *, + const pcre_uchar *, int, int, int, int *, int); extern void PRIV(jit_free)(void *); extern int PRIV(jit_get_size)(void *); extern const char* PRIV(jit_get_target)(void); diff --git a/pcre_jit_compile.c b/pcre_jit_compile.c index 54a285c..bc2145b 100644 --- a/pcre_jit_compile.c +++ b/pcre_jit_compile.c @@ -307,11 +307,13 @@ typedef struct compiler_common { /* Labels and jump lists. */ struct sljit_label *partialmatchlabel; + struct sljit_label *leavelabel; struct sljit_label *acceptlabel; stub_list *stubs; recurse_entry *entries; recurse_entry *currententry; jump_list *partialmatch; + jump_list *leave; jump_list *accept; jump_list *calllimit; jump_list *stackalloc; @@ -517,6 +519,7 @@ switch(*cc) case OP_BRAZERO: case OP_BRAMINZERO: case OP_BRAPOSZERO: + case OP_COMMIT: case OP_FAIL: case OP_ACCEPT: case OP_ASSERT_ACCEPT: @@ -4159,7 +4162,7 @@ if (common->has_set_som && common->mark_ptr != 0) } else if (common->has_set_som || common->mark_ptr != 0) { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (OVECTOR(0)) : common->mark_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr); allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } @@ -4186,10 +4189,12 @@ jump_list *tmp = NULL; jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks; jump_list **found; /* Saving previous accept variables. */ +struct sljit_label *save_leavelabel = common->leavelabel; struct sljit_label *save_acceptlabel = common->acceptlabel; +jump_list *save_leave = common->leave; +jump_list *save_accept = common->accept; struct sljit_jump *jump; struct sljit_jump *brajump = NULL; -jump_list *save_accept = common->accept; if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) { @@ -4234,6 +4239,8 @@ else } memset(&altfallback, 0, sizeof(fallback_common)); +common->leavelabel = NULL; +common->leave = NULL; while (1) { common->acceptlabel = NULL; @@ -4248,7 +4255,9 @@ while (1) compile_hotpath(common, ccbegin + 1 + LINK_SIZE, cc, &altfallback); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { + common->leavelabel = save_leavelabel; common->acceptlabel = save_acceptlabel; + common->leave = save_leave; common->accept = save_accept; return NULL; } @@ -4301,7 +4310,9 @@ while (1) compile_fallbackpath(common, altfallback.top); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { + common->leavelabel = save_leavelabel; common->acceptlabel = save_acceptlabel; + common->leave = save_leave; common->accept = save_accept; return NULL; } @@ -4314,6 +4325,8 @@ while (1) cc += GET(cc, 1); } /* None of them matched. */ +if (common->leave != NULL) + set_jumps(common->leave, LABEL()); if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) { @@ -4438,7 +4451,9 @@ else } } +common->leavelabel = save_leavelabel; common->acceptlabel = save_acceptlabel; +common->leave = save_leave; common->accept = save_accept; return cc + 1 + LINK_SIZE; } @@ -5810,6 +5825,11 @@ while (cc < ccend) cc += 1 + 2 + cc[1]; break; + case OP_COMMIT: + PUSH_FALLBACK_NOVALUE(sizeof(fallback_common), cc); + cc += 1; + break; + case OP_FAIL: case OP_ACCEPT: case OP_ASSERT_ACCEPT: @@ -6016,7 +6036,7 @@ else if (common->has_set_som || common->mark_ptr != 0) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (OVECTOR(0)) : common->mark_ptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0); } } @@ -6659,6 +6679,14 @@ while (current) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0); break; + case OP_COMMIT: + OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); + if (common->leavelabel == NULL) + add_jump(compiler, &common->leave, JUMP(SLJIT_JUMP)); + else + JUMPTO(SLJIT_JUMP, common->leavelabel); + break; + case OP_FAIL: case OP_ACCEPT: case OP_ASSERT_ACCEPT: @@ -6684,6 +6712,8 @@ int framesize = get_framesize(common, cc, TRUE); int alternativesize; BOOL needsframe; fallback_common altfallback; +struct sljit_label *save_leavelabel = common->leavelabel; +jump_list *save_leave = common->leave; struct sljit_jump *jump; SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS); @@ -6708,7 +6738,9 @@ if (alternativesize > 0) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); memset(&altfallback, 0, sizeof(fallback_common)); +common->leavelabel = NULL; common->acceptlabel = NULL; +common->leave = NULL; common->accept = NULL; altfallback.cc = ccbegin; cc += GET(cc, 1); @@ -6722,13 +6754,21 @@ while (1) compile_hotpath(common, altfallback.cc, cc, &altfallback); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + { + common->leavelabel = save_leavelabel; + common->leave = save_leave; return; + } add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); compile_fallbackpath(common, altfallback.top); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + { + common->leavelabel = save_leavelabel; + common->leave = save_leave; return; + } set_jumps(altfallback.topfallbacks, LABEL()); if (*cc != OP_ALT) @@ -6738,6 +6778,9 @@ while (1) cc += GET(cc, 1); } /* None of them matched. */ +if (common->leave != NULL) + set_jumps(common->leave, LABEL()); + OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); jump = JUMP(SLJIT_JUMP); @@ -6758,6 +6801,9 @@ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_w)); OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head, TMP2, 0); sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0); + +common->leavelabel = save_leavelabel; +common->leave = save_leave; } #undef COMPILE_FALLBACKPATH @@ -6776,7 +6822,6 @@ pcre_uchar *ccend; executable_functions *functions; void *executable_func; sljit_uw executable_size; -struct sljit_label *leave; struct sljit_label *mainloop = NULL; struct sljit_label *empty_match_found; struct sljit_label *empty_match_fallback; @@ -6967,14 +7012,16 @@ if (common->accept != NULL) /* This means we have a match. Update the ovector. */ copy_ovector(common, re->top_bracket + 1); -leave = LABEL(); +common->leavelabel = LABEL(); +if (common->leave != NULL) + set_jumps(common->leave, common->leavelabel); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); if (mode != JIT_COMPILE) { common->partialmatchlabel = LABEL(); set_jumps(common->partialmatch, common->partialmatchlabel); - return_with_partial_match(common, leave); + return_with_partial_match(common, common->leavelabel); } empty_match_fallback = LABEL(); @@ -7038,7 +7085,7 @@ if (mode == JIT_PARTIAL_SOFT_COMPILE) CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0, common->partialmatchlabel); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); -JUMPTO(SLJIT_JUMP, leave); +JUMPTO(SLJIT_JUMP, common->leavelabel); flush_stubs(common); @@ -7091,12 +7138,12 @@ sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); JUMPHERE(jump); /* We break the return address cache here, but this is a really rare case. */ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT); -JUMPTO(SLJIT_JUMP, leave); +JUMPTO(SLJIT_JUMP, common->leavelabel); /* Call limit reached. */ set_jumps(common->calllimit, LABEL()); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT); -JUMPTO(SLJIT_JUMP, leave); +JUMPTO(SLJIT_JUMP, common->leavelabel); if (common->revertframes != NULL) { @@ -7203,11 +7250,10 @@ return convert_executable_func.call_executable_func(arguments); } int -PRIV(jit_exec)(const REAL_PCRE *re, void *executable_funcs, - const pcre_uchar *subject, int length, int start_offset, int options, - int match_limit, int *offsets, int offsetcount, pcre_uchar **mark_ptr) +PRIV(jit_exec)(const REAL_PCRE *re, const PUBL(extra) *extra_data, const pcre_uchar *subject, + int length, int start_offset, int options, int *offsets, int offsetcount) { -executable_functions *functions = (executable_functions *)executable_funcs; +executable_functions *functions = (executable_functions *)extra_data->executable_jit; union { void* executable_func; jit_function call_executable_func; @@ -7232,7 +7278,7 @@ arguments.begin = subject; arguments.end = subject + length; arguments.mark_ptr = NULL; /* JIT decreases this value less frequently than the interpreter. */ -arguments.calllimit = match_limit; +arguments.calllimit = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : extra_data->match_limit; arguments.notbol = (options & PCRE_NOTBOL) != 0; arguments.noteol = (options & PCRE_NOTEOL) != 0; arguments.notempty = (options & PCRE_NOTEMPTY) != 0; @@ -7267,8 +7313,8 @@ else if (retval * 2 > offsetcount) retval = 0; -if (mark_ptr != NULL) - *mark_ptr = arguments.mark_ptr; +if ((extra_data->flags & PCRE_EXTRA_MARK) != 0) + *(extra_data->mark) = arguments.mark_ptr; return retval; } diff --git a/pcre_jit_test.c b/pcre_jit_test.c index e0bd702..dc06e2d 100644 --- a/pcre_jit_test.c +++ b/pcre_jit_test.c @@ -679,6 +679,13 @@ static struct regression_test_case regression_test_cases[] = { { MUA, 0, "(a\\K(*:aa)){0}(?:b(?1)b)+", "babba" }, { MUA, 0 | F_NOMATCH, "(a\\K(*:aa)){0}(?:b(?1)b)+", "ba" }, + /* (*COMMIT) verb. */ + { 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" }, + /* Deep recursion. */ { MUA, 0, "((((?:(?:(?:\\w)+)?)*|(?>\\w)+?)+|(?>\\w)?\?)*)?\\s", "aaaaa+ " }, { MUA, 0, "(?:((?:(?:(?:\\w*?)+)??|(?>\\w)?|\\w*+)*)+)+?\\s", "aa+ " }, diff --git a/testdata/testinput12 b/testdata/testinput12 index c4f5693..fff8db1 100644 --- a/testdata/testinput12 +++ b/testdata/testinput12 @@ -4,7 +4,7 @@ and a couple of things that are different with JIT. --/ /abc/S+I -/ab(*COMMIT)/S+I +/ab(*THEN)/S+I /abc/S+I>testsavedregex diff --git a/testdata/testoutput12 b/testdata/testoutput12 index 7e173cf..c9a428a 100644 --- a/testdata/testoutput12 +++ b/testdata/testoutput12 @@ -11,7 +11,7 @@ Subject length lower bound = 3 No set of starting bytes JIT study was successful -/ab(*COMMIT)/S+I +/ab(*THEN)/S+I Capturing subpattern count = 0 No options First char = 'a' |