Revision: 941
http://vcs.pcre.org/viewvc?view=rev&revision=941
Author: zherczeg
Date: 2012-02-28 11:33:34 +0000 (Tue, 28 Feb 2012)
Log Message:
-----------
(COMMIT*) is now supported by the JIT compiler
Modified Paths:
--------------
code/trunk/ChangeLog
code/trunk/pcre_exec.c
code/trunk/pcre_internal.h
code/trunk/pcre_jit_compile.c
code/trunk/pcre_jit_test.c
code/trunk/testdata/testinput12
code/trunk/testdata/testoutput12
Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog 2012-02-28 10:30:51 UTC (rev 940)
+++ code/trunk/ChangeLog 2012-02-28 11:33:34 UTC (rev 941)
@@ -63,7 +63,9 @@
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
-----------------------------
Modified: code/trunk/pcre_exec.c
===================================================================
--- code/trunk/pcre_exec.c 2012-02-28 10:30:51 UTC (rev 940)
+++ code/trunk/pcre_exec.c 2012-02-28 11:33:34 UTC (rev 941)
@@ -6469,11 +6469,8 @@
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. */
Modified: code/trunk/pcre_internal.h
===================================================================
--- code/trunk/pcre_internal.h 2012-02-28 10:30:51 UTC (rev 940)
+++ code/trunk/pcre_internal.h 2012-02-28 11:33:34 UTC (rev 941)
@@ -2296,10 +2296,10 @@
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);
Modified: code/trunk/pcre_jit_compile.c
===================================================================
--- code/trunk/pcre_jit_compile.c 2012-02-28 10:30:51 UTC (rev 940)
+++ code/trunk/pcre_jit_compile.c 2012-02-28 11:33:34 UTC (rev 941)
@@ -307,11 +307,13 @@
/* 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 @@
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 @@
}
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 **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 @@
}
memset(&altfallback, 0, sizeof(fallback_common));
+common->leavelabel = NULL;
+common->leave = NULL;
while (1)
{
common->acceptlabel = NULL;
@@ -4248,7 +4255,9 @@
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 @@
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 @@
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 @@
}
}
+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 @@
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 @@
{
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 @@
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 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 @@
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 @@
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 @@
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, 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 @@
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 @@
/* 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 @@
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 @@
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 @@
}
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.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 @@
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;
}
Modified: code/trunk/pcre_jit_test.c
===================================================================
--- code/trunk/pcre_jit_test.c 2012-02-28 10:30:51 UTC (rev 940)
+++ code/trunk/pcre_jit_test.c 2012-02-28 11:33:34 UTC (rev 941)
@@ -679,6 +679,13 @@
{ 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+ " },
Modified: code/trunk/testdata/testinput12
===================================================================
--- code/trunk/testdata/testinput12 2012-02-28 10:30:51 UTC (rev 940)
+++ code/trunk/testdata/testinput12 2012-02-28 11:33:34 UTC (rev 941)
@@ -4,7 +4,7 @@
/abc/S+I
-/ab(*COMMIT)/S+I
+/ab(*THEN)/S+I
/abc/S+I>testsavedregex
Modified: code/trunk/testdata/testoutput12
===================================================================
--- code/trunk/testdata/testoutput12 2012-02-28 10:30:51 UTC (rev 940)
+++ code/trunk/testdata/testoutput12 2012-02-28 11:33:34 UTC (rev 941)
@@ -11,7 +11,7 @@
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'