Revision: 1278
http://vcs.pcre.org/viewvc?view=rev&revision=1278
Author: zherczeg
Date: 2013-03-12 06:15:04 +0000 (Tue, 12 Mar 2013)
Log Message:
-----------
Support for SKIP with argument is added to the JIT compiler. Control verb support is still experimental.
Modified Paths:
--------------
code/trunk/pcre_jit_compile.c
Modified: code/trunk/pcre_jit_compile.c
===================================================================
--- code/trunk/pcre_jit_compile.c 2013-03-11 09:50:29 UTC (rev 1277)
+++ code/trunk/pcre_jit_compile.c 2013-03-12 06:15:04 UTC (rev 1278)
@@ -204,7 +204,9 @@
enum control_types {
type_commit = 0,
type_prune = 1,
- type_skip = 2
+ type_skip = 2,
+ type_skip_arg = 3,
+ type_mark = 4
};
typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);
@@ -332,6 +334,8 @@
int mode;
/* \K is in the pattern. */
BOOL has_set_som;
+ /* (*SKIP:arg) is in the pattern. */
+ BOOL has_skip_arg;
/* Needs to know the start position anytime. */
BOOL needs_start_ptr;
/* Currently in recurse or assert. */
@@ -696,6 +700,7 @@
case OP_MARK:
case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
return cc + 1 + 2 + cc[1];
default:
@@ -964,13 +969,16 @@
case OP_PRUNE:
case OP_SKIP:
common->needs_start_ptr = TRUE;
- /* Fall through. */
-
- case OP_COMMIT:
common->control_head_ptr = 1;
cc += 1;
break;
+ case OP_SKIP_ARG:
+ common->control_head_ptr = 1;
+ common->has_skip_arg = TRUE;
+ cc += 1 + 2 + cc[1];
+ break;
+
default:
cc = next_opcode(common, cc);
if (cc == NULL)
@@ -1239,6 +1247,7 @@
case OP_PRUNE:
case OP_SKIP:
+ case OP_SKIP_ARG:
case OP_COMMIT:
if (common->control_head_ptr != 0)
*needs_control_head = TRUE;
@@ -2025,6 +2034,7 @@
static sljit_sw SLJIT_CALL do_check_control_chain(sljit_sw *current)
{
sljit_sw return_value = 0;
+const pcre_uchar *skip_arg = NULL;
SLJIT_ASSERT(current != NULL);
do
@@ -2040,10 +2050,21 @@
case type_skip:
/* Overwrites prune, but not other skips. */
- if (return_value == 0)
+ if (return_value == 0 && skip_arg == NULL)
return_value = current[-3];
break;
+ case type_skip_arg:
+ if (return_value == 0 && skip_arg == NULL)
+ skip_arg = (pcre_uchar *)current[-3];
+ break;
+
+ case type_mark:
+ if (return_value == 0 && skip_arg != NULL)
+ if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0)
+ return_value = current[-4];
+ break;
+
default:
SLJIT_ASSERT_STOP();
break;
@@ -2051,7 +2072,7 @@
current = (sljit_sw*)current[-1];
}
while (current != NULL);
-return return_value;
+return (return_value != 0 || skip_arg == NULL) ? return_value : -2;
}
static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
@@ -7368,12 +7389,21 @@
PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
SLJIT_ASSERT(common->mark_ptr != 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
- allocate_stack(common, 1);
+ allocate_stack(common, common->has_skip_arg ? 5 : 1);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
+ if (common->has_skip_arg)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_mark);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), SLJIT_IMM, (sljit_sw)(cc + 2));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
+ }
cc += 1 + 2 + cc[1];
break;
@@ -7397,14 +7427,15 @@
break;
case OP_SKIP:
+ case OP_SKIP_ARG:
PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
allocate_stack(common, 3);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0);
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_skip);
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, *cc == OP_SKIP ? type_skip : type_skip_arg);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), *cc == OP_SKIP ? STR_PTR : SLJIT_IMM, *cc == OP_SKIP ? 0 : (sljit_sw)(cc + 2));
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
- cc += 1;
+ cc += (*cc == OP_SKIP_ARG) ? (1 + 2 + cc[1]) : 1;
break;
case OP_FAIL:
@@ -8310,9 +8341,13 @@
break;
case OP_MARK:
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
- free_stack(common, 1);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0));
+ if (common->has_skip_arg)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, common->has_skip_arg ? 5 : 1);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0);
+ if (common->has_skip_arg)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP2, 0);
break;
case OP_PRUNE:
@@ -8339,6 +8374,39 @@
JUMPTO(SLJIT_JUMP, common->quit_label);
break;
+ case OP_SKIP_ARG:
+ if (!common->local_exit)
+ {
+ SLJIT_ASSERT(common->control_head_ptr != 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
+ sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_check_control_chain));
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
+ add_jump(compiler, &common->reset_match, CMP(SLJIT_C_LESS, STR_PTR, 0, SLJIT_IMM, -2));
+
+ /* May not find suitable mark. */
+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
+ if (common->quit_label == NULL)
+ add_jump(compiler, &common->quit, CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, -1));
+ else
+ CMPTO(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, -1, common->quit_label);
+
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 3);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0);
+ }
+ else
+ {
+ /* In recurse or accept. */
+ if (common->quit_label == NULL)
+ add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));
+ else
+ JUMPTO(SLJIT_JUMP, common->quit_label);
+ }
+ break;
+
case OP_COMMIT:
if (!common->local_exit)
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);