196 |
struct stub_list *next; |
struct stub_list *next; |
197 |
} stub_list; |
} stub_list; |
198 |
|
|
|
enum bytecode_flag_types { |
|
|
flag_optimized_cbracket = 1, |
|
|
flag_then_start = 2, |
|
|
}; |
|
|
|
|
199 |
enum frame_types { |
enum frame_types { |
200 |
no_frame = -1, |
no_frame = -1, |
201 |
no_stack = -2 |
no_stack = -2 |
202 |
}; |
}; |
203 |
|
|
204 |
enum control_types { |
enum control_types { |
205 |
type_commit = 0, |
type_mark = 0, |
206 |
type_prune = 1, |
type_then_trap = 1 |
|
type_skip = 2, |
|
|
type_skip_arg = 3, |
|
|
type_mark = 4, |
|
|
type_then_trap = 5 |
|
207 |
}; |
}; |
208 |
|
|
209 |
typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); |
typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); |
976 |
|
|
977 |
case OP_THEN_ARG: |
case OP_THEN_ARG: |
978 |
common->has_then = TRUE; |
common->has_then = TRUE; |
979 |
|
common->control_head_ptr = 1; |
980 |
/* Fall through. */ |
/* Fall through. */ |
981 |
|
|
982 |
case OP_PRUNE_ARG: |
case OP_PRUNE_ARG: |
983 |
common->needs_start_ptr = TRUE; |
common->needs_start_ptr = TRUE; |
|
common->control_head_ptr = 1; |
|
984 |
/* Fall through. */ |
/* Fall through. */ |
985 |
|
|
986 |
case OP_MARK: |
case OP_MARK: |
994 |
|
|
995 |
case OP_THEN: |
case OP_THEN: |
996 |
common->has_then = TRUE; |
common->has_then = TRUE; |
997 |
|
common->control_head_ptr = 1; |
998 |
/* Fall through. */ |
/* Fall through. */ |
999 |
|
|
1000 |
case OP_PRUNE: |
case OP_PRUNE: |
1001 |
case OP_SKIP: |
case OP_SKIP: |
1002 |
common->needs_start_ptr = TRUE; |
common->needs_start_ptr = TRUE; |
|
common->control_head_ptr = 1; |
|
1003 |
cc += 1; |
cc += 1; |
1004 |
break; |
break; |
1005 |
|
|
1279 |
cc += 1 + LINK_SIZE + IMM2_SIZE; |
cc += 1 + LINK_SIZE + IMM2_SIZE; |
1280 |
break; |
break; |
1281 |
|
|
|
case OP_PRUNE: |
|
|
case OP_SKIP: |
|
|
case OP_SKIP_ARG: |
|
|
case OP_COMMIT: |
|
|
if (common->control_head_ptr != 0) |
|
|
*needs_control_head = TRUE; |
|
|
/* Fall through. */ |
|
|
|
|
1282 |
default: |
default: |
1283 |
stack_restore = TRUE; |
stack_restore = TRUE; |
1284 |
/* Fall through. */ |
/* Fall through. */ |
2088 |
OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); |
2089 |
if (common->mark_ptr != 0) |
if (common->mark_ptr != 0) |
2090 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); |
2091 |
SLJIT_ASSERT(common->control_head_ptr != 0); |
if (common->control_head_ptr != 0) |
2092 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); |
2093 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); |
2094 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr); |
2095 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); |
2096 |
} |
} |
2097 |
|
|
2098 |
static sljit_sw SLJIT_CALL do_check_control_chain(sljit_sw *current) |
static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg) |
2099 |
{ |
{ |
2100 |
sljit_sw return_value = 0; |
while (current != NULL) |
|
const pcre_uchar *skip_arg = NULL; |
|
|
|
|
|
SLJIT_ASSERT(current != NULL); |
|
|
do |
|
2101 |
{ |
{ |
2102 |
switch (current[-2]) |
switch (current[-2]) |
2103 |
{ |
{ |
|
case type_commit: |
|
|
/* Commit overwrites all. */ |
|
|
return -1; |
|
|
|
|
|
case type_prune: |
|
2104 |
case type_then_trap: |
case type_then_trap: |
2105 |
break; |
break; |
2106 |
|
|
|
case type_skip: |
|
|
/* Overwrites prune, but not other skips. */ |
|
|
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; |
|
|
|
|
2107 |
case type_mark: |
case type_mark: |
2108 |
if (return_value == 0 && skip_arg != NULL) |
if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0) |
2109 |
if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0) |
return current[-4]; |
|
return_value = current[-4]; |
|
2110 |
break; |
break; |
2111 |
|
|
2112 |
default: |
default: |
2115 |
} |
} |
2116 |
current = (sljit_sw*)current[-1]; |
current = (sljit_sw*)current[-1]; |
2117 |
} |
} |
2118 |
while (current != NULL); |
return -1; |
|
return (return_value != 0 || skip_arg == NULL) ? return_value : -2; |
|
2119 |
} |
} |
2120 |
|
|
2121 |
static sljit_sw SLJIT_CALL do_search_then_trap(sljit_sw *current, sljit_sw start) |
static sljit_sw SLJIT_CALL do_search_then_trap(sljit_sw *current, sljit_sw start) |
2122 |
{ |
{ |
2123 |
do |
do |
2124 |
{ |
{ |
2125 |
|
SLJIT_ASSERT(current != NULL); |
2126 |
switch (current[-2]) |
switch (current[-2]) |
2127 |
{ |
{ |
|
case type_commit: |
|
|
/* Commit overwrites all. */ |
|
|
return 0; |
|
|
|
|
2128 |
case type_then_trap: |
case type_then_trap: |
2129 |
if (current[-3] == start) |
if (current[-3] == start) |
2130 |
return (sljit_sw)current; |
return (sljit_sw)current; |
2131 |
break; |
break; |
2132 |
|
|
|
case type_prune: |
|
|
case type_skip: |
|
|
case type_skip_arg: |
|
2133 |
case type_mark: |
case type_mark: |
2134 |
break; |
break; |
2135 |
|
|
2138 |
break; |
break; |
2139 |
} |
} |
2140 |
current = (sljit_sw*)current[-1]; |
current = (sljit_sw*)current[-1]; |
|
SLJIT_ASSERT(current != NULL); |
|
2141 |
} |
} |
2142 |
while (TRUE); |
while (TRUE); |
2143 |
} |
} |
7250 |
pcre_uchar opcode = *cc; |
pcre_uchar opcode = *cc; |
7251 |
pcre_uchar *ccend = cc + 1; |
pcre_uchar *ccend = cc + 1; |
7252 |
|
|
|
SLJIT_ASSERT(common->control_head_ptr != 0 || *cc == OP_COMMIT); |
|
|
|
|
7253 |
if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG) |
if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG) |
7254 |
ccend += 2 + cc[1]; |
ccend += 2 + cc[1]; |
7255 |
|
|
7256 |
PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); |
PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); |
7257 |
|
|
7258 |
if (opcode == OP_SKIP || opcode == OP_SKIP_ARG) |
if (opcode == OP_SKIP) |
7259 |
{ |
{ |
7260 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
allocate_stack(common, 1); |
7261 |
allocate_stack(common, 3); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
|
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, *cc == OP_SKIP ? type_skip : type_skip_arg); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), (opcode == OP_SKIP) ? STR_PTR : SLJIT_IMM, (opcode == OP_SKIP) ? 0 : (sljit_sw)(cc + 2)); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); |
|
7262 |
return ccend; |
return ccend; |
7263 |
} |
} |
7264 |
|
|
7270 |
OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); |
7271 |
} |
} |
7272 |
|
|
|
if (common->control_head_ptr != 0 && ((opcode != OP_THEN && opcode != OP_THEN_ARG) || common->then_trap == NULL)) |
|
|
{ |
|
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
|
|
allocate_stack(common, 2); |
|
|
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, *cc == OP_COMMIT ? type_commit : type_prune); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); |
|
|
} |
|
|
|
|
7273 |
return ccend; |
return ccend; |
7274 |
} |
} |
7275 |
|
|
8348 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
8349 |
pcre_uchar opcode = *current->cc; |
pcre_uchar opcode = *current->cc; |
8350 |
|
|
|
SLJIT_ASSERT(common->control_head_ptr != 0); |
|
|
|
|
8351 |
if ((opcode == OP_THEN || opcode == OP_THEN_ARG) && common->then_trap != NULL) |
if ((opcode == OP_THEN || opcode == OP_THEN_ARG) && common->then_trap != NULL) |
8352 |
{ |
{ |
8353 |
|
SLJIT_ASSERT(common->control_head_ptr != 0); |
8354 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
8355 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
8356 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, common->then_trap->start); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, common->then_trap->start); |
8369 |
return; |
return; |
8370 |
} |
} |
8371 |
|
|
8372 |
if (!common->local_exit) |
if (common->local_exit) |
8373 |
|
{ |
8374 |
|
if (common->quit_label == NULL) |
8375 |
|
add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); |
8376 |
|
else |
8377 |
|
JUMPTO(SLJIT_JUMP, common->quit_label); |
8378 |
|
return; |
8379 |
|
} |
8380 |
|
|
8381 |
|
if (opcode == OP_SKIP_ARG) |
8382 |
{ |
{ |
8383 |
|
SLJIT_ASSERT(common->control_head_ptr != 0); |
8384 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
8385 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
8386 |
sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_check_control_chain)); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2)); |
8387 |
|
sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark)); |
8388 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
8389 |
|
|
8390 |
OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); |
OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); |
8391 |
add_jump(compiler, &common->reset_match, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1)); |
add_jump(compiler, &common->reset_match, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1)); |
8392 |
|
return; |
|
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
|
8393 |
} |
} |
8394 |
|
|
8395 |
/* Commit or in recurse or accept. */ |
if (opcode == OP_SKIP) |
8396 |
if (common->quit_label == NULL) |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
|
add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); |
|
8397 |
else |
else |
8398 |
JUMPTO(SLJIT_JUMP, common->quit_label); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_IMM, 0); |
8399 |
|
add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP)); |
8400 |
} |
} |
8401 |
|
|
8402 |
static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
8580 |
case OP_PRUNE: |
case OP_PRUNE: |
8581 |
case OP_PRUNE_ARG: |
case OP_PRUNE_ARG: |
8582 |
case OP_SKIP: |
case OP_SKIP: |
|
compile_control_verb_backtrackingpath(common, current); |
|
|
break; |
|
|
|
|
8583 |
case OP_SKIP_ARG: |
case OP_SKIP_ARG: |
8584 |
if (!common->local_exit) |
compile_control_verb_backtrackingpath(common, current); |
|
{ |
|
|
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); |
|
|
} |
|
8585 |
break; |
break; |
8586 |
|
|
8587 |
case OP_COMMIT: |
case OP_COMMIT: |