| 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 |
pcre_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; |
| 355 |
frame_setstrbegin = -1 |
frame_setstrbegin = -1 |
| 356 |
}; |
}; |
| 357 |
|
|
| 358 |
|
/* Undefine sljit macros. */ |
| 359 |
|
#undef CMP |
| 360 |
|
|
| 361 |
/* Used for accessing the elements of the stack. */ |
/* Used for accessing the elements of the stack. */ |
| 362 |
#define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w)) |
#define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w)) |
| 363 |
|
|
| 364 |
#define TMP1 SLJIT_TEMPORARY_REG1 |
#define TMP1 SLJIT_TEMPORARY_REG1 |
| 365 |
#define TMP2 SLJIT_TEMPORARY_REG3 |
#define TMP2 SLJIT_TEMPORARY_REG3 |
| 366 |
#define TMP3 SLJIT_TEMPORARY_EREG2 |
#define TMP3 SLJIT_TEMPORARY_EREG2 |
| 367 |
#define STR_PTR SLJIT_GENERAL_REG1 |
#define STR_PTR SLJIT_SAVED_REG1 |
| 368 |
#define STR_END SLJIT_GENERAL_REG2 |
#define STR_END SLJIT_SAVED_REG2 |
| 369 |
#define STACK_TOP SLJIT_TEMPORARY_REG2 |
#define STACK_TOP SLJIT_TEMPORARY_REG2 |
| 370 |
#define STACK_LIMIT SLJIT_GENERAL_REG3 |
#define STACK_LIMIT SLJIT_SAVED_REG3 |
| 371 |
#define ARGUMENTS SLJIT_GENERAL_EREG1 |
#define ARGUMENTS SLJIT_SAVED_EREG1 |
| 372 |
#define CALL_COUNT SLJIT_GENERAL_EREG2 |
#define CALL_COUNT SLJIT_SAVED_EREG2 |
| 373 |
#define RETURN_ADDR SLJIT_TEMPORARY_EREG1 |
#define RETURN_ADDR SLJIT_TEMPORARY_EREG1 |
| 374 |
|
|
| 375 |
/* Locals layout. */ |
/* Locals layout. */ |
| 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]) |
| 805 |
int offset; |
int offset; |
| 806 |
|
|
| 807 |
/* >= 1 + shortest item size (2) */ |
/* >= 1 + shortest item size (2) */ |
| 808 |
|
SLJIT_UNUSED_ARG(stacktop); |
| 809 |
SLJIT_ASSERT(stackpos >= stacktop + 2); |
SLJIT_ASSERT(stackpos >= stacktop + 2); |
| 810 |
|
|
| 811 |
stackpos = STACK(stackpos); |
stackpos = STACK(stackpos); |
| 1214 |
int i; |
int i; |
| 1215 |
/* At this point we can freely use all temporary registers. */ |
/* At this point we can freely use all temporary registers. */ |
| 1216 |
/* TMP1 returns with begin - 1. */ |
/* TMP1 returns with begin - 1. */ |
| 1217 |
OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); |
OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); |
| 1218 |
if (length < 8) |
if (length < 8) |
| 1219 |
{ |
{ |
| 1220 |
for (i = 0; i < length; i++) |
for (i = 0; i < length; i++) |
| 1238 |
struct sljit_jump *earlyexit; |
struct sljit_jump *earlyexit; |
| 1239 |
|
|
| 1240 |
/* At this point we can freely use all registers. */ |
/* At this point we can freely use all registers. */ |
| 1241 |
OP1(SLJIT_MOV, SLJIT_GENERAL_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
| 1242 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0); |
| 1243 |
|
|
| 1244 |
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0); |
| 1245 |
OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount)); |
OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount)); |
| 1246 |
OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); |
OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); |
| 1247 |
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); |
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); |
| 1248 |
OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START); |
OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START); |
| 1249 |
/* Unlikely, but possible */ |
/* Unlikely, but possible */ |
| 1250 |
earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); |
earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); |
| 1251 |
loop = LABEL(); |
loop = LABEL(); |
| 1252 |
OP2(SLJIT_SUB, SLJIT_GENERAL_REG2, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), 0, SLJIT_TEMPORARY_REG1, 0); |
OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_TEMPORARY_REG1, 0); |
| 1253 |
OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_GENERAL_REG1, 0, SLJIT_IMM, sizeof(sljit_w)); |
OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_w)); |
| 1254 |
/* Copy the integer value to the output buffer */ |
/* Copy the integer value to the output buffer */ |
| 1255 |
#ifdef COMPILE_PCRE16 |
#ifdef COMPILE_PCRE16 |
| 1256 |
OP2(SLJIT_ASHR, SLJIT_GENERAL_REG2, 0, SLJIT_GENERAL_REG2, 0, SLJIT_IMM, 1); |
OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1); |
| 1257 |
#endif |
#endif |
| 1258 |
OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_GENERAL_REG2, 0); |
OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_SAVED_REG2, 0); |
| 1259 |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); |
| 1260 |
JUMPTO(SLJIT_C_NOT_ZERO, loop); |
JUMPTO(SLJIT_C_NOT_ZERO, loop); |
| 1261 |
JUMPHERE(earlyexit); |
JUMPHERE(earlyexit); |
| 1266 |
OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w)); |
OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w)); |
| 1267 |
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); |
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); |
| 1268 |
|
|
| 1269 |
/* OVECTOR(0) is never equal to SLJIT_GENERAL_REG3. */ |
/* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ |
| 1270 |
loop = LABEL(); |
loop = LABEL(); |
| 1271 |
OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w))); |
OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w))); |
| 1272 |
OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); |
OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); |
| 1273 |
CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_GENERAL_REG3, 0, loop); |
CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG3, 0, loop); |
| 1274 |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0); |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0); |
| 1275 |
} |
} |
| 1276 |
else |
else |
| 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; |
DEFINE_COMPILER; |
| 1458 |
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
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; |
| 1510 |
|
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); |
| 5099 |
SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS); |
SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS); |
| 5100 |
*type = *opcode; |
*type = *opcode; |
| 5101 |
cc++; |
cc++; |
| 5102 |
class_len = (*type < OP_XCLASS) ? (1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0); |
class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0); |
| 5103 |
*opcode = cc[class_len - 1]; |
*opcode = cc[class_len - 1]; |
| 5104 |
if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) |
if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) |
| 5105 |
{ |
{ |
| 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_GENERAL_REG1, 0); |
OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0); |
| 6668 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_GENERAL_REG1, 0); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1, 0); |
| 6669 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); |
| 6670 |
OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end)); |
OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end)); |
| 6671 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); |
| 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 |
{ |
{ |
| 6683 |
mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0); |
mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0); |
| 6684 |
/* Forward search if possible. */ |
/* Forward search if possible. */ |
| 6685 |
if ((re->flags & PCRE_FIRSTSET) != 0) |
if ((re->flags & PCRE_FIRSTSET) != 0) |
| 6686 |
fast_forward_first_char(common, re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0); |
fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0); |
| 6687 |
else if ((re->flags & PCRE_STARTLINE) != 0) |
else if ((re->flags & PCRE_STARTLINE) != 0) |
| 6688 |
fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0); |
fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0); |
| 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, 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))) |
| 6724 |
/* This means we have a match. Update the ovector. */ |
/* This means we have a match. Update the ovector. */ |
| 6725 |
copy_ovector(common, re->top_bracket + 1); |
copy_ovector(common, re->top_bracket + 1); |
| 6726 |
leave = LABEL(); |
leave = LABEL(); |
| 6727 |
sljit_emit_return(compiler, SLJIT_UNUSED, 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); |
| 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; |
| 6997 |
number of captured strings in the same way as pcre_exec(), so that the user |
number of captured strings in the same way as pcre_exec(), so that the user |
| 6998 |
gets the same result with and without JIT. */ |
gets the same result with and without JIT. */ |
| 6999 |
|
|
| 7000 |
offsetcount = ((offsetcount - (offsetcount % 3)) * 2)/3; |
if (offsetcount != 2) |
| 7001 |
|
offsetcount = ((offsetcount - (offsetcount % 3)) * 2) / 3; |
| 7002 |
maxoffsetcount = (re->top_bracket + 1) * 2; |
maxoffsetcount = (re->top_bracket + 1) * 2; |
| 7003 |
if (offsetcount > maxoffsetcount) |
if (offsetcount > maxoffsetcount) |
| 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* |
| 7045 |
|
PRIV(jit_get_target)(void) |
| 7046 |
|
{ |
| 7047 |
|
return sljit_get_platform_name(); |
| 7048 |
} |
} |
| 7049 |
|
|
| 7050 |
#ifdef COMPILE_PCRE8 |
#ifdef COMPILE_PCRE8 |
| 7051 |
PCRE_EXP_DECL pcre_jit_stack * |
PCRE_EXP_DECL pcre_jit_stack * |
| 7052 |
pcre_jit_stack_alloc(int startsize, int maxsize) |
pcre_jit_stack_alloc(int startsize, int maxsize) |
| 7053 |
#else |
#else |
| 7054 |
PCRE_EXP_DECL pcre_jit_stack * |
PCRE_EXP_DECL pcre16_jit_stack * |
| 7055 |
pcre16_jit_stack_alloc(int startsize, int maxsize) |
pcre16_jit_stack_alloc(int startsize, int maxsize) |
| 7056 |
#endif |
#endif |
| 7057 |
{ |
{ |
| 7061 |
startsize = maxsize; |
startsize = maxsize; |
| 7062 |
startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); |
startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); |
| 7063 |
maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); |
maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); |
| 7064 |
return (pcre_jit_stack*)sljit_allocate_stack(startsize, maxsize); |
return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize); |
| 7065 |
} |
} |
| 7066 |
|
|
| 7067 |
#ifdef COMPILE_PCRE8 |
#ifdef COMPILE_PCRE8 |
| 7069 |
pcre_jit_stack_free(pcre_jit_stack *stack) |
pcre_jit_stack_free(pcre_jit_stack *stack) |
| 7070 |
#else |
#else |
| 7071 |
PCRE_EXP_DECL void |
PCRE_EXP_DECL void |
| 7072 |
pcre16_jit_stack_free(pcre_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 |
| 7080 |
pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata) |
pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata) |
| 7081 |
#else |
#else |
| 7082 |
PCRE_EXP_DECL void |
PCRE_EXP_DECL void |
| 7083 |
pcre16_assign_jit_stack(pcre16_extra *extra, pcre_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 |
|
|
| 7103 |
PCRE_EXP_DECL pcre_jit_stack * |
PCRE_EXP_DECL pcre_jit_stack * |
| 7104 |
pcre_jit_stack_alloc(int startsize, int maxsize) |
pcre_jit_stack_alloc(int startsize, int maxsize) |
| 7105 |
#else |
#else |
| 7106 |
PCRE_EXP_DECL pcre_jit_stack * |
PCRE_EXP_DECL pcre16_jit_stack * |
| 7107 |
pcre16_jit_stack_alloc(int startsize, int maxsize) |
pcre16_jit_stack_alloc(int startsize, int maxsize) |
| 7108 |
#endif |
#endif |
| 7109 |
{ |
{ |
| 7117 |
pcre_jit_stack_free(pcre_jit_stack *stack) |
pcre_jit_stack_free(pcre_jit_stack *stack) |
| 7118 |
#else |
#else |
| 7119 |
PCRE_EXP_DECL void |
PCRE_EXP_DECL void |
| 7120 |
pcre16_jit_stack_free(pcre_jit_stack *stack) |
pcre16_jit_stack_free(pcre16_jit_stack *stack) |
| 7121 |
#endif |
#endif |
| 7122 |
{ |
{ |
| 7123 |
(void)stack; |
(void)stack; |
| 7128 |
pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata) |
pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata) |
| 7129 |
#else |
#else |
| 7130 |
PCRE_EXP_DECL void |
PCRE_EXP_DECL void |
| 7131 |
pcre16_assign_jit_stack(pcre16_extra *extra, pcre_jit_callback callback, void *userdata) |
pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata) |
| 7132 |
#endif |
#endif |
| 7133 |
{ |
{ |
| 7134 |
(void)extra; |
(void)extra; |