summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15>2012-02-28 11:33:34 +0000
committerzherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15>2012-02-28 11:33:34 +0000
commit82e768d97aaa919496bc8c81924ef25045df5597 (patch)
tree05e16545265a0c437628e40d843c425149b958e4
parent6ceabc3f2a47d73edeaf4bf0f2f3c9fea52dfb3d (diff)
downloadpcre-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--ChangeLog2
-rw-r--r--pcre_exec.c7
-rw-r--r--pcre_internal.h8
-rw-r--r--pcre_jit_compile.c78
-rw-r--r--pcre_jit_test.c7
-rw-r--r--testdata/testinput122
-rw-r--r--testdata/testoutput122
7 files changed, 79 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index eb218c0..356ba91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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'