162 |
pcre_uint8 notempty_atstart; |
pcre_uint8 notempty_atstart; |
163 |
} jit_arguments; |
} jit_arguments; |
164 |
|
|
165 |
typedef struct executable_function { |
typedef struct executable_functions { |
166 |
void *executable_func; |
void *executable_funcs[JIT_NUMBER_OF_COMPILE_TYPES]; |
167 |
PUBL(jit_callback) callback; |
PUBL(jit_callback) callback; |
168 |
void *userdata; |
void *userdata; |
169 |
sljit_uw executable_size; |
sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_TYPES]; |
170 |
} executable_function; |
} executable_functions; |
171 |
|
|
172 |
typedef struct jump_list { |
typedef struct jump_list { |
173 |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
275 |
const pcre_uint8 *fcc; |
const pcre_uint8 *fcc; |
276 |
sljit_w lcc; |
sljit_w lcc; |
277 |
int cbraptr; |
int cbraptr; |
278 |
|
int mode; |
279 |
int nltype; |
int nltype; |
280 |
int newline; |
int newline; |
281 |
int bsr_nltype; |
int bsr_nltype; |
284 |
sljit_uw name_table; |
sljit_uw name_table; |
285 |
sljit_w name_count; |
sljit_w name_count; |
286 |
sljit_w name_entry_size; |
sljit_w name_entry_size; |
287 |
|
struct sljit_label *partialmatchlabel; |
288 |
struct sljit_label *acceptlabel; |
struct sljit_label *acceptlabel; |
289 |
stub_list *stubs; |
stub_list *stubs; |
290 |
recurse_entry *entries; |
recurse_entry *entries; |
291 |
recurse_entry *currententry; |
recurse_entry *currententry; |
292 |
|
jump_list *partialmatch; |
293 |
jump_list *accept; |
jump_list *accept; |
294 |
jump_list *calllimit; |
jump_list *calllimit; |
295 |
jump_list *stackalloc; |
jump_list *stackalloc; |
383 |
#define RECURSIVE_HEAD (4 * sizeof(sljit_w)) |
#define RECURSIVE_HEAD (4 * sizeof(sljit_w)) |
384 |
/* Max limit of recursions. */ |
/* Max limit of recursions. */ |
385 |
#define CALL_LIMIT (5 * sizeof(sljit_w)) |
#define CALL_LIMIT (5 * sizeof(sljit_w)) |
386 |
/* Last known position of the requested byte. */ |
/* Last known position of the requested byte. |
387 |
|
Same as START_USED_PTR. (Partial matching and req_char are exclusive) */ |
388 |
#define REQ_CHAR_PTR (6 * sizeof(sljit_w)) |
#define REQ_CHAR_PTR (6 * sizeof(sljit_w)) |
389 |
|
/* First inspected character for partial matching. |
390 |
|
Same as REQ_CHAR_PTR. (Partial matching and req_char are exclusive) */ |
391 |
|
#define START_USED_PTR (6 * sizeof(sljit_w)) |
392 |
|
/* Starting pointer for partial soft matches. */ |
393 |
|
#define HIT_START (8 * sizeof(sljit_w)) |
394 |
/* End pointer of the first line. */ |
/* End pointer of the first line. */ |
395 |
#define FIRSTLINE_END (7 * sizeof(sljit_w)) |
#define FIRSTLINE_END (9 * sizeof(sljit_w)) |
396 |
/* The output vector is stored on the stack, and contains pointers |
/* The output vector is stored on the stack, and contains pointers |
397 |
to characters. The vector data is divided into two groups: the first |
to characters. The vector data is divided into two groups: the first |
398 |
group contains the start / end character pointers, and the second is |
group contains the start / end character pointers, and the second is |
399 |
the start pointers when the end of the capturing group has not yet reached. */ |
the start pointers when the end of the capturing group has not yet reached. */ |
400 |
#define OVECTOR_START (8 * sizeof(sljit_w)) |
#define OVECTOR_START (10 * sizeof(sljit_w)) |
401 |
#define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w)) |
#define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w)) |
402 |
#define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w)) |
#define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w)) |
403 |
#define PRIV_DATA(cc) (common->localptrs[(cc) - common->start]) |
#define PRIV_DATA(cc) (common->localptrs[(cc) - common->start]) |
1277 |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); |
1278 |
} |
} |
1279 |
|
|
1280 |
|
static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *leave) |
1281 |
|
{ |
1282 |
|
DEFINE_COMPILER; |
1283 |
|
|
1284 |
|
SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2); |
1285 |
|
|
1286 |
|
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); |
1287 |
|
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); |
1288 |
|
OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsetcount)); |
1289 |
|
CMPTO(SLJIT_C_LESS, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 2, leave); |
1290 |
|
|
1291 |
|
/* Store match begin and end. */ |
1292 |
|
OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, begin)); |
1293 |
|
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsets)); |
1294 |
|
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? START_USED_PTR : HIT_START); |
1295 |
|
OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0); |
1296 |
|
#ifdef COMPILE_PCRE16 |
1297 |
|
OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1); |
1298 |
|
#endif |
1299 |
|
OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(int), SLJIT_SAVED_REG2, 0); |
1300 |
|
|
1301 |
|
OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG1, 0); |
1302 |
|
#ifdef COMPILE_PCRE16 |
1303 |
|
OP2(SLJIT_ASHR, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1); |
1304 |
|
#endif |
1305 |
|
OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), 0, SLJIT_TEMPORARY_REG3, 0); |
1306 |
|
|
1307 |
|
JUMPTO(SLJIT_JUMP, leave); |
1308 |
|
} |
1309 |
|
|
1310 |
|
static SLJIT_INLINE void check_start_used_ptr(compiler_common *common) |
1311 |
|
{ |
1312 |
|
/* May destroy TMP1. */ |
1313 |
|
DEFINE_COMPILER; |
1314 |
|
struct sljit_jump *jump; |
1315 |
|
|
1316 |
|
if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
1317 |
|
{ |
1318 |
|
/* The value of -1 must be kept for START_USED_PTR! */ |
1319 |
|
OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, SLJIT_IMM, 1); |
1320 |
|
/* Jumps if START_USED_PTR < STR_PTR, or START_USED_PTR == -1. Although overwriting |
1321 |
|
is not necessary if START_USED_PTR == STR_PTR, it does not hurt as well. */ |
1322 |
|
jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_PTR, 0); |
1323 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); |
1324 |
|
JUMPHERE(jump); |
1325 |
|
} |
1326 |
|
else if (common->mode == JIT_PARTIAL_HARD_COMPILE) |
1327 |
|
{ |
1328 |
|
jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); |
1329 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); |
1330 |
|
JUMPHERE(jump); |
1331 |
|
} |
1332 |
|
} |
1333 |
|
|
1334 |
static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc) |
static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc) |
1335 |
{ |
{ |
1336 |
/* Detects if the character has an othercase. */ |
/* Detects if the character has an othercase. */ |
1452 |
#endif /* COMPILE_PCRE8 */ |
#endif /* COMPILE_PCRE8 */ |
1453 |
} |
} |
1454 |
|
|
1455 |
static SLJIT_INLINE void check_input_end(compiler_common *common, jump_list **fallbacks) |
static void check_partial(compiler_common *common) |
1456 |
|
{ |
1457 |
|
DEFINE_COMPILER; |
1458 |
|
struct sljit_jump *jump; |
1459 |
|
|
1460 |
|
if (common->mode == JIT_COMPILE) |
1461 |
|
return; |
1462 |
|
|
1463 |
|
jump = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); |
1464 |
|
if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
1465 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, SLJIT_IMM, -1); |
1466 |
|
else |
1467 |
|
{ |
1468 |
|
if (common->partialmatchlabel != NULL) |
1469 |
|
JUMPTO(SLJIT_JUMP, common->partialmatchlabel); |
1470 |
|
else |
1471 |
|
add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); |
1472 |
|
} |
1473 |
|
JUMPHERE(jump); |
1474 |
|
} |
1475 |
|
|
1476 |
|
static struct sljit_jump *check_str_end(compiler_common *common) |
1477 |
|
{ |
1478 |
|
/* Does not affect registers. Usually used in a tight spot. */ |
1479 |
|
DEFINE_COMPILER; |
1480 |
|
struct sljit_jump *jump; |
1481 |
|
struct sljit_jump *nohit; |
1482 |
|
struct sljit_jump *return_value; |
1483 |
|
|
1484 |
|
if (common->mode == JIT_COMPILE) |
1485 |
|
return CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
1486 |
|
|
1487 |
|
jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); |
1488 |
|
if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
1489 |
|
{ |
1490 |
|
nohit = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); |
1491 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, SLJIT_IMM, -1); |
1492 |
|
JUMPHERE(nohit); |
1493 |
|
return_value = JUMP(SLJIT_JUMP); |
1494 |
|
} |
1495 |
|
else |
1496 |
|
{ |
1497 |
|
return_value = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); |
1498 |
|
if (common->partialmatchlabel != NULL) |
1499 |
|
JUMPTO(SLJIT_JUMP, common->partialmatchlabel); |
1500 |
|
else |
1501 |
|
add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); |
1502 |
|
} |
1503 |
|
JUMPHERE(jump); |
1504 |
|
return return_value; |
1505 |
|
} |
1506 |
|
|
1507 |
|
static void fallback_at_str_end(compiler_common *common, jump_list **fallbacks) |
1508 |
{ |
{ |
1509 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
1510 |
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
struct sljit_jump *jump; |
1511 |
|
|
1512 |
|
if (common->mode == JIT_COMPILE) |
1513 |
|
{ |
1514 |
|
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
1515 |
|
return; |
1516 |
|
} |
1517 |
|
|
1518 |
|
/* Partial matching mode. */ |
1519 |
|
jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); |
1520 |
|
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0)); |
1521 |
|
if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
1522 |
|
{ |
1523 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, SLJIT_IMM, -1); |
1524 |
|
add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); |
1525 |
|
} |
1526 |
|
else |
1527 |
|
{ |
1528 |
|
if (common->partialmatchlabel != NULL) |
1529 |
|
JUMPTO(SLJIT_JUMP, common->partialmatchlabel); |
1530 |
|
else |
1531 |
|
add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); |
1532 |
|
} |
1533 |
|
JUMPHERE(jump); |
1534 |
} |
} |
1535 |
|
|
1536 |
static void read_char(compiler_common *common) |
static void read_char(compiler_common *common) |
2300 |
static void check_wordboundary(compiler_common *common) |
static void check_wordboundary(compiler_common *common) |
2301 |
{ |
{ |
2302 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
2303 |
struct sljit_jump *beginend; |
struct sljit_jump *skipread; |
2304 |
#if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF |
#if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF |
2305 |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
2306 |
#endif |
#endif |
2312 |
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
2313 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); |
2314 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0); |
2315 |
beginend = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); |
skipread = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); |
2316 |
skip_char_back(common); |
skip_char_back(common); |
2317 |
|
check_start_used_ptr(common); |
2318 |
read_char(common); |
read_char(common); |
2319 |
|
|
2320 |
/* Testing char type. */ |
/* Testing char type. */ |
2355 |
JUMPHERE(jump); |
JUMPHERE(jump); |
2356 |
#endif /* COMPILE_PCRE8 */ |
#endif /* COMPILE_PCRE8 */ |
2357 |
} |
} |
2358 |
JUMPHERE(beginend); |
JUMPHERE(skipread); |
2359 |
|
|
2360 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
2361 |
beginend = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
skipread = check_str_end(common); |
2362 |
peek_char(common); |
peek_char(common); |
2363 |
|
|
2364 |
/* Testing char type. This is a code duplication. */ |
/* Testing char type. This is a code duplication. */ |
2399 |
JUMPHERE(jump); |
JUMPHERE(jump); |
2400 |
#endif /* COMPILE_PCRE8 */ |
#endif /* COMPILE_PCRE8 */ |
2401 |
} |
} |
2402 |
JUMPHERE(beginend); |
JUMPHERE(skipread); |
2403 |
|
|
2404 |
OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); |
OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); |
2405 |
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
2799 |
unsigned int charoffset; |
unsigned int charoffset; |
2800 |
|
|
2801 |
/* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */ |
/* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */ |
2802 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
2803 |
read_char(common); |
read_char(common); |
2804 |
|
|
2805 |
if ((*cc++ & XCL_MAP) != 0) |
if ((*cc++ & XCL_MAP) != 0) |
3153 |
|
|
3154 |
case OP_NOT_DIGIT: |
case OP_NOT_DIGIT: |
3155 |
case OP_DIGIT: |
case OP_DIGIT: |
3156 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3157 |
read_char8_type(common); |
read_char8_type(common); |
3158 |
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); |
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); |
3159 |
add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
3161 |
|
|
3162 |
case OP_NOT_WHITESPACE: |
case OP_NOT_WHITESPACE: |
3163 |
case OP_WHITESPACE: |
case OP_WHITESPACE: |
3164 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3165 |
read_char8_type(common); |
read_char8_type(common); |
3166 |
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); |
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); |
3167 |
add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
3169 |
|
|
3170 |
case OP_NOT_WORDCHAR: |
case OP_NOT_WORDCHAR: |
3171 |
case OP_WORDCHAR: |
case OP_WORDCHAR: |
3172 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3173 |
read_char8_type(common); |
read_char8_type(common); |
3174 |
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); |
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); |
3175 |
add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
3176 |
return cc; |
return cc; |
3177 |
|
|
3178 |
case OP_ANY: |
case OP_ANY: |
3179 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3180 |
read_char(common); |
read_char(common); |
3181 |
if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
3182 |
{ |
{ |
3192 |
return cc; |
return cc; |
3193 |
|
|
3194 |
case OP_ALLANY: |
case OP_ALLANY: |
3195 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3196 |
#ifdef SUPPORT_UTF |
#ifdef SUPPORT_UTF |
3197 |
if (common->utf) |
if (common->utf) |
3198 |
{ |
{ |
3220 |
return cc; |
return cc; |
3221 |
|
|
3222 |
case OP_ANYBYTE: |
case OP_ANYBYTE: |
3223 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3224 |
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3225 |
return cc; |
return cc; |
3226 |
|
|
3239 |
#endif |
#endif |
3240 |
|
|
3241 |
case OP_ANYNL: |
case OP_ANYNL: |
3242 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3243 |
read_char(common); |
read_char(common); |
3244 |
jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); |
jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); |
3245 |
jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
3256 |
|
|
3257 |
case OP_NOT_HSPACE: |
case OP_NOT_HSPACE: |
3258 |
case OP_HSPACE: |
case OP_HSPACE: |
3259 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3260 |
read_char(common); |
read_char(common); |
3261 |
add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); |
add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); |
3262 |
add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
3264 |
|
|
3265 |
case OP_NOT_VSPACE: |
case OP_NOT_VSPACE: |
3266 |
case OP_VSPACE: |
case OP_VSPACE: |
3267 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3268 |
read_char(common); |
read_char(common); |
3269 |
add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); |
add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); |
3270 |
add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
3272 |
|
|
3273 |
#ifdef SUPPORT_UCP |
#ifdef SUPPORT_UCP |
3274 |
case OP_EXTUNI: |
case OP_EXTUNI: |
3275 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3276 |
read_char(common); |
read_char(common); |
3277 |
add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); |
add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); |
3278 |
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); |
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); |
3342 |
JUMPHERE(jump[3]); |
JUMPHERE(jump[3]); |
3343 |
} |
} |
3344 |
JUMPHERE(jump[0]); |
JUMPHERE(jump[0]); |
3345 |
|
check_partial(common); |
3346 |
return cc; |
return cc; |
3347 |
|
|
3348 |
case OP_EOD: |
case OP_EOD: |
3349 |
add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); |
add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); |
3350 |
|
check_partial(common); |
3351 |
return cc; |
return cc; |
3352 |
|
|
3353 |
case OP_CIRC: |
case OP_CIRC: |
3367 |
jump[0] = JUMP(SLJIT_JUMP); |
jump[0] = JUMP(SLJIT_JUMP); |
3368 |
JUMPHERE(jump[1]); |
JUMPHERE(jump[1]); |
3369 |
|
|
3370 |
add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, STR_PTR, 0, STR_END, 0)); |
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
3371 |
if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
3372 |
{ |
{ |
3373 |
OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
3394 |
if (!common->endonly) |
if (!common->endonly) |
3395 |
compile_char1_hotpath(common, OP_EODN, cc, fallbacks); |
compile_char1_hotpath(common, OP_EODN, cc, fallbacks); |
3396 |
else |
else |
3397 |
|
{ |
3398 |
add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); |
add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); |
3399 |
|
check_partial(common); |
3400 |
|
} |
3401 |
return cc; |
return cc; |
3402 |
|
|
3403 |
case OP_DOLLM: |
case OP_DOLLM: |
3405 |
OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); |
3406 |
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); |
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); |
3407 |
add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
3408 |
|
check_partial(common); |
3409 |
jump[0] = JUMP(SLJIT_JUMP); |
jump[0] = JUMP(SLJIT_JUMP); |
3410 |
JUMPHERE(jump[1]); |
JUMPHERE(jump[1]); |
3411 |
|
|
3432 |
#ifdef SUPPORT_UTF |
#ifdef SUPPORT_UTF |
3433 |
if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); |
if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); |
3434 |
#endif |
#endif |
3435 |
if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0) |
if (common->mode == JIT_COMPILE && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)) |
3436 |
{ |
{ |
3437 |
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); |
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); |
3438 |
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); |
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); |
3444 |
#endif |
#endif |
3445 |
return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks); |
return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks); |
3446 |
} |
} |
3447 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3448 |
read_char(common); |
read_char(common); |
3449 |
#ifdef SUPPORT_UTF |
#ifdef SUPPORT_UTF |
3450 |
if (common->utf) |
if (common->utf) |
3454 |
else |
else |
3455 |
#endif |
#endif |
3456 |
c = *cc; |
c = *cc; |
3457 |
|
if (type == OP_CHAR || !char_has_othercase(common, cc)) |
3458 |
|
{ |
3459 |
|
add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); |
3460 |
|
return cc + length; |
3461 |
|
} |
3462 |
|
oc = char_othercase(common, c); |
3463 |
|
bit = c ^ oc; |
3464 |
|
if (ispowerof2(bit)) |
3465 |
|
{ |
3466 |
|
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); |
3467 |
|
add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); |
3468 |
|
return cc + length; |
3469 |
|
} |
3470 |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c); |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c); |
3471 |
COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
3472 |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c)); |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c)); |
3476 |
|
|
3477 |
case OP_NOT: |
case OP_NOT: |
3478 |
case OP_NOTI: |
case OP_NOTI: |
3479 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3480 |
length = 1; |
length = 1; |
3481 |
#ifdef SUPPORT_UTF |
#ifdef SUPPORT_UTF |
3482 |
if (common->utf) |
if (common->utf) |
3537 |
|
|
3538 |
case OP_CLASS: |
case OP_CLASS: |
3539 |
case OP_NCLASS: |
case OP_NCLASS: |
3540 |
check_input_end(common, fallbacks); |
fallback_at_str_end(common, fallbacks); |
3541 |
read_char(common); |
read_char(common); |
3542 |
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
3543 |
jump[0] = NULL; |
jump[0] = NULL; |
3587 |
skip_char_back(common); |
skip_char_back(common); |
3588 |
OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); |
OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); |
3589 |
JUMPTO(SLJIT_C_NOT_ZERO, label); |
JUMPTO(SLJIT_C_NOT_ZERO, label); |
|
return cc + LINK_SIZE; |
|
3590 |
} |
} |
3591 |
|
else |
3592 |
#endif |
#endif |
3593 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); |
{ |
3594 |
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); |
3595 |
add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); |
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); |
3596 |
|
add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); |
3597 |
|
} |
3598 |
|
check_start_used_ptr(common); |
3599 |
return cc + LINK_SIZE; |
return cc + LINK_SIZE; |
3600 |
} |
} |
3601 |
SLJIT_ASSERT_STOP(); |
SLJIT_ASSERT_STOP(); |
3678 |
{ |
{ |
3679 |
if (fallbacks == NULL) |
if (fallbacks == NULL) |
3680 |
{ |
{ |
3681 |
|
/* OVECTOR(1) contains the "string begin - 1" constant. */ |
3682 |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
3683 |
COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
3684 |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
3720 |
} \ |
} \ |
3721 |
while (0) |
while (0) |
3722 |
|
|
3723 |
#define FALLBACK_AS(type) ((type*)fallback) |
#define FALLBACK_AS(type) ((type *)fallback) |
3724 |
|
|
3725 |
static pcre_uchar *compile_ref_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail) |
static pcre_uchar *compile_ref_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail) |
3726 |
{ |
{ |
3729 |
struct sljit_jump *jump = NULL; |
struct sljit_jump *jump = NULL; |
3730 |
|
|
3731 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
3732 |
|
/* OVECTOR(1) contains the "string begin - 1" constant. */ |
3733 |
if (withchecks && !common->jscript_compat) |
if (withchecks && !common->jscript_compat) |
3734 |
add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); |
add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); |
3735 |
|
|
3741 |
if (withchecks) |
if (withchecks) |
3742 |
jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0); |
jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0); |
3743 |
|
|
3744 |
|
if (common->mode != JIT_COMPILE) |
3745 |
|
fallback_at_str_end(common, fallbacks); |
3746 |
|
|
3747 |
/* Needed to save important temporary registers. */ |
/* Needed to save important temporary registers. */ |
3748 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
3749 |
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); |
3759 |
OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); |
OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); |
3760 |
if (withchecks) |
if (withchecks) |
3761 |
jump = JUMP(SLJIT_C_ZERO); |
jump = JUMP(SLJIT_C_ZERO); |
3762 |
|
|
3763 |
|
if (common->mode != JIT_COMPILE) |
3764 |
|
fallback_at_str_end(common, fallbacks); |
3765 |
|
|
3766 |
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
3767 |
|
|
3768 |
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); |
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); |
4814 |
if (bra == OP_BRAMINZERO) |
if (bra == OP_BRAMINZERO) |
4815 |
{ |
{ |
4816 |
/* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */ |
/* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */ |
4817 |
JUMPTO(SLJIT_JUMP, ((braminzero_fallback*)parent)->hotpath); |
JUMPTO(SLJIT_JUMP, ((braminzero_fallback *)parent)->hotpath); |
4818 |
if (braminzerojump != NULL) |
if (braminzerojump != NULL) |
4819 |
{ |
{ |
4820 |
JUMPHERE(braminzerojump); |
JUMPHERE(braminzerojump); |
5434 |
|
|
5435 |
case OP_CHAR: |
case OP_CHAR: |
5436 |
case OP_CHARI: |
case OP_CHARI: |
5437 |
cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); |
if (common->mode == JIT_COMPILE) |
5438 |
|
cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); |
5439 |
|
else |
5440 |
|
cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); |
5441 |
break; |
break; |
5442 |
|
|
5443 |
case OP_STAR: |
case OP_STAR: |
5630 |
} \ |
} \ |
5631 |
while (0) |
while (0) |
5632 |
|
|
5633 |
#define CURRENT_AS(type) ((type*)current) |
#define CURRENT_AS(type) ((type *)current) |
5634 |
|
|
5635 |
static void compile_iterator_fallbackpath(compiler_common *common, struct fallback_common *current) |
static void compile_iterator_fallbackpath(compiler_common *common, struct fallback_common *current) |
5636 |
{ |
{ |
6531 |
#undef CURRENT_AS |
#undef CURRENT_AS |
6532 |
|
|
6533 |
void |
void |
6534 |
PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra) |
PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra, int mode) |
6535 |
{ |
{ |
6536 |
struct sljit_compiler *compiler; |
struct sljit_compiler *compiler; |
6537 |
fallback_common rootfallback; |
fallback_common rootfallback; |
6540 |
const pcre_uint8 *tables = re->tables; |
const pcre_uint8 *tables = re->tables; |
6541 |
pcre_study_data *study; |
pcre_study_data *study; |
6542 |
pcre_uchar *ccend; |
pcre_uchar *ccend; |
6543 |
executable_function *function; |
executable_functions *functions; |
6544 |
void *executable_func; |
void *executable_func; |
6545 |
sljit_uw executable_size; |
sljit_uw executable_size; |
6546 |
struct sljit_label *leave; |
struct sljit_label *leave; |
6547 |
struct sljit_label *mainloop = NULL; |
struct sljit_label *mainloop = NULL; |
6548 |
struct sljit_label *empty_match_found; |
struct sljit_label *empty_match_found; |
6549 |
struct sljit_label *empty_match_fallback; |
struct sljit_label *empty_match_fallback; |
6550 |
struct sljit_jump *alloc_error; |
struct sljit_jump *jump; |
6551 |
struct sljit_jump *reqbyte_notfound = NULL; |
struct sljit_jump *reqbyte_notfound = NULL; |
6552 |
struct sljit_jump *empty_match; |
struct sljit_jump *empty_match; |
6553 |
|
|
6565 |
common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w); |
common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w); |
6566 |
common->fcc = tables + fcc_offset; |
common->fcc = tables + fcc_offset; |
6567 |
common->lcc = (sljit_w)(tables + lcc_offset); |
common->lcc = (sljit_w)(tables + lcc_offset); |
6568 |
|
common->mode = mode; |
6569 |
common->nltype = NLTYPE_FIXED; |
common->nltype = NLTYPE_FIXED; |
6570 |
switch(re->options & PCRE_NEWLINE_BITS) |
switch(re->options & PCRE_NEWLINE_BITS) |
6571 |
{ |
{ |
6603 |
common->name_table = (sljit_w)((pcre_uchar *)re + re->name_table_offset); |
common->name_table = (sljit_w)((pcre_uchar *)re + re->name_table_offset); |
6604 |
common->name_count = re->name_count; |
common->name_count = re->name_count; |
6605 |
common->name_entry_size = re->name_entry_size; |
common->name_entry_size = re->name_entry_size; |
6606 |
|
common->partialmatchlabel = NULL; |
6607 |
common->acceptlabel = NULL; |
common->acceptlabel = NULL; |
6608 |
common->stubs = NULL; |
common->stubs = NULL; |
6609 |
common->entries = NULL; |
common->entries = NULL; |
6610 |
common->currententry = NULL; |
common->currententry = NULL; |
6611 |
|
common->partialmatch = NULL; |
6612 |
common->accept = NULL; |
common->accept = NULL; |
6613 |
common->calllimit = NULL; |
common->calllimit = NULL; |
6614 |
common->stackalloc = NULL; |
common->stackalloc = NULL; |
6642 |
common->localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w); |
common->localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w); |
6643 |
if (common->localsize > SLJIT_MAX_LOCAL_SIZE) |
if (common->localsize > SLJIT_MAX_LOCAL_SIZE) |
6644 |
return; |
return; |
6645 |
common->localptrs = (int*)SLJIT_MALLOC((ccend - rootfallback.cc) * sizeof(int)); |
common->localptrs = (int *)SLJIT_MALLOC((ccend - rootfallback.cc) * sizeof(int)); |
6646 |
if (!common->localptrs) |
if (!common->localptrs) |
6647 |
return; |
return; |
6648 |
memset(common->localptrs, 0, (ccend - rootfallback.cc) * sizeof(int)); |
memset(common->localptrs, 0, (ccend - rootfallback.cc) * sizeof(int)); |
6661 |
|
|
6662 |
/* Register init. */ |
/* Register init. */ |
6663 |
reset_ovector(common, (re->top_bracket + 1) * 2); |
reset_ovector(common, (re->top_bracket + 1) * 2); |
6664 |
if ((re->flags & PCRE_REQCHSET) != 0) |
if (mode == JIT_COMPILE && (re->flags & PCRE_REQCHSET) != 0) |
6665 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, SLJIT_TEMPORARY_REG1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, SLJIT_TEMPORARY_REG1, 0); |
6666 |
|
|
6667 |
OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0); |
OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0); |
6674 |
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit)); |
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit)); |
6675 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0); |
6676 |
|
|
6677 |
|
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
6678 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, SLJIT_IMM, 0); |
6679 |
|
|
6680 |
/* Main part of the matching */ |
/* Main part of the matching */ |
6681 |
if ((re->options & PCRE_ANCHORED) == 0) |
if ((re->options & PCRE_ANCHORED) == 0) |
6682 |
{ |
{ |
6689 |
else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0) |
else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0) |
6690 |
fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0); |
fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0); |
6691 |
} |
} |
6692 |
if ((re->flags & PCRE_REQCHSET) != 0) |
if (mode == JIT_COMPILE && (re->flags & PCRE_REQCHSET) != 0) |
6693 |
reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0); |
reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0); |
6694 |
|
|
6695 |
/* Store the current STR_PTR in OVECTOR(0). */ |
/* Store the current STR_PTR in OVECTOR(0). */ |
6696 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); |
6697 |
/* Copy the limit of allowed recursions. */ |
/* Copy the limit of allowed recursions. */ |
6698 |
OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT); |
OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT); |
6699 |
|
/* Copy the beginning of the string. */ |
6700 |
|
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
6701 |
|
{ |
6702 |
|
jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, SLJIT_IMM, 0); |
6703 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); |
6704 |
|
JUMPHERE(jump); |
6705 |
|
} |
6706 |
|
else if (mode == JIT_PARTIAL_HARD_COMPILE) |
6707 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); |
6708 |
|
|
6709 |
compile_hotpath(common, rootfallback.cc, ccend, &rootfallback); |
compile_hotpath(common, rootfallback.cc, ccend, &rootfallback); |
6710 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
6726 |
leave = LABEL(); |
leave = LABEL(); |
6727 |
sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); |
sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); |
6728 |
|
|
6729 |
|
if (mode != JIT_COMPILE) |
6730 |
|
{ |
6731 |
|
common->partialmatchlabel = LABEL(); |
6732 |
|
set_jumps(common->partialmatch, common->partialmatchlabel); |
6733 |
|
return_with_partial_match(common, leave); |
6734 |
|
} |
6735 |
|
|
6736 |
empty_match_fallback = LABEL(); |
empty_match_fallback = LABEL(); |
6737 |
compile_fallbackpath(common, rootfallback.top); |
compile_fallbackpath(common, rootfallback.top); |
6738 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
6744 |
|
|
6745 |
SLJIT_ASSERT(rootfallback.prev == NULL); |
SLJIT_ASSERT(rootfallback.prev == NULL); |
6746 |
|
|
6747 |
|
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
6748 |
|
{ |
6749 |
|
jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, SLJIT_IMM, -1); |
6750 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR); |
6751 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, SLJIT_IMM, -1); |
6752 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, TMP1, 0); |
6753 |
|
JUMPHERE(jump); |
6754 |
|
} |
6755 |
|
|
6756 |
/* Check we have remaining characters. */ |
/* Check we have remaining characters. */ |
6757 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
6758 |
|
|
6760 |
{ |
{ |
6761 |
if ((re->options & PCRE_FIRSTLINE) == 0) |
if ((re->options & PCRE_FIRSTLINE) == 0) |
6762 |
{ |
{ |
6763 |
if (study != NULL && study->minlength > 1) |
if (mode == JIT_COMPILE && study != NULL && study->minlength > 1) |
6764 |
{ |
{ |
6765 |
OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength)); |
OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength)); |
6766 |
CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop); |
CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop); |
6770 |
} |
} |
6771 |
else |
else |
6772 |
{ |
{ |
6773 |
if (study != NULL && study->minlength > 1) |
if (mode == JIT_COMPILE && study != NULL && study->minlength > 1) |
6774 |
{ |
{ |
6775 |
OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength)); |
OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength)); |
6776 |
OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0); |
OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0); |
6784 |
} |
} |
6785 |
} |
} |
6786 |
|
|
6787 |
|
/* No more remaining characters. */ |
6788 |
if (reqbyte_notfound != NULL) |
if (reqbyte_notfound != NULL) |
6789 |
JUMPHERE(reqbyte_notfound); |
JUMPHERE(reqbyte_notfound); |
6790 |
/* Copy OVECTOR(1) to OVECTOR(0) */ |
|
6791 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
6792 |
|
CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, SLJIT_IMM, 0, common->partialmatchlabel); |
6793 |
|
|
6794 |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
6795 |
JUMPTO(SLJIT_JUMP, leave); |
JUMPTO(SLJIT_JUMP, leave); |
6796 |
|
|
6833 |
OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE); |
OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE); |
6834 |
|
|
6835 |
sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize)); |
sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize)); |
6836 |
alloc_error = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); |
jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); |
6837 |
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
6838 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); |
6839 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top)); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top)); |
6842 |
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
6843 |
|
|
6844 |
/* Allocation failed. */ |
/* Allocation failed. */ |
6845 |
JUMPHERE(alloc_error); |
JUMPHERE(jump); |
6846 |
/* We break the return address cache here, but this is a really rare case. */ |
/* We break the return address cache here, but this is a really rare case. */ |
6847 |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT); |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT); |
6848 |
JUMPTO(SLJIT_JUMP, leave); |
JUMPTO(SLJIT_JUMP, leave); |
6916 |
if (executable_func == NULL) |
if (executable_func == NULL) |
6917 |
return; |
return; |
6918 |
|
|
6919 |
function = SLJIT_MALLOC(sizeof(executable_function)); |
/* Reuse the function descriptor if possible. */ |
6920 |
if (function == NULL) |
if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL) |
6921 |
|
functions = (executable_functions *)extra->executable_jit; |
6922 |
|
else |
6923 |
{ |
{ |
6924 |
/* This case is highly unlikely since we just recently |
functions = SLJIT_MALLOC(sizeof(executable_functions)); |
6925 |
freed a lot of memory. Although not impossible. */ |
if (functions == NULL) |
6926 |
sljit_free_code(executable_func); |
{ |
6927 |
return; |
/* This case is highly unlikely since we just recently |
6928 |
|
freed a lot of memory. Although not impossible. */ |
6929 |
|
sljit_free_code(executable_func); |
6930 |
|
return; |
6931 |
|
} |
6932 |
|
memset(functions, 0, sizeof(executable_functions)); |
6933 |
|
extra->executable_jit = functions; |
6934 |
|
extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT; |
6935 |
} |
} |
6936 |
|
|
6937 |
function->executable_func = executable_func; |
functions->executable_funcs[mode] = executable_func; |
6938 |
function->executable_size = executable_size; |
functions->executable_sizes[mode] = executable_size; |
|
function->callback = NULL; |
|
|
function->userdata = NULL; |
|
|
extra->executable_jit = function; |
|
|
extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT; |
|
6939 |
} |
} |
6940 |
|
|
6941 |
static int jit_machine_stack_exec(jit_arguments *arguments, executable_function *function) |
static int jit_machine_stack_exec(jit_arguments *arguments, void* executable_func) |
6942 |
{ |
{ |
6943 |
union { |
union { |
6944 |
void* executable_func; |
void* executable_func; |
6952 |
local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE; |
local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE; |
6953 |
local_stack.max_limit = local_stack.limit; |
local_stack.max_limit = local_stack.limit; |
6954 |
arguments->stack = &local_stack; |
arguments->stack = &local_stack; |
6955 |
convert_executable_func.executable_func = function->executable_func; |
convert_executable_func.executable_func = executable_func; |
6956 |
return convert_executable_func.call_executable_func(arguments); |
return convert_executable_func.call_executable_func(arguments); |
6957 |
} |
} |
6958 |
|
|
6959 |
int |
int |
6960 |
PRIV(jit_exec)(const REAL_PCRE *re, void *executable_func, |
PRIV(jit_exec)(const REAL_PCRE *re, void *executable_funcs, |
6961 |
const pcre_uchar *subject, int length, int start_offset, int options, |
const pcre_uchar *subject, int length, int start_offset, int options, |
6962 |
int match_limit, int *offsets, int offsetcount) |
int match_limit, int *offsets, int offsetcount) |
6963 |
{ |
{ |
6964 |
executable_function *function = (executable_function*)executable_func; |
executable_functions *functions = (executable_functions *)executable_funcs; |
6965 |
union { |
union { |
6966 |
void* executable_func; |
void* executable_func; |
6967 |
jit_function call_executable_func; |
jit_function call_executable_func; |
6969 |
jit_arguments arguments; |
jit_arguments arguments; |
6970 |
int maxoffsetcount; |
int maxoffsetcount; |
6971 |
int retval; |
int retval; |
6972 |
|
int mode = JIT_COMPILE; |
6973 |
|
|
6974 |
|
if ((options & PCRE_PARTIAL_HARD) != 0) |
6975 |
|
mode = JIT_PARTIAL_HARD_COMPILE; |
6976 |
|
else if ((options & PCRE_PARTIAL_SOFT) != 0) |
6977 |
|
mode = JIT_PARTIAL_SOFT_COMPILE; |
6978 |
|
|
6979 |
|
if (functions->executable_funcs[mode] == NULL) |
6980 |
|
return PCRE_ERROR_NULL; |
6981 |
|
|
6982 |
/* Sanity checks should be handled by pcre_exec. */ |
/* Sanity checks should be handled by pcre_exec. */ |
6983 |
arguments.stack = NULL; |
arguments.stack = NULL; |
7004 |
offsetcount = maxoffsetcount; |
offsetcount = maxoffsetcount; |
7005 |
arguments.offsetcount = offsetcount; |
arguments.offsetcount = offsetcount; |
7006 |
|
|
7007 |
if (function->callback) |
if (functions->callback) |
7008 |
arguments.stack = (struct sljit_stack*)function->callback(function->userdata); |
arguments.stack = (struct sljit_stack *)functions->callback(functions->userdata); |
7009 |
else |
else |
7010 |
arguments.stack = (struct sljit_stack*)function->userdata; |
arguments.stack = (struct sljit_stack *)functions->userdata; |
7011 |
|
|
7012 |
if (arguments.stack == NULL) |
if (arguments.stack == NULL) |
7013 |
retval = jit_machine_stack_exec(&arguments, function); |
retval = jit_machine_stack_exec(&arguments, functions->executable_funcs[mode]); |
7014 |
else |
else |
7015 |
{ |
{ |
7016 |
convert_executable_func.executable_func = function->executable_func; |
convert_executable_func.executable_func = functions->executable_funcs[mode]; |
7017 |
retval = convert_executable_func.call_executable_func(&arguments); |
retval = convert_executable_func.call_executable_func(&arguments); |
7018 |
} |
} |
7019 |
|
|
7023 |
} |
} |
7024 |
|
|
7025 |
void |
void |
7026 |
PRIV(jit_free)(void *executable_func) |
PRIV(jit_free)(void *executable_funcs) |
7027 |
{ |
{ |
7028 |
executable_function *function = (executable_function*)executable_func; |
int i; |
7029 |
sljit_free_code(function->executable_func); |
executable_functions *functions = (executable_functions *)executable_funcs; |
7030 |
SLJIT_FREE(function); |
for (i = 0; i < JIT_NUMBER_OF_COMPILE_TYPES; i++) |
7031 |
|
{ |
7032 |
|
if (functions->executable_funcs[i] != NULL) |
7033 |
|
sljit_free_code(functions->executable_funcs[i]); |
7034 |
|
} |
7035 |
|
SLJIT_FREE(functions); |
7036 |
} |
} |
7037 |
|
|
7038 |
int |
int |
7039 |
PRIV(jit_get_size)(void *executable_func) |
PRIV(jit_get_size)(void *executable_funcs) |
7040 |
{ |
{ |
7041 |
return ((executable_function*)executable_func)->executable_size; |
return ((executable_functions *)executable_funcs)->executable_sizes[PCRE_STUDY_JIT_COMPILE]; |
7042 |
} |
} |
7043 |
|
|
7044 |
const char* |
const char* |
7072 |
pcre16_jit_stack_free(pcre16_jit_stack *stack) |
pcre16_jit_stack_free(pcre16_jit_stack *stack) |
7073 |
#endif |
#endif |
7074 |
{ |
{ |
7075 |
sljit_free_stack((struct sljit_stack*)stack); |
sljit_free_stack((struct sljit_stack *)stack); |
7076 |
} |
} |
7077 |
|
|
7078 |
#ifdef COMPILE_PCRE8 |
#ifdef COMPILE_PCRE8 |
7083 |
pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata) |
pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata) |
7084 |
#endif |
#endif |
7085 |
{ |
{ |
7086 |
executable_function *function; |
executable_functions *functions; |
7087 |
if (extra != NULL && |
if (extra != NULL && |
7088 |
(extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && |
(extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && |
7089 |
extra->executable_jit != NULL) |
extra->executable_jit != NULL) |
7090 |
{ |
{ |
7091 |
function = (executable_function*)extra->executable_jit; |
functions = (executable_functions *)extra->executable_jit; |
7092 |
function->callback = callback; |
functions->callback = callback; |
7093 |
function->userdata = userdata; |
functions->userdata = userdata; |
7094 |
} |
} |
7095 |
} |
} |
7096 |
|
|