Parent Directory
|
Revision Log
|
Patch
revision 1306 by zherczeg, Mon Apr 1 17:04:17 2013 UTC | revision 1640 by zherczeg, Mon Feb 29 09:21:21 2016 UTC | |
---|---|---|
# | Line 52 POSSIBILITY OF SUCH DAMAGE. | Line 52 POSSIBILITY OF SUCH DAMAGE. |
52 | we just include it. This way we don't need to touch the build | we just include it. This way we don't need to touch the build |
53 | system files. */ | system files. */ |
54 | ||
55 | #define SLJIT_MALLOC(size) (PUBL(malloc))(size) | #define SLJIT_MALLOC(size, allocator_data) (PUBL(malloc))(size) |
56 | #define SLJIT_FREE(ptr) (PUBL(free))(ptr) | #define SLJIT_FREE(ptr, allocator_data) (PUBL(free))(ptr) |
57 | #define SLJIT_CONFIG_AUTO 1 | #define SLJIT_CONFIG_AUTO 1 |
58 | #define SLJIT_CONFIG_STATIC 1 | #define SLJIT_CONFIG_STATIC 1 |
59 | #define SLJIT_VERBOSE 0 | #define SLJIT_VERBOSE 0 |
# | Line 168 typedef struct jit_arguments { | Line 168 typedef struct jit_arguments { |
168 | pcre_uchar *mark_ptr; | pcre_uchar *mark_ptr; |
169 | void *callout_data; | void *callout_data; |
170 | /* Everything else after. */ | /* Everything else after. */ |
171 | pcre_uint32 limit_match; | |
172 | int real_offset_count; | int real_offset_count; |
173 | int offset_count; | int offset_count; |
int call_limit; | ||
174 | pcre_uint8 notbol; | pcre_uint8 notbol; |
175 | pcre_uint8 noteol; | pcre_uint8 noteol; |
176 | pcre_uint8 notempty; | pcre_uint8 notempty; |
# | Line 179 typedef struct jit_arguments { | Line 179 typedef struct jit_arguments { |
179 | ||
180 | typedef struct executable_functions { | typedef struct executable_functions { |
181 | void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES]; | void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES]; |
182 | void *read_only_data_heads[JIT_NUMBER_OF_COMPILE_MODES]; | |
183 | sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES]; | |
184 | PUBL(jit_callback) callback; | PUBL(jit_callback) callback; |
185 | void *userdata; | void *userdata; |
186 | pcre_uint32 top_bracket; | sljit_u32 top_bracket; |
187 | sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES]; | sljit_u32 limit_match; |
188 | } executable_functions; | } executable_functions; |
189 | ||
190 | typedef struct jump_list { | typedef struct jump_list { |
# | Line 196 typedef struct stub_list { | Line 198 typedef struct stub_list { |
198 | struct stub_list *next; | struct stub_list *next; |
199 | } stub_list; | } stub_list; |
200 | ||
201 | typedef struct label_addr_list { | |
202 | struct sljit_label *label; | |
203 | sljit_uw *update_addr; | |
204 | struct label_addr_list *next; | |
205 | } label_addr_list; | |
206 | ||
207 | enum frame_types { | enum frame_types { |
208 | no_frame = -1, | no_frame = -1, |
209 | no_stack = -2 | no_stack = -2 |
# | Line 210 typedef int (SLJIT_CALL *jit_function)(j | Line 218 typedef int (SLJIT_CALL *jit_function)(j |
218 | ||
219 | /* The following structure is the key data type for the recursive | /* The following structure is the key data type for the recursive |
220 | code generator. It is allocated by compile_matchingpath, and contains | code generator. It is allocated by compile_matchingpath, and contains |
221 | the aguments for compile_backtrackingpath. Must be the first member | the arguments for compile_backtrackingpath. Must be the first member |
222 | of its descendants. */ | of its descendants. */ |
223 | typedef struct backtrack_common { | typedef struct backtrack_common { |
224 | /* Concatenation stack. */ | /* Concatenation stack. */ |
# | Line 269 typedef struct braminzero_backtrack { | Line 277 typedef struct braminzero_backtrack { |
277 | struct sljit_label *matchingpath; | struct sljit_label *matchingpath; |
278 | } braminzero_backtrack; | } braminzero_backtrack; |
279 | ||
280 | typedef struct iterator_backtrack { | typedef struct char_iterator_backtrack { |
281 | backtrack_common common; | |
282 | /* Next iteration. */ | |
283 | struct sljit_label *matchingpath; | |
284 | union { | |
285 | jump_list *backtracks; | |
286 | struct { | |
287 | unsigned int othercasebit; | |
288 | pcre_uchar chr; | |
289 | BOOL enabled; | |
290 | } charpos; | |
291 | } u; | |
292 | } char_iterator_backtrack; | |
293 | ||
294 | typedef struct ref_iterator_backtrack { | |
295 | backtrack_common common; | backtrack_common common; |
296 | /* Next iteration. */ | /* Next iteration. */ |
297 | struct sljit_label *matchingpath; | struct sljit_label *matchingpath; |
298 | } iterator_backtrack; | } ref_iterator_backtrack; |
299 | ||
300 | typedef struct recurse_entry { | typedef struct recurse_entry { |
301 | struct recurse_entry *next; | struct recurse_entry *next; |
# | Line 305 typedef struct then_trap_backtrack { | Line 327 typedef struct then_trap_backtrack { |
327 | int framesize; | int framesize; |
328 | } then_trap_backtrack; | } then_trap_backtrack; |
329 | ||
330 | #define MAX_RANGE_SIZE 6 | #define MAX_RANGE_SIZE 4 |
331 | ||
332 | typedef struct compiler_common { | typedef struct compiler_common { |
333 | /* The sljit ceneric compiler. */ | /* The sljit ceneric compiler. */ |
# | Line 313 typedef struct compiler_common { | Line 335 typedef struct compiler_common { |
335 | /* First byte code. */ | /* First byte code. */ |
336 | pcre_uchar *start; | pcre_uchar *start; |
337 | /* Maps private data offset to each opcode. */ | /* Maps private data offset to each opcode. */ |
338 | sljit_si *private_data_ptrs; | sljit_s32 *private_data_ptrs; |
339 | /* Chain list of read-only data ptrs. */ | |
340 | void *read_only_data_head; | |
341 | /* Tells whether the capturing bracket is optimized. */ | /* Tells whether the capturing bracket is optimized. */ |
342 | pcre_uint8 *optimized_cbracket; | sljit_u8 *optimized_cbracket; |
343 | /* Tells whether the starting offset is a target of then. */ | /* Tells whether the starting offset is a target of then. */ |
344 | pcre_uint8 *then_offsets; | sljit_u8 *then_offsets; |
345 | /* Current position where a THEN must jump. */ | /* Current position where a THEN must jump. */ |
346 | then_trap_backtrack *then_trap; | then_trap_backtrack *then_trap; |
347 | /* Starting offset of private data for capturing brackets. */ | /* Starting offset of private data for capturing brackets. */ |
348 | int cbra_ptr; | sljit_s32 cbra_ptr; |
349 | /* Output vector starting point. Must be divisible by 2. */ | /* Output vector starting point. Must be divisible by 2. */ |
350 | int ovector_start; | sljit_s32 ovector_start; |
351 | /* Points to the starting character of the current match. */ | |
352 | sljit_s32 start_ptr; | |
353 | /* Last known position of the requested byte. */ | /* Last known position of the requested byte. */ |
354 | int req_char_ptr; | sljit_s32 req_char_ptr; |
355 | /* Head of the last recursion. */ | /* Head of the last recursion. */ |
356 | int recursive_head_ptr; | sljit_s32 recursive_head_ptr; |
357 | /* First inspected character for partial matching. */ | /* First inspected character for partial matching. |
358 | int start_used_ptr; | (Needed for avoiding zero length partial matches.) */ |
359 | sljit_s32 start_used_ptr; | |
360 | /* Starting pointer for partial soft matches. */ | /* Starting pointer for partial soft matches. */ |
361 | int hit_start; | sljit_s32 hit_start; |
362 | /* End pointer of the first line. */ | /* Pointer of the match end position. */ |
363 | int first_line_end; | sljit_s32 match_end_ptr; |
364 | /* Points to the marked string. */ | /* Points to the marked string. */ |
365 | int mark_ptr; | sljit_s32 mark_ptr; |
366 | /* Recursive control verb management chain. */ | /* Recursive control verb management chain. */ |
367 | int control_head_ptr; | sljit_s32 control_head_ptr; |
368 | /* Points to the last matched capture block index. */ | /* Points to the last matched capture block index. */ |
369 | int capture_last_ptr; | sljit_s32 capture_last_ptr; |
370 | /* Points to the starting position of the current match. */ | /* Fast forward skipping byte code pointer. */ |
371 | int start_ptr; | pcre_uchar *fast_forward_bc_ptr; |
372 | /* Locals used by fast fail optimization. */ | |
373 | sljit_s32 fast_fail_start_ptr; | |
374 | sljit_s32 fast_fail_end_ptr; | |
375 | ||
376 | /* Flipped and lower case tables. */ | /* Flipped and lower case tables. */ |
377 | const pcre_uint8 *fcc; | const sljit_u8 *fcc; |
378 | sljit_sw lcc; | sljit_sw lcc; |
379 | /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */ | /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */ |
380 | int mode; | int mode; |
381 | /* TRUE, when minlength is greater than 0. */ | |
382 | BOOL might_be_empty; | |
383 | /* \K is found in the pattern. */ | /* \K is found in the pattern. */ |
384 | BOOL has_set_som; | BOOL has_set_som; |
385 | /* (*SKIP:arg) is found in the pattern. */ | /* (*SKIP:arg) is found in the pattern. */ |
386 | BOOL has_skip_arg; | BOOL has_skip_arg; |
387 | /* (*THEN) is found in the pattern. */ | /* (*THEN) is found in the pattern. */ |
388 | BOOL has_then; | BOOL has_then; |
389 | /* Needs to know the start position anytime. */ | /* (*SKIP) or (*SKIP:arg) is found in lookbehind assertion. */ |
390 | BOOL needs_start_ptr; | BOOL has_skip_in_assert_back; |
391 | /* Currently in recurse or negative assert. */ | /* Currently in recurse or negative assert. */ |
392 | BOOL local_exit; | BOOL local_exit; |
393 | /* Currently in a positive assert. */ | /* Currently in a positive assert. */ |
394 | BOOL positive_assert; | BOOL positive_assert; |
395 | /* Newline control. */ | /* Newline control. */ |
396 | int nltype; | int nltype; |
397 | sljit_u32 nlmax; | |
398 | sljit_u32 nlmin; | |
399 | int newline; | int newline; |
400 | int bsr_nltype; | int bsr_nltype; |
401 | sljit_u32 bsr_nlmax; | |
402 | sljit_u32 bsr_nlmin; | |
403 | /* Dollar endonly. */ | /* Dollar endonly. */ |
404 | int endonly; | int endonly; |
405 | /* Tables. */ | /* Tables. */ |
406 | sljit_sw ctypes; | sljit_sw ctypes; |
int digits[2 + MAX_RANGE_SIZE]; | ||
407 | /* Named capturing brackets. */ | /* Named capturing brackets. */ |
408 | sljit_uw name_table; | pcre_uchar *name_table; |
409 | sljit_sw name_count; | sljit_sw name_count; |
410 | sljit_sw name_entry_size; | sljit_sw name_entry_size; |
411 | ||
# | Line 379 typedef struct compiler_common { | Line 414 typedef struct compiler_common { |
414 | struct sljit_label *quit_label; | struct sljit_label *quit_label; |
415 | struct sljit_label *forced_quit_label; | struct sljit_label *forced_quit_label; |
416 | struct sljit_label *accept_label; | struct sljit_label *accept_label; |
417 | struct sljit_label *ff_newline_shortcut; | |
418 | stub_list *stubs; | stub_list *stubs; |
419 | label_addr_list *label_addrs; | |
420 | recurse_entry *entries; | recurse_entry *entries; |
421 | recurse_entry *currententry; | recurse_entry *currententry; |
422 | jump_list *partialmatch; | jump_list *partialmatch; |
# | Line 402 typedef struct compiler_common { | Line 439 typedef struct compiler_common { |
439 | BOOL utf; | BOOL utf; |
440 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
441 | BOOL use_ucp; | BOOL use_ucp; |
442 | #endif | jump_list *getucd; |
#ifndef COMPILE_PCRE32 | ||
jump_list *utfreadchar; | ||
443 | #endif | #endif |
444 | #ifdef COMPILE_PCRE8 | #ifdef COMPILE_PCRE8 |
445 | jump_list *utfreadchar; | |
446 | jump_list *utfreadchar16; | |
447 | jump_list *utfreadtype8; | jump_list *utfreadtype8; |
448 | #endif | #endif |
449 | #endif /* SUPPORT_UTF */ | #endif /* SUPPORT_UTF */ |
#ifdef SUPPORT_UCP | ||
jump_list *getucd; | ||
#endif | ||
450 | } compiler_common; | } compiler_common; |
451 | ||
452 | /* For byte_sequence_compare. */ | /* For byte_sequence_compare. */ |
# | Line 423 typedef struct compare_context { | Line 457 typedef struct compare_context { |
457 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED |
458 | int ucharptr; | int ucharptr; |
459 | union { | union { |
460 | sljit_si asint; | sljit_s32 asint; |
461 | sljit_uh asushort; | sljit_u16 asushort; |
462 | #if defined COMPILE_PCRE8 | #if defined COMPILE_PCRE8 |
463 | sljit_ub asbyte; | sljit_u8 asbyte; |
464 | sljit_ub asuchars[4]; | sljit_u8 asuchars[4]; |
465 | #elif defined COMPILE_PCRE16 | #elif defined COMPILE_PCRE16 |
466 | sljit_uh asuchars[2]; | sljit_u16 asuchars[2]; |
467 | #elif defined COMPILE_PCRE32 | #elif defined COMPILE_PCRE32 |
468 | sljit_ui asuchars[1]; | sljit_u32 asuchars[1]; |
469 | #endif | #endif |
470 | } c; | } c; |
471 | union { | union { |
472 | sljit_si asint; | sljit_s32 asint; |
473 | sljit_uh asushort; | sljit_u16 asushort; |
474 | #if defined COMPILE_PCRE8 | #if defined COMPILE_PCRE8 |
475 | sljit_ub asbyte; | sljit_u8 asbyte; |
476 | sljit_ub asuchars[4]; | sljit_u8 asuchars[4]; |
477 | #elif defined COMPILE_PCRE16 | #elif defined COMPILE_PCRE16 |
478 | sljit_uh asuchars[2]; | sljit_u16 asuchars[2]; |
479 | #elif defined COMPILE_PCRE32 | #elif defined COMPILE_PCRE32 |
480 | sljit_ui asuchars[1]; | sljit_u32 asuchars[1]; |
481 | #endif | #endif |
482 | } oc; | } oc; |
483 | #endif | #endif |
# | Line 455 typedef struct compare_context { | Line 489 typedef struct compare_context { |
489 | /* Used for accessing the elements of the stack. */ | /* Used for accessing the elements of the stack. */ |
490 | #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_sw)) | #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_sw)) |
491 | ||
492 | #define TMP1 SLJIT_SCRATCH_REG1 | #define TMP1 SLJIT_R0 |
493 | #define TMP2 SLJIT_SCRATCH_REG3 | #define TMP2 SLJIT_R2 |
494 | #define TMP3 SLJIT_TEMPORARY_EREG2 | #define TMP3 SLJIT_R3 |
495 | #define STR_PTR SLJIT_SAVED_REG1 | #define STR_PTR SLJIT_S0 |
496 | #define STR_END SLJIT_SAVED_REG2 | #define STR_END SLJIT_S1 |
497 | #define STACK_TOP SLJIT_SCRATCH_REG2 | #define STACK_TOP SLJIT_R1 |
498 | #define STACK_LIMIT SLJIT_SAVED_REG3 | #define STACK_LIMIT SLJIT_S2 |
499 | #define ARGUMENTS SLJIT_SAVED_EREG1 | #define COUNT_MATCH SLJIT_S3 |
500 | #define CALL_COUNT SLJIT_SAVED_EREG2 | #define ARGUMENTS SLJIT_S4 |
501 | #define RETURN_ADDR SLJIT_TEMPORARY_EREG1 | #define RETURN_ADDR SLJIT_R4 |
502 | ||
503 | /* Local space layout. */ | /* Local space layout. */ |
504 | /* These two locals can be used by the current opcode. */ | /* These two locals can be used by the current opcode. */ |
# | Line 474 typedef struct compare_context { | Line 508 typedef struct compare_context { |
508 | #define POSSESSIVE0 (2 * sizeof(sljit_sw)) | #define POSSESSIVE0 (2 * sizeof(sljit_sw)) |
509 | #define POSSESSIVE1 (3 * sizeof(sljit_sw)) | #define POSSESSIVE1 (3 * sizeof(sljit_sw)) |
510 | /* Max limit of recursions. */ | /* Max limit of recursions. */ |
511 | #define CALL_LIMIT (4 * sizeof(sljit_sw)) | #define LIMIT_MATCH (4 * sizeof(sljit_sw)) |
512 | /* The output vector is stored on the stack, and contains pointers | /* The output vector is stored on the stack, and contains pointers |
513 | to characters. The vector data is divided into two groups: the first | to characters. The vector data is divided into two groups: the first |
514 | group contains the start / end character pointers, and the second is | group contains the start / end character pointers, and the second is |
515 | 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. */ |
516 | #define OVECTOR_START (common->ovector_start) | #define OVECTOR_START (common->ovector_start) |
517 | #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_sw)) | #define OVECTOR(i) (OVECTOR_START + (i) * (sljit_sw)sizeof(sljit_sw)) |
518 | #define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * sizeof(sljit_sw)) | #define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * (sljit_sw)sizeof(sljit_sw)) |
519 | #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start]) | #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start]) |
520 | ||
521 | #if defined COMPILE_PCRE8 | #if defined COMPILE_PCRE8 |
522 | #define MOV_UCHAR SLJIT_MOV_UB | #define MOV_UCHAR SLJIT_MOV_U8 |
523 | #define MOVU_UCHAR SLJIT_MOVU_UB | #define MOVU_UCHAR SLJIT_MOVU_U8 |
524 | #elif defined COMPILE_PCRE16 | #elif defined COMPILE_PCRE16 |
525 | #define MOV_UCHAR SLJIT_MOV_UH | #define MOV_UCHAR SLJIT_MOV_U16 |
526 | #define MOVU_UCHAR SLJIT_MOVU_UH | #define MOVU_UCHAR SLJIT_MOVU_U16 |
527 | #elif defined COMPILE_PCRE32 | #elif defined COMPILE_PCRE32 |
528 | #define MOV_UCHAR SLJIT_MOV_UI | #define MOV_UCHAR SLJIT_MOV_U32 |
529 | #define MOVU_UCHAR SLJIT_MOVU_UI | #define MOVU_UCHAR SLJIT_MOVU_U32 |
530 | #else | #else |
531 | #error Unsupported compiling mode | #error Unsupported compiling mode |
532 | #endif | #endif |
# | Line 523 the start pointers when the end of the c | Line 557 the start pointers when the end of the c |
557 | #define GET_LOCAL_BASE(dst, dstw, offset) \ | #define GET_LOCAL_BASE(dst, dstw, offset) \ |
558 | sljit_get_local_base(compiler, (dst), (dstw), (offset)) | sljit_get_local_base(compiler, (dst), (dstw), (offset)) |
559 | ||
560 | static pcre_uchar* bracketend(pcre_uchar* cc) | #define READ_CHAR_MAX 0x7fffffff |
561 | ||
562 | static pcre_uchar *bracketend(pcre_uchar *cc) | |
563 | { | { |
564 | SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); | SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); |
565 | do cc += GET(cc, 1); while (*cc == OP_ALT); | do cc += GET(cc, 1); while (*cc == OP_ALT); |
# | Line 532 cc += 1 + LINK_SIZE; | Line 568 cc += 1 + LINK_SIZE; |
568 | return cc; | return cc; |
569 | } | } |
570 | ||
571 | static int no_alternatives(pcre_uchar *cc) | |
572 | { | |
573 | int count = 0; | |
574 | SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); | |
575 | do | |
576 | { | |
577 | cc += GET(cc, 1); | |
578 | count++; | |
579 | } | |
580 | while (*cc == OP_ALT); | |
581 | SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS); | |
582 | return count; | |
583 | } | |
584 | ||
585 | /* Functions whose might need modification for all new supported opcodes: | /* Functions whose might need modification for all new supported opcodes: |
586 | next_opcode | next_opcode |
587 | check_opcode_types | check_opcode_types |
# | Line 584 switch(*cc) | Line 634 switch(*cc) |
634 | case OP_CRMINQUERY: | case OP_CRMINQUERY: |
635 | case OP_CRRANGE: | case OP_CRRANGE: |
636 | case OP_CRMINRANGE: | case OP_CRMINRANGE: |
637 | case OP_CRPOSSTAR: | |
638 | case OP_CRPOSPLUS: | |
639 | case OP_CRPOSQUERY: | |
640 | case OP_CRPOSRANGE: | |
641 | case OP_CLASS: | case OP_CLASS: |
642 | case OP_NCLASS: | case OP_NCLASS: |
643 | case OP_REF: | case OP_REF: |
644 | case OP_REFI: | case OP_REFI: |
645 | case OP_DNREF: | |
646 | case OP_DNREFI: | |
647 | case OP_RECURSE: | case OP_RECURSE: |
648 | case OP_CALLOUT: | case OP_CALLOUT: |
649 | case OP_ALT: | case OP_ALT: |
# | Line 613 switch(*cc) | Line 669 switch(*cc) |
669 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
670 | case OP_SCOND: | case OP_SCOND: |
671 | case OP_CREF: | case OP_CREF: |
672 | case OP_NCREF: | case OP_DNCREF: |
673 | case OP_RREF: | case OP_RREF: |
674 | case OP_NRREF: | case OP_DNRREF: |
675 | case OP_DEF: | case OP_DEF: |
676 | case OP_BRAZERO: | case OP_BRAZERO: |
677 | case OP_BRAMINZERO: | case OP_BRAMINZERO: |
# | Line 735 switch(*cc) | Line 791 switch(*cc) |
791 | ||
792 | static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) | static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) |
793 | { | { |
794 | pcre_uchar *name; | int count; |
795 | pcre_uchar *name2; | pcre_uchar *slot; |
796 | int i, cbra_index; | pcre_uchar *assert_back_end = cc - 1; |
797 | ||
798 | /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ | /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ |
799 | while (cc < ccend) | while (cc < ccend) |
# | Line 746 while (cc < ccend) | Line 802 while (cc < ccend) |
802 | { | { |
803 | case OP_SET_SOM: | case OP_SET_SOM: |
804 | common->has_set_som = TRUE; | common->has_set_som = TRUE; |
805 | common->might_be_empty = TRUE; | |
806 | cc += 1; | cc += 1; |
807 | break; | break; |
808 | ||
# | Line 771 while (cc < ccend) | Line 828 while (cc < ccend) |
828 | break; | break; |
829 | ||
830 | case OP_CREF: | case OP_CREF: |
831 | i = GET2(cc, 1); | common->optimized_cbracket[GET2(cc, 1)] = 0; |
common->optimized_cbracket[i] = 0; | ||
832 | cc += 1 + IMM2_SIZE; | cc += 1 + IMM2_SIZE; |
833 | break; | break; |
834 | ||
835 | case OP_NCREF: | case OP_DNREF: |
836 | cbra_index = GET2(cc, 1); | case OP_DNREFI: |
837 | name = (pcre_uchar *)common->name_table; | case OP_DNCREF: |
838 | name2 = name; | count = GET2(cc, 1 + IMM2_SIZE); |
839 | for (i = 0; i < common->name_count; i++) | slot = common->name_table + GET2(cc, 1) * common->name_entry_size; |
840 | { | while (count-- > 0) |
841 | if (GET2(name, 0) == cbra_index) break; | { |
842 | name += common->name_entry_size; | common->optimized_cbracket[GET2(slot, 0)] = 0; |
843 | } | slot += common->name_entry_size; |
SLJIT_ASSERT(i != common->name_count); | ||
for (i = 0; i < common->name_count; i++) | ||
{ | ||
if (STRCMP_UC_UC(name2 + IMM2_SIZE, name + IMM2_SIZE) == 0) | ||
common->optimized_cbracket[GET2(name2, 0)] = 0; | ||
name2 += common->name_entry_size; | ||
844 | } | } |
845 | cc += 1 + IMM2_SIZE; | cc += 1 + 2 * IMM2_SIZE; |
846 | break; | break; |
847 | ||
848 | case OP_RECURSE: | case OP_RECURSE: |
# | Line 815 while (cc < ccend) | Line 864 while (cc < ccend) |
864 | cc += 2 + 2 * LINK_SIZE; | cc += 2 + 2 * LINK_SIZE; |
865 | break; | break; |
866 | ||
867 | case OP_ASSERTBACK: | |
868 | slot = bracketend(cc); | |
869 | if (slot > assert_back_end) | |
870 | assert_back_end = slot; | |
871 | cc += 1 + LINK_SIZE; | |
872 | break; | |
873 | ||
874 | case OP_THEN_ARG: | case OP_THEN_ARG: |
875 | common->has_then = TRUE; | common->has_then = TRUE; |
876 | common->control_head_ptr = 1; | common->control_head_ptr = 1; |
877 | /* Fall through. */ | /* Fall through. */ |
878 | ||
879 | case OP_PRUNE_ARG: | case OP_PRUNE_ARG: |
common->needs_start_ptr = TRUE; | ||
/* Fall through. */ | ||
880 | case OP_MARK: | case OP_MARK: |
881 | if (common->mark_ptr == 0) | if (common->mark_ptr == 0) |
882 | { | { |
# | Line 836 while (cc < ccend) | Line 889 while (cc < ccend) |
889 | case OP_THEN: | case OP_THEN: |
890 | common->has_then = TRUE; | common->has_then = TRUE; |
891 | common->control_head_ptr = 1; | common->control_head_ptr = 1; |
892 | /* Fall through. */ | cc += 1; |
893 | break; | |
894 | ||
case OP_PRUNE: | ||
895 | case OP_SKIP: | case OP_SKIP: |
896 | common->needs_start_ptr = TRUE; | if (cc < assert_back_end) |
897 | common->has_skip_in_assert_back = TRUE; | |
898 | cc += 1; | cc += 1; |
899 | break; | break; |
900 | ||
901 | case OP_SKIP_ARG: | case OP_SKIP_ARG: |
902 | common->control_head_ptr = 1; | common->control_head_ptr = 1; |
903 | common->has_skip_arg = TRUE; | common->has_skip_arg = TRUE; |
904 | if (cc < assert_back_end) | |
905 | common->has_skip_in_assert_back = TRUE; | |
906 | cc += 1 + 2 + cc[1]; | cc += 1 + 2 + cc[1]; |
907 | break; | break; |
908 | ||
# | Line 860 while (cc < ccend) | Line 916 while (cc < ccend) |
916 | return TRUE; | return TRUE; |
917 | } | } |
918 | ||
919 | static BOOL is_accelerated_repeat(pcre_uchar *cc) | |
920 | { | |
921 | switch(*cc) | |
922 | { | |
923 | case OP_TYPESTAR: | |
924 | case OP_TYPEMINSTAR: | |
925 | case OP_TYPEPLUS: | |
926 | case OP_TYPEMINPLUS: | |
927 | case OP_TYPEPOSSTAR: | |
928 | case OP_TYPEPOSPLUS: | |
929 | return (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI); | |
930 | ||
931 | case OP_STAR: | |
932 | case OP_MINSTAR: | |
933 | case OP_PLUS: | |
934 | case OP_MINPLUS: | |
935 | case OP_POSSTAR: | |
936 | case OP_POSPLUS: | |
937 | ||
938 | case OP_STARI: | |
939 | case OP_MINSTARI: | |
940 | case OP_PLUSI: | |
941 | case OP_MINPLUSI: | |
942 | case OP_POSSTARI: | |
943 | case OP_POSPLUSI: | |
944 | ||
945 | case OP_NOTSTAR: | |
946 | case OP_NOTMINSTAR: | |
947 | case OP_NOTPLUS: | |
948 | case OP_NOTMINPLUS: | |
949 | case OP_NOTPOSSTAR: | |
950 | case OP_NOTPOSPLUS: | |
951 | ||
952 | case OP_NOTSTARI: | |
953 | case OP_NOTMINSTARI: | |
954 | case OP_NOTPLUSI: | |
955 | case OP_NOTMINPLUSI: | |
956 | case OP_NOTPOSSTARI: | |
957 | case OP_NOTPOSPLUSI: | |
958 | return TRUE; | |
959 | ||
960 | case OP_CLASS: | |
961 | case OP_NCLASS: | |
962 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | |
963 | case OP_XCLASS: | |
964 | cc += (*cc == OP_XCLASS) ? GET(cc, 1) : (int)(1 + (32 / sizeof(pcre_uchar))); | |
965 | #else | |
966 | cc += (1 + (32 / sizeof(pcre_uchar))); | |
967 | #endif | |
968 | ||
969 | switch(*cc) | |
970 | { | |
971 | case OP_CRSTAR: | |
972 | case OP_CRMINSTAR: | |
973 | case OP_CRPLUS: | |
974 | case OP_CRMINPLUS: | |
975 | case OP_CRPOSSTAR: | |
976 | case OP_CRPOSPLUS: | |
977 | return TRUE; | |
978 | } | |
979 | break; | |
980 | } | |
981 | return FALSE; | |
982 | } | |
983 | ||
984 | static SLJIT_INLINE BOOL detect_fast_forward_skip(compiler_common *common, int *private_data_start) | |
985 | { | |
986 | pcre_uchar *cc = common->start; | |
987 | pcre_uchar *end; | |
988 | ||
989 | /* Skip not repeated brackets. */ | |
990 | while (TRUE) | |
991 | { | |
992 | switch(*cc) | |
993 | { | |
994 | case OP_SOD: | |
995 | case OP_SOM: | |
996 | case OP_SET_SOM: | |
997 | case OP_NOT_WORD_BOUNDARY: | |
998 | case OP_WORD_BOUNDARY: | |
999 | case OP_EODN: | |
1000 | case OP_EOD: | |
1001 | case OP_CIRC: | |
1002 | case OP_CIRCM: | |
1003 | case OP_DOLL: | |
1004 | case OP_DOLLM: | |
1005 | /* Zero width assertions. */ | |
1006 | cc++; | |
1007 | continue; | |
1008 | } | |
1009 | ||
1010 | if (*cc != OP_BRA && *cc != OP_CBRA) | |
1011 | break; | |
1012 | ||
1013 | end = cc + GET(cc, 1); | |
1014 | if (*end != OP_KET || PRIVATE_DATA(end) != 0) | |
1015 | return FALSE; | |
1016 | if (*cc == OP_CBRA) | |
1017 | { | |
1018 | if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) | |
1019 | return FALSE; | |
1020 | cc += IMM2_SIZE; | |
1021 | } | |
1022 | cc += 1 + LINK_SIZE; | |
1023 | } | |
1024 | ||
1025 | if (is_accelerated_repeat(cc)) | |
1026 | { | |
1027 | common->fast_forward_bc_ptr = cc; | |
1028 | common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start; | |
1029 | *private_data_start += sizeof(sljit_sw); | |
1030 | return TRUE; | |
1031 | } | |
1032 | return FALSE; | |
1033 | } | |
1034 | ||
1035 | static SLJIT_INLINE void detect_fast_fail(compiler_common *common, pcre_uchar *cc, int *private_data_start, sljit_s32 depth) | |
1036 | { | |
1037 | pcre_uchar *next_alt; | |
1038 | ||
1039 | SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA); | |
1040 | ||
1041 | if (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) | |
1042 | return; | |
1043 | ||
1044 | next_alt = bracketend(cc) - (1 + LINK_SIZE); | |
1045 | if (*next_alt != OP_KET || PRIVATE_DATA(next_alt) != 0) | |
1046 | return; | |
1047 | ||
1048 | do | |
1049 | { | |
1050 | next_alt = cc + GET(cc, 1); | |
1051 | ||
1052 | cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0); | |
1053 | ||
1054 | while (TRUE) | |
1055 | { | |
1056 | switch(*cc) | |
1057 | { | |
1058 | case OP_SOD: | |
1059 | case OP_SOM: | |
1060 | case OP_SET_SOM: | |
1061 | case OP_NOT_WORD_BOUNDARY: | |
1062 | case OP_WORD_BOUNDARY: | |
1063 | case OP_EODN: | |
1064 | case OP_EOD: | |
1065 | case OP_CIRC: | |
1066 | case OP_CIRCM: | |
1067 | case OP_DOLL: | |
1068 | case OP_DOLLM: | |
1069 | /* Zero width assertions. */ | |
1070 | cc++; | |
1071 | continue; | |
1072 | } | |
1073 | break; | |
1074 | } | |
1075 | ||
1076 | if (depth > 0 && (*cc == OP_BRA || *cc == OP_CBRA)) | |
1077 | detect_fast_fail(common, cc, private_data_start, depth - 1); | |
1078 | ||
1079 | if (is_accelerated_repeat(cc)) | |
1080 | { | |
1081 | common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start; | |
1082 | ||
1083 | if (common->fast_fail_start_ptr == 0) | |
1084 | common->fast_fail_start_ptr = *private_data_start; | |
1085 | ||
1086 | *private_data_start += sizeof(sljit_sw); | |
1087 | common->fast_fail_end_ptr = *private_data_start; | |
1088 | ||
1089 | if (*private_data_start > SLJIT_MAX_LOCAL_SIZE) | |
1090 | return; | |
1091 | } | |
1092 | ||
1093 | cc = next_alt; | |
1094 | } | |
1095 | while (*cc == OP_ALT); | |
1096 | } | |
1097 | ||
1098 | static int get_class_iterator_size(pcre_uchar *cc) | static int get_class_iterator_size(pcre_uchar *cc) |
1099 | { | { |
1100 | sljit_u32 min; | |
1101 | sljit_u32 max; | |
1102 | switch(*cc) | switch(*cc) |
1103 | { | { |
1104 | case OP_CRSTAR: | case OP_CRSTAR: |
# | Line 876 switch(*cc) | Line 1113 switch(*cc) |
1113 | ||
1114 | case OP_CRRANGE: | case OP_CRRANGE: |
1115 | case OP_CRMINRANGE: | case OP_CRMINRANGE: |
1116 | if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE)) | min = GET2(cc, 1); |
1117 | return 0; | max = GET2(cc, 1 + IMM2_SIZE); |
1118 | return 2; | if (max == 0) |
1119 | return (*cc == OP_CRRANGE) ? 2 : 1; | |
1120 | max -= min; | |
1121 | if (max > 2) | |
1122 | max = 2; | |
1123 | return max; | |
1124 | ||
1125 | default: | default: |
1126 | return 0; | return 0; |
# | Line 892 pcre_uchar *next; | Line 1134 pcre_uchar *next; |
1134 | pcre_uchar *next_end; | pcre_uchar *next_end; |
1135 | pcre_uchar *max_end; | pcre_uchar *max_end; |
1136 | pcre_uchar type; | pcre_uchar type; |
1137 | sljit_uw length = end - begin; | sljit_sw length = end - begin; |
1138 | int min, max, i; | int min, max, i; |
1139 | ||
1140 | /* Detect fixed iterations first. */ | /* Detect fixed iterations first. */ |
# | Line 1029 pcre_uchar *alternative; | Line 1271 pcre_uchar *alternative; |
1271 | pcre_uchar *end = NULL; | pcre_uchar *end = NULL; |
1272 | int private_data_ptr = *private_data_start; | int private_data_ptr = *private_data_start; |
1273 | int space, size, bracketlen; | int space, size, bracketlen; |
1274 | BOOL repeat_check = TRUE; | |
1275 | ||
1276 | while (cc < ccend) | while (cc < ccend) |
1277 | { | { |
# | Line 1036 while (cc < ccend) | Line 1279 while (cc < ccend) |
1279 | size = 0; | size = 0; |
1280 | bracketlen = 0; | bracketlen = 0; |
1281 | if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE) | if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE) |
1282 | return; | break; |
1283 | ||
1284 | if (*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_ONCE || *cc == OP_ONCE_NC) | if (repeat_check && (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)) |
1285 | { | |
1286 | if (detect_repeat(common, cc)) | if (detect_repeat(common, cc)) |
1287 | { | { |
1288 | /* These brackets are converted to repeats, so no global | /* These brackets are converted to repeats, so no global |
# | Line 1046 while (cc < ccend) | Line 1290 while (cc < ccend) |
1290 | if (cc >= end) | if (cc >= end) |
1291 | end = bracketend(cc); | end = bracketend(cc); |
1292 | } | } |
1293 | } | |
1294 | repeat_check = TRUE; | |
1295 | ||
1296 | switch(*cc) | switch(*cc) |
1297 | { | { |
# | Line 1101 while (cc < ccend) | Line 1347 while (cc < ccend) |
1347 | bracketlen = 1 + LINK_SIZE + IMM2_SIZE; | bracketlen = 1 + LINK_SIZE + IMM2_SIZE; |
1348 | break; | break; |
1349 | ||
1350 | case OP_BRAZERO: | |
1351 | case OP_BRAMINZERO: | |
1352 | case OP_BRAPOSZERO: | |
1353 | repeat_check = FALSE; | |
1354 | size = 1; | |
1355 | break; | |
1356 | ||
1357 | CASE_ITERATOR_PRIVATE_DATA_1 | CASE_ITERATOR_PRIVATE_DATA_1 |
1358 | space = 1; | space = 1; |
1359 | size = -2; | size = -2; |
# | Line 1127 while (cc < ccend) | Line 1380 while (cc < ccend) |
1380 | size = 1; | size = 1; |
1381 | break; | break; |
1382 | ||
1383 | CASE_ITERATOR_TYPE_PRIVATE_DATA_2B | case OP_TYPEUPTO: |
1384 | if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) | if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) |
1385 | space = 2; | space = 2; |
1386 | size = 1 + IMM2_SIZE; | size = 1 + IMM2_SIZE; |
1387 | break; | break; |
1388 | ||
1389 | case OP_TYPEMINUPTO: | |
1390 | space = 2; | |
1391 | size = 1 + IMM2_SIZE; | |
1392 | break; | |
1393 | ||
1394 | case OP_CLASS: | case OP_CLASS: |
1395 | case OP_NCLASS: | case OP_NCLASS: |
1396 | size += 1 + 32 / sizeof(pcre_uchar); | size += 1 + 32 / sizeof(pcre_uchar); |
# | Line 1188 while (cc < ccend) | Line 1446 while (cc < ccend) |
1446 | } | } |
1447 | ||
1448 | /* Returns with a frame_types (always < 0) if no need for frame. */ | /* Returns with a frame_types (always < 0) if no need for frame. */ |
1449 | static int get_framesize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL recursive, BOOL* needs_control_head) | static int get_framesize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL recursive, BOOL *needs_control_head) |
1450 | { | { |
1451 | int length = 0; | int length = 0; |
1452 | int possessive = 0; | int possessive = 0; |
# | Line 1281 while (cc < ccend) | Line 1539 while (cc < ccend) |
1539 | cc += 1 + LINK_SIZE + IMM2_SIZE; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
1540 | break; | break; |
1541 | ||
1542 | case OP_THEN: | |
1543 | stack_restore = TRUE; | |
1544 | if (common->control_head_ptr != 0) | |
1545 | *needs_control_head = TRUE; | |
1546 | cc ++; | |
1547 | break; | |
1548 | ||
1549 | default: | default: |
1550 | stack_restore = TRUE; | stack_restore = TRUE; |
1551 | /* Fall through. */ | /* Fall through. */ |
# | Line 1348 while (cc < ccend) | Line 1613 while (cc < ccend) |
1613 | case OP_CLASS: | case OP_CLASS: |
1614 | case OP_NCLASS: | case OP_NCLASS: |
1615 | case OP_XCLASS: | case OP_XCLASS: |
1616 | case OP_CALLOUT: | |
1617 | ||
1618 | cc = next_opcode(common, cc); | cc = next_opcode(common, cc); |
1619 | SLJIT_ASSERT(cc != NULL); | SLJIT_ASSERT(cc != NULL); |
# | Line 1392 while (cc < ccend) | Line 1658 while (cc < ccend) |
1658 | SLJIT_ASSERT(common->has_set_som); | SLJIT_ASSERT(common->has_set_som); |
1659 | if (!setsom_found) | if (!setsom_found) |
1660 | { | { |
1661 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); |
1662 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); |
1663 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1664 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
# | Line 1408 while (cc < ccend) | Line 1674 while (cc < ccend) |
1674 | SLJIT_ASSERT(common->mark_ptr != 0); | SLJIT_ASSERT(common->mark_ptr != 0); |
1675 | if (!setmark_found) | if (!setmark_found) |
1676 | { | { |
1677 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); |
1678 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); |
1679 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1680 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
# | Line 1421 while (cc < ccend) | Line 1687 while (cc < ccend) |
1687 | case OP_RECURSE: | case OP_RECURSE: |
1688 | if (common->has_set_som && !setsom_found) | if (common->has_set_som && !setsom_found) |
1689 | { | { |
1690 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); |
1691 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); |
1692 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1693 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
# | Line 1430 while (cc < ccend) | Line 1696 while (cc < ccend) |
1696 | } | } |
1697 | if (common->mark_ptr != 0 && !setmark_found) | if (common->mark_ptr != 0 && !setmark_found) |
1698 | { | { |
1699 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); |
1700 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); |
1701 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1702 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
# | Line 1439 while (cc < ccend) | Line 1705 while (cc < ccend) |
1705 | } | } |
1706 | if (common->capture_last_ptr != 0 && !capture_last_found) | if (common->capture_last_ptr != 0 && !capture_last_found) |
1707 | { | { |
1708 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); |
1709 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); |
1710 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1711 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
# | Line 1455 while (cc < ccend) | Line 1721 while (cc < ccend) |
1721 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
1722 | if (common->capture_last_ptr != 0 && !capture_last_found) | if (common->capture_last_ptr != 0 && !capture_last_found) |
1723 | { | { |
1724 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); |
1725 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); |
1726 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1727 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
# | Line 1465 while (cc < ccend) | Line 1731 while (cc < ccend) |
1731 | offset = (GET2(cc, 1 + LINK_SIZE)) << 1; | offset = (GET2(cc, 1 + LINK_SIZE)) << 1; |
1732 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset)); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset)); |
1733 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1734 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); |
1735 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); |
1736 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
1737 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1738 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0); |
# | Line 1496 while (cc < ccend) | Line 1762 while (cc < ccend) |
1762 | size = 0; | size = 0; |
1763 | switch(*cc) | switch(*cc) |
1764 | { | { |
1765 | case OP_KET: | |
1766 | if (PRIVATE_DATA(cc) != 0) | |
1767 | { | |
1768 | private_data_length++; | |
1769 | SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); | |
1770 | cc += PRIVATE_DATA(cc + 1); | |
1771 | } | |
1772 | cc += 1 + LINK_SIZE; | |
1773 | break; | |
1774 | ||
1775 | case OP_ASSERT: | case OP_ASSERT: |
1776 | case OP_ASSERT_NOT: | case OP_ASSERT_NOT: |
1777 | case OP_ASSERTBACK: | case OP_ASSERTBACK: |
# | Line 1507 while (cc < ccend) | Line 1783 while (cc < ccend) |
1783 | case OP_SBRAPOS: | case OP_SBRAPOS: |
1784 | case OP_SCOND: | case OP_SCOND: |
1785 | private_data_length++; | private_data_length++; |
1786 | SLJIT_ASSERT(PRIVATE_DATA(cc) != 0); | |
1787 | cc += 1 + LINK_SIZE; | cc += 1 + LINK_SIZE; |
1788 | break; | break; |
1789 | ||
# | Line 1664 do | Line 1941 do |
1941 | ||
1942 | switch(*cc) | switch(*cc) |
1943 | { | { |
1944 | case OP_KET: | |
1945 | if (PRIVATE_DATA(cc) != 0) | |
1946 | { | |
1947 | count = 1; | |
1948 | srcw[0] = PRIVATE_DATA(cc); | |
1949 | SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); | |
1950 | cc += PRIVATE_DATA(cc + 1); | |
1951 | } | |
1952 | cc += 1 + LINK_SIZE; | |
1953 | break; | |
1954 | ||
1955 | case OP_ASSERT: | case OP_ASSERT: |
1956 | case OP_ASSERT_NOT: | case OP_ASSERT_NOT: |
1957 | case OP_ASSERTBACK: | case OP_ASSERTBACK: |
# | Line 1831 do | Line 2119 do |
2119 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); |
2120 | stackptr += sizeof(sljit_sw); | stackptr += sizeof(sljit_sw); |
2121 | } | } |
2122 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), srcw[count]); |
2123 | tmp1empty = FALSE; | tmp1empty = FALSE; |
2124 | tmp1next = FALSE; | tmp1next = FALSE; |
2125 | } | } |
# | Line 1842 do | Line 2130 do |
2130 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); |
2131 | stackptr += sizeof(sljit_sw); | stackptr += sizeof(sljit_sw); |
2132 | } | } |
2133 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), srcw[count]); |
2134 | tmp2empty = FALSE; | tmp2empty = FALSE; |
2135 | tmp1next = TRUE; | tmp1next = TRUE; |
2136 | } | } |
# | Line 1852 do | Line 2140 do |
2140 | if (tmp1next) | if (tmp1next) |
2141 | { | { |
2142 | SLJIT_ASSERT(!tmp1empty); | SLJIT_ASSERT(!tmp1empty); |
2143 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), srcw[count], TMP1, 0); |
2144 | tmp1empty = stackptr >= stacktop; | tmp1empty = stackptr >= stacktop; |
2145 | if (!tmp1empty) | if (!tmp1empty) |
2146 | { | { |
# | Line 1864 do | Line 2152 do |
2152 | else | else |
2153 | { | { |
2154 | SLJIT_ASSERT(!tmp2empty); | SLJIT_ASSERT(!tmp2empty); |
2155 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), srcw[count], TMP2, 0); |
2156 | tmp2empty = stackptr >= stacktop; | tmp2empty = stackptr >= stacktop; |
2157 | if (!tmp2empty) | if (!tmp2empty) |
2158 | { | { |
# | Line 1966 while (list) | Line 2254 while (list) |
2254 | } | } |
2255 | } | } |
2256 | ||
2257 | static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump) | static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump *jump) |
2258 | { | { |
2259 | jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list)); | jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list)); |
2260 | if (list_item) | if (list_item) |
# | Line 1980 if (list_item) | Line 2268 if (list_item) |
2268 | static void add_stub(compiler_common *common, struct sljit_jump *start) | static void add_stub(compiler_common *common, struct sljit_jump *start) |
2269 | { | { |
2270 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2271 | stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list)); | stub_list *list_item = sljit_alloc_memory(compiler, sizeof(stub_list)); |
2272 | ||
2273 | if (list_item) | if (list_item) |
2274 | { | { |
# | Line 1994 if (list_item) | Line 2282 if (list_item) |
2282 | static void flush_stubs(compiler_common *common) | static void flush_stubs(compiler_common *common) |
2283 | { | { |
2284 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2285 | stub_list* list_item = common->stubs; | stub_list *list_item = common->stubs; |
2286 | ||
2287 | while (list_item) | while (list_item) |
2288 | { | { |
# | Line 2006 while (list_item) | Line 2294 while (list_item) |
2294 | common->stubs = NULL; | common->stubs = NULL; |
2295 | } | } |
2296 | ||
2297 | static SLJIT_INLINE void decrease_call_count(compiler_common *common) | static void add_label_addr(compiler_common *common, sljit_uw *update_addr) |
2298 | { | |
2299 | DEFINE_COMPILER; | |
2300 | label_addr_list *label_addr; | |
2301 | ||
2302 | label_addr = sljit_alloc_memory(compiler, sizeof(label_addr_list)); | |
2303 | if (label_addr == NULL) | |
2304 | return; | |
2305 | label_addr->label = LABEL(); | |
2306 | label_addr->update_addr = update_addr; | |
2307 | label_addr->next = common->label_addrs; | |
2308 | common->label_addrs = label_addr; | |
2309 | } | |
2310 | ||
2311 | static SLJIT_INLINE void count_match(compiler_common *common) | |
2312 | { | { |
2313 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2314 | ||
2315 | OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1); |
2316 | add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO)); | add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO)); |
2317 | } | } |
2318 | ||
2319 | static SLJIT_INLINE void allocate_stack(compiler_common *common, int size) | static SLJIT_INLINE void allocate_stack(compiler_common *common, int size) |
# | Line 2019 static SLJIT_INLINE void allocate_stack( | Line 2321 static SLJIT_INLINE void allocate_stack( |
2321 | /* May destroy all locals and registers except TMP2. */ | /* May destroy all locals and registers except TMP2. */ |
2322 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2323 | ||
2324 | SLJIT_ASSERT(size > 0); | |
2325 | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); |
2326 | #ifdef DESTROY_REGISTERS | #ifdef DESTROY_REGISTERS |
2327 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345); |
2328 | OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); | OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); |
2329 | OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); | OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); |
2330 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP1, 0); |
2331 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0); |
2332 | #endif | #endif |
2333 | add_stub(common, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0)); | add_stub(common, CMP(SLJIT_GREATER, STACK_TOP, 0, STACK_LIMIT, 0)); |
2334 | } | } |
2335 | ||
2336 | static SLJIT_INLINE void free_stack(compiler_common *common, int size) | static SLJIT_INLINE void free_stack(compiler_common *common, int size) |
2337 | { | { |
2338 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2339 | ||
2340 | SLJIT_ASSERT(size > 0); | |
2341 | OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); | OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); |
2342 | } | } |
2343 | ||
2344 | static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size) | |
2345 | { | |
2346 | DEFINE_COMPILER; | |
2347 | sljit_uw *result; | |
2348 | ||
2349 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | |
2350 | return NULL; | |
2351 | ||
2352 | result = (sljit_uw *)SLJIT_MALLOC(size + sizeof(sljit_uw), compiler->allocator_data); | |
2353 | if (SLJIT_UNLIKELY(result == NULL)) | |
2354 | { | |
2355 | sljit_set_compiler_memory_error(compiler); | |
2356 | return NULL; | |
2357 | } | |
2358 | ||
2359 | *(void**)result = common->read_only_data_head; | |
2360 | common->read_only_data_head = (void *)result; | |
2361 | return result + 1; | |
2362 | } | |
2363 | ||
2364 | static void free_read_only_data(void *current, void *allocator_data) | |
2365 | { | |
2366 | void *next; | |
2367 | ||
2368 | SLJIT_UNUSED_ARG(allocator_data); | |
2369 | ||
2370 | while (current != NULL) | |
2371 | { | |
2372 | next = *(void**)current; | |
2373 | SLJIT_FREE(current, allocator_data); | |
2374 | current = next; | |
2375 | } | |
2376 | } | |
2377 | ||
2378 | static SLJIT_INLINE void reset_ovector(compiler_common *common, int length) | static SLJIT_INLINE void reset_ovector(compiler_common *common, int length) |
2379 | { | { |
2380 | DEFINE_COMPILER; | DEFINE_COMPILER; |
# | Line 2045 int i; | Line 2384 int i; |
2384 | /* At this point we can freely use all temporary registers. */ | /* At this point we can freely use all temporary registers. */ |
2385 | SLJIT_ASSERT(length > 1); | SLJIT_ASSERT(length > 1); |
2386 | /* TMP1 returns with begin - 1. */ | /* TMP1 returns with begin - 1. */ |
2387 | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); |
2388 | if (length < 8) | if (length < 8) |
2389 | { | { |
2390 | for (i = 1; i < length; i++) | for (i = 1; i < length; i++) |
2391 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_SCRATCH_REG1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), SLJIT_R0, 0); |
2392 | } | } |
2393 | else | else |
2394 | { | { |
2395 | GET_LOCAL_BASE(SLJIT_SCRATCH_REG2, 0, OVECTOR_START); | GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START); |
2396 | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, length - 1); | OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1); |
2397 | loop = LABEL(); | loop = LABEL(); |
2398 | OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_SCRATCH_REG2), sizeof(sljit_sw), SLJIT_SCRATCH_REG1, 0); | OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0); |
2399 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); |
2400 | JUMPTO(SLJIT_C_NOT_ZERO, loop); | JUMPTO(SLJIT_NOT_ZERO, loop); |
2401 | } | } |
2402 | } | } |
2403 | ||
2404 | static SLJIT_INLINE void reset_fast_fail(compiler_common *common) | |
2405 | { | |
2406 | DEFINE_COMPILER; | |
2407 | sljit_s32 i; | |
2408 | ||
2409 | SLJIT_ASSERT(common->fast_fail_start_ptr < common->fast_fail_end_ptr); | |
2410 | ||
2411 | OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
2412 | for (i = common->fast_fail_start_ptr; i < common->fast_fail_end_ptr; i += sizeof(sljit_sw)) | |
2413 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), i, TMP1, 0); | |
2414 | } | |
2415 | ||
2416 | static SLJIT_INLINE void do_reset_match(compiler_common *common, int length) | static SLJIT_INLINE void do_reset_match(compiler_common *common, int length) |
2417 | { | { |
2418 | DEFINE_COMPILER; | DEFINE_COMPILER; |
# | Line 2071 int i; | Line 2422 int i; |
2422 | SLJIT_ASSERT(length > 1); | SLJIT_ASSERT(length > 1); |
2423 | /* OVECTOR(1) contains the "string begin - 1" constant. */ | /* OVECTOR(1) contains the "string begin - 1" constant. */ |
2424 | if (length > 2) | if (length > 2) |
2425 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); |
2426 | if (length < 8) | if (length < 8) |
2427 | { | { |
2428 | for (i = 2; i < length; i++) | for (i = 2; i < length; i++) |
2429 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), TMP1, 0); |
2430 | } | } |
2431 | else | else |
2432 | { | { |
# | Line 2084 else | Line 2435 else |
2435 | loop = LABEL(); | loop = LABEL(); |
2436 | OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); | OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); |
2437 | OP2(SLJIT_SUB | SLJIT_SET_E, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); |
2438 | JUMPTO(SLJIT_C_NOT_ZERO, loop); | JUMPTO(SLJIT_NOT_ZERO, loop); |
2439 | } | } |
2440 | ||
2441 | OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); |
2442 | if (common->mark_ptr != 0) | if (common->mark_ptr != 0) |
2443 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0); |
2444 | if (common->control_head_ptr != 0) | if (common->control_head_ptr != 0) |
2445 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); |
2446 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); |
2447 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr); |
2448 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); |
2449 | } | } |
2450 | ||
# | Line 2115 while (current != NULL) | Line 2466 while (current != NULL) |
2466 | SLJIT_ASSERT_STOP(); | SLJIT_ASSERT_STOP(); |
2467 | break; | break; |
2468 | } | } |
2469 | SLJIT_ASSERT(current > (sljit_sw*)current[-1]); | |
2470 | current = (sljit_sw*)current[-1]; | current = (sljit_sw*)current[-1]; |
2471 | } | } |
2472 | return -1; | return -1; |
# | Line 2127 struct sljit_label *loop; | Line 2479 struct sljit_label *loop; |
2479 | struct sljit_jump *early_quit; | struct sljit_jump *early_quit; |
2480 | ||
2481 | /* At this point we can freely use all registers. */ | /* At this point we can freely use all registers. */ |
2482 | OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); | OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); |
2483 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0); |
2484 | ||
2485 | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0); |
2486 | if (common->mark_ptr != 0) | if (common->mark_ptr != 0) |
2487 | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); |
2488 | OP1(SLJIT_MOV_SI, SLJIT_SCRATCH_REG2, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, offset_count)); | OP1(SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offset_count)); |
2489 | if (common->mark_ptr != 0) | if (common->mark_ptr != 0) |
2490 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_SCRATCH_REG3, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0); |
2491 | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); | OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); |
2492 | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin)); |
2493 | GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START); | GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START); |
2494 | /* Unlikely, but possible */ | /* Unlikely, but possible */ |
2495 | early_quit = CMP(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 0); | early_quit = CMP(SLJIT_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0); |
2496 | loop = LABEL(); | loop = LABEL(); |
2497 | OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_SCRATCH_REG1, 0); | OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); |
2498 | OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_sw)); | OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw)); |
2499 | /* Copy the integer value to the output buffer */ | /* Copy the integer value to the output buffer */ |
2500 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
2501 | OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT); |
2502 | #endif | #endif |
2503 | OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG3), sizeof(int), SLJIT_SAVED_REG2, 0); | OP1(SLJIT_MOVU_S32, SLJIT_MEM1(SLJIT_R2), sizeof(int), SLJIT_S1, 0); |
2504 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); |
2505 | JUMPTO(SLJIT_C_NOT_ZERO, loop); | JUMPTO(SLJIT_NOT_ZERO, loop); |
2506 | JUMPHERE(early_quit); | JUMPHERE(early_quit); |
2507 | ||
2508 | /* Calculate the return value, which is the maximum ovector value. */ | /* Calculate the return value, which is the maximum ovector value. */ |
2509 | if (topbracket > 1) | if (topbracket > 1) |
2510 | { | { |
2511 | GET_LOCAL_BASE(SLJIT_SCRATCH_REG1, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); | GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); |
2512 | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, topbracket + 1); | OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1); |
2513 | ||
2514 | /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ | /* OVECTOR(0) is never equal to SLJIT_S2. */ |
2515 | loop = LABEL(); | loop = LABEL(); |
2516 | OP1(SLJIT_MOVU, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), -(2 * (sljit_sw)sizeof(sljit_sw))); | OP1(SLJIT_MOVU, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))); |
2517 | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); |
2518 | CMPTO(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG3, 0, SLJIT_SAVED_REG3, 0, loop); | CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop); |
2519 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_SCRATCH_REG2, 0); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0); |
2520 | } | } |
2521 | else | else |
2522 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); |
# | Line 2175 static SLJIT_INLINE void return_with_par | Line 2527 static SLJIT_INLINE void return_with_par |
2527 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2528 | struct sljit_jump *jump; | struct sljit_jump *jump; |
2529 | ||
2530 | SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2); | SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S1, str_end_must_be_saved_reg2); |
2531 | SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0 | SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0 |
2532 | && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0)); | && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0)); |
2533 | ||
2534 | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0); |
2535 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); |
2536 | OP1(SLJIT_MOV_SI, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, real_offset_count)); | OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, real_offset_count)); |
2537 | CMPTO(SLJIT_C_SIG_LESS, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 2, quit); | CMPTO(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 2, quit); |
2538 | ||
2539 | /* Store match begin and end. */ | /* Store match begin and end. */ |
2540 | OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin)); |
2541 | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, offsets)); | OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, offsets)); |
2542 | ||
2543 | jump = CMP(SLJIT_C_SIG_LESS, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 3); | jump = CMP(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 3); |
2544 | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_ptr : (common->hit_start + (int)sizeof(sljit_sw)), SLJIT_SAVED_REG1, 0); | OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_ptr : (common->hit_start + (int)sizeof(sljit_sw)), SLJIT_S0, 0); |
2545 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
2546 | OP2(SLJIT_ASHR, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT); |
2547 | #endif | #endif |
2548 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), 2 * sizeof(int), SLJIT_SCRATCH_REG3, 0); | OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(int), SLJIT_R2, 0); |
2549 | JUMPHERE(jump); | JUMPHERE(jump); |
2550 | ||
2551 | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start); | OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start); |
2552 | OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0); | OP2(SLJIT_SUB, SLJIT_S1, 0, STR_END, 0, SLJIT_S0, 0); |
2553 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
2554 | OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT); |
2555 | #endif | #endif |
2556 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), sizeof(int), SLJIT_SAVED_REG2, 0); | OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), sizeof(int), SLJIT_S1, 0); |
2557 | ||
2558 | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_SAVED_REG1, 0); | OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S0, 0); |
2559 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
2560 | OP2(SLJIT_ASHR, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT); |
2561 | #endif | #endif |
2562 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), 0, SLJIT_SCRATCH_REG3, 0); | OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0); |
2563 | ||
2564 | JUMPTO(SLJIT_JUMP, quit); | JUMPTO(SLJIT_JUMP, quit); |
2565 | } | } |
# | Line 2221 struct sljit_jump *jump; | Line 2573 struct sljit_jump *jump; |
2573 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2574 | { | { |
2575 | /* The value of -1 must be kept for start_used_ptr! */ | /* The value of -1 must be kept for start_used_ptr! */ |
2576 | OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, 1); | OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, 1); |
2577 | /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting | /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting |
2578 | is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */ | is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */ |
2579 | jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_PTR, 0); | jump = CMP(SLJIT_LESS_EQUAL, TMP1, 0, STR_PTR, 0); |
2580 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); |
2581 | JUMPHERE(jump); | JUMPHERE(jump); |
2582 | } | } |
2583 | else if (common->mode == JIT_PARTIAL_HARD_COMPILE) | else if (common->mode == JIT_PARTIAL_HARD_COMPILE) |
2584 | { | { |
2585 | jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | jump = CMP(SLJIT_LESS_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); |
2586 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); |
2587 | JUMPHERE(jump); | JUMPHERE(jump); |
2588 | } | } |
2589 | } | } |
2590 | ||
2591 | 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) |
2592 | { | { |
2593 | /* Detects if the character has an othercase. */ | /* Detects if the character has an othercase. */ |
2594 | unsigned int c; | unsigned int c; |
# | Line 2279 if (common->utf && c > 127) | Line 2631 if (common->utf && c > 127) |
2631 | return TABLE_GET(c, common->fcc, c); | return TABLE_GET(c, common->fcc, c); |
2632 | } | } |
2633 | ||
2634 | static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar* cc) | static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar *cc) |
2635 | { | { |
2636 | /* Detects if the character and its othercase has only 1 bit difference. */ | /* Detects if the character and its othercase has only 1 bit difference. */ |
2637 | unsigned int c, oc, bit; | unsigned int c, oc, bit; |
# | Line 2357 return (bit < 256) ? ((0 << 8) | bit) : | Line 2709 return (bit < 256) ? ((0 << 8) | bit) : |
2709 | ||
2710 | static void check_partial(compiler_common *common, BOOL force) | static void check_partial(compiler_common *common, BOOL force) |
2711 | { | { |
2712 | /* Checks whether a partial matching is occured. Does not modify registers. */ | /* Checks whether a partial matching is occurred. Does not modify registers. */ |
2713 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2714 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
2715 | ||
# | Line 2367 if (common->mode == JIT_COMPILE) | Line 2719 if (common->mode == JIT_COMPILE) |
2719 | return; | return; |
2720 | ||
2721 | if (!force) | if (!force) |
2722 | jump = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); |
2723 | else if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | else if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2724 | jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); | jump = CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1); |
2725 | ||
2726 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2727 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); |
2728 | else | else |
2729 | { | { |
2730 | if (common->partialmatchlabel != NULL) | if (common->partialmatchlabel != NULL) |
# | Line 2393 struct sljit_jump *jump; | Line 2745 struct sljit_jump *jump; |
2745 | ||
2746 | if (common->mode == JIT_COMPILE) | if (common->mode == JIT_COMPILE) |
2747 | { | { |
2748 | add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
2749 | return; | return; |
2750 | } | } |
2751 | ||
2752 | jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); |
2753 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2754 | { | { |
2755 | add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); | add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0)); |
2756 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); |
2757 | add_jump(compiler, end_reached, JUMP(SLJIT_JUMP)); | add_jump(compiler, end_reached, JUMP(SLJIT_JUMP)); |
2758 | } | } |
2759 | else | else |
2760 | { | { |
2761 | add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); | add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0)); |
2762 | if (common->partialmatchlabel != NULL) | if (common->partialmatchlabel != NULL) |
2763 | JUMPTO(SLJIT_JUMP, common->partialmatchlabel); | JUMPTO(SLJIT_JUMP, common->partialmatchlabel); |
2764 | else | else |
# | Line 2422 struct sljit_jump *jump; | Line 2774 struct sljit_jump *jump; |
2774 | ||
2775 | if (common->mode == JIT_COMPILE) | if (common->mode == JIT_COMPILE) |
2776 | { | { |
2777 | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
2778 | return; | return; |
2779 | } | } |
2780 | ||
2781 | /* Partial matching mode. */ | /* Partial matching mode. */ |
2782 | jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); |
2783 | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0)); |
2784 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2785 | { | { |
2786 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); |
2787 | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
2788 | } | } |
2789 | else | else |
# | Line 2444 else | Line 2796 else |
2796 | JUMPHERE(jump); | JUMPHERE(jump); |
2797 | } | } |
2798 | ||
2799 | static void read_char(compiler_common *common) | static void peek_char(compiler_common *common, sljit_u32 max) |
2800 | { | { |
2801 | /* Reads the character into TMP1, updates STR_PTR. | /* Reads the character into TMP1, keeps STR_PTR. |
2802 | Does not check STR_END. TMP2 Destroyed. */ | Does not check STR_END. TMP2 Destroyed. */ |
2803 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2804 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 |
2805 | struct sljit_jump *jump; | struct sljit_jump *jump; |
2806 | #endif | #endif |
2807 | ||
2808 | SLJIT_UNUSED_ARG(max); | |
2809 | ||
2810 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
2811 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 |
2812 | if (common->utf) | if (common->utf) |
2813 | { | { |
2814 | #if defined COMPILE_PCRE8 | if (max < 128) return; |
2815 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); | |
2816 | #elif defined COMPILE_PCRE16 | jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); |
2817 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
#endif /* COMPILE_PCRE[8|16] */ | ||
2818 | add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); |
2819 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | |
2820 | JUMPHERE(jump); | JUMPHERE(jump); |
2821 | } | } |
2822 | #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */ | #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */ |
2823 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
2824 | #if defined SUPPORT_UTF && defined COMPILE_PCRE16 | |
2825 | if (common->utf) | |
2826 | { | |
2827 | if (max < 0xd800) return; | |
2828 | ||
2829 | OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800); | |
2830 | jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); | |
2831 | /* TMP2 contains the high surrogate. */ | |
2832 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | |
2833 | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40); | |
2834 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10); | |
2835 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff); | |
2836 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
2837 | JUMPHERE(jump); | |
2838 | } | |
2839 | #endif | |
2840 | } | } |
2841 | ||
2842 | static void peek_char(compiler_common *common) | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 |
2843 | ||
2844 | static BOOL is_char7_bitset(const sljit_u8 *bitset, BOOL nclass) | |
2845 | { | { |
2846 | /* Reads the character into TMP1, keeps STR_PTR. | /* Tells whether the character codes below 128 are enough |
2847 | Does not check STR_END. TMP2 Destroyed. */ | to determine a match. */ |
2848 | const sljit_u8 value = nclass ? 0xff : 0; | |
2849 | const sljit_u8 *end = bitset + 32; | |
2850 | ||
2851 | bitset += 16; | |
2852 | do | |
2853 | { | |
2854 | if (*bitset++ != value) | |
2855 | return FALSE; | |
2856 | } | |
2857 | while (bitset < end); | |
2858 | return TRUE; | |
2859 | } | |
2860 | ||
2861 | static void read_char7_type(compiler_common *common, BOOL full_read) | |
2862 | { | |
2863 | /* Reads the precise character type of a character into TMP1, if the character | |
2864 | is less than 128. Otherwise it returns with zero. Does not check STR_END. The | |
2865 | full_read argument tells whether characters above max are accepted or not. */ | |
2866 | DEFINE_COMPILER; | |
2867 | struct sljit_jump *jump; | |
2868 | ||
2869 | SLJIT_ASSERT(common->utf); | |
2870 | ||
2871 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); | |
2872 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
2873 | ||
2874 | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); | |
2875 | ||
2876 | if (full_read) | |
2877 | { | |
2878 | jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0); | |
2879 | OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); | |
2880 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | |
2881 | JUMPHERE(jump); | |
2882 | } | |
2883 | } | |
2884 | ||
2885 | #endif /* SUPPORT_UTF && COMPILE_PCRE8 */ | |
2886 | ||
2887 | static void read_char_range(compiler_common *common, sljit_u32 min, sljit_u32 max, BOOL update_str_ptr) | |
2888 | { | |
2889 | /* Reads the precise value of a character into TMP1, if the character is | |
2890 | between min and max (c >= min && c <= max). Otherwise it returns with a value | |
2891 | outside the range. Does not check STR_END. */ | |
2892 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2893 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 |
2894 | struct sljit_jump *jump; | struct sljit_jump *jump; |
2895 | #endif | #endif |
2896 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | |
2897 | struct sljit_jump *jump2; | |
2898 | #endif | |
2899 | ||
2900 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | SLJIT_UNUSED_ARG(update_str_ptr); |
2901 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | SLJIT_UNUSED_ARG(min); |
2902 | SLJIT_UNUSED_ARG(max); | |
2903 | SLJIT_ASSERT(min <= max); | |
2904 | ||
2905 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | |
2906 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
2907 | ||
2908 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | |
2909 | if (common->utf) | if (common->utf) |
2910 | { | { |
2911 | #if defined COMPILE_PCRE8 | if (max < 128 && !update_str_ptr) return; |
2912 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); | |
2913 | #elif defined COMPILE_PCRE16 | jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); |
2914 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | if (min >= 0x10000) |
2915 | #endif /* COMPILE_PCRE[8|16] */ | { |
2916 | add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); | OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0); |
2917 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | if (update_str_ptr) |
2918 | OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); | |
2919 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | |
2920 | jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x7); | |
2921 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); | |
2922 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); | |
2923 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
2924 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | |
2925 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); | |
2926 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | |
2927 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
2928 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); | |
2929 | if (!update_str_ptr) | |
2930 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); | |
2931 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); | |
2932 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | |
2933 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
2934 | JUMPHERE(jump2); | |
2935 | if (update_str_ptr) | |
2936 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0); | |
2937 | } | |
2938 | else if (min >= 0x800 && max <= 0xffff) | |
2939 | { | |
2940 | OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xe0); | |
2941 | if (update_str_ptr) | |
2942 | OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); | |
2943 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | |
2944 | jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xf); | |
2945 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); | |
2946 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); | |
2947 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
2948 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | |
2949 | if (!update_str_ptr) | |
2950 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); | |
2951 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); | |
2952 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | |
2953 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
2954 | JUMPHERE(jump2); | |
2955 | if (update_str_ptr) | |
2956 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0); | |
2957 | } | |
2958 | else if (max >= 0x800) | |
2959 | add_jump(compiler, (max < 0x10000) ? &common->utfreadchar16 : &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); | |
2960 | else if (max < 128) | |
2961 | { | |
2962 | OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); | |
2963 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | |
2964 | } | |
2965 | else | |
2966 | { | |
2967 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | |
2968 | if (!update_str_ptr) | |
2969 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
2970 | else | |
2971 | OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); | |
2972 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); | |
2973 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); | |
2974 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | |
2975 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
2976 | if (update_str_ptr) | |
2977 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0); | |
2978 | } | |
2979 | JUMPHERE(jump); | JUMPHERE(jump); |
2980 | } | } |
2981 | #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */ | #endif |
2982 | ||
2983 | #if defined SUPPORT_UTF && defined COMPILE_PCRE16 | |
2984 | if (common->utf) | |
2985 | { | |
2986 | if (max >= 0x10000) | |
2987 | { | |
2988 | OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800); | |
2989 | jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); | |
2990 | /* TMP2 contains the high surrogate. */ | |
2991 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | |
2992 | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40); | |
2993 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10); | |
2994 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
2995 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff); | |
2996 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
2997 | JUMPHERE(jump); | |
2998 | return; | |
2999 | } | |
3000 | ||
3001 | if (max < 0xd800 && !update_str_ptr) return; | |
3002 | ||
3003 | /* Skip low surrogate if necessary. */ | |
3004 | OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800); | |
3005 | jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); | |
3006 | if (update_str_ptr) | |
3007 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
3008 | if (max >= 0xd800) | |
3009 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000); | |
3010 | JUMPHERE(jump); | |
3011 | } | |
3012 | #endif | |
3013 | } | |
3014 | ||
3015 | static SLJIT_INLINE void read_char(compiler_common *common) | |
3016 | { | |
3017 | read_char_range(common, 0, READ_CHAR_MAX, TRUE); | |
3018 | } | } |
3019 | ||
3020 | static void read_char8_type(compiler_common *common) | static void read_char8_type(compiler_common *common, BOOL update_str_ptr) |
3021 | { | { |
3022 | /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */ | /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */ |
3023 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3024 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
3025 | struct sljit_jump *jump; | struct sljit_jump *jump; |
3026 | #endif | #endif |
3027 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | |
3028 | struct sljit_jump *jump2; | |
3029 | #endif | |
3030 | ||
3031 | #ifdef SUPPORT_UTF | SLJIT_UNUSED_ARG(update_str_ptr); |
3032 | ||
3033 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); | |
3034 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
3035 | ||
3036 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | |
3037 | if (common->utf) | if (common->utf) |
3038 | { | { |
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | ||
#if defined COMPILE_PCRE8 | ||
3039 | /* This can be an extra read in some situations, but hopefully | /* This can be an extra read in some situations, but hopefully |
3040 | it is needed in most cases. */ | it is needed in most cases. */ |
3041 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); |
3042 | jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0); | jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0); |
3043 | add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL)); | if (!update_str_ptr) |
3044 | JUMPHERE(jump); | { |
3045 | #elif defined COMPILE_PCRE16 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
3046 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3047 | jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
3048 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); |
3049 | JUMPHERE(jump); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); |
3050 | /* Skip low surrogate if necessary. */ | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); |
3051 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); |
3052 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800); | jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255); |
3053 | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); |
3054 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); | JUMPHERE(jump2); |
3055 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | } |
3056 | #elif defined COMPILE_PCRE32 | else |
3057 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); | add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL)); |
jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); | ||
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); | ||
3058 | JUMPHERE(jump); | JUMPHERE(jump); |
#endif /* COMPILE_PCRE[8|16|32] */ | ||
3059 | return; | return; |
3060 | } | } |
3061 | #endif /* SUPPORT_UTF */ | #endif /* SUPPORT_UTF && COMPILE_PCRE8 */ |
3062 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); | |
3063 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | #if !defined COMPILE_PCRE8 |
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | ||
3064 | /* The ctypes array contains only 256 values. */ | /* The ctypes array contains only 256 values. */ |
3065 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); |
3066 | jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255); |
3067 | #endif | #endif |
3068 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); |
3069 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if !defined COMPILE_PCRE8 |
3070 | JUMPHERE(jump); | JUMPHERE(jump); |
3071 | #endif | #endif |
3072 | ||
3073 | #if defined SUPPORT_UTF && defined COMPILE_PCRE16 | |
3074 | if (common->utf && update_str_ptr) | |
3075 | { | |
3076 | /* Skip low surrogate if necessary. */ | |
3077 | OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800); | |
3078 | jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); | |
3079 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
3080 | JUMPHERE(jump); | |
3081 | } | |
3082 | #endif /* SUPPORT_UTF && COMPILE_PCRE16 */ | |
3083 | } | } |
3084 | ||
3085 | static void skip_char_back(compiler_common *common) | static void skip_char_back(compiler_common *common) |
# | Line 2561 if (common->utf) | Line 3096 if (common->utf) |
3096 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); |
3097 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3098 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); |
3099 | CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label); | CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label); |
3100 | return; | return; |
3101 | } | } |
3102 | #elif defined COMPILE_PCRE16 | #elif defined COMPILE_PCRE16 |
# | Line 2572 if (common->utf) | Line 3107 if (common->utf) |
3107 | /* Skip low surrogate if necessary. */ | /* Skip low surrogate if necessary. */ |
3108 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); |
3109 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); |
3110 | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); |
3111 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
3112 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
3113 | return; | return; |
# | Line 2582 if (common->utf) | Line 3117 if (common->utf) |
3117 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3118 | } | } |
3119 | ||
3120 | static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpiftrue) | static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpifmatch) |
3121 | { | { |
3122 | /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */ | /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */ |
3123 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3124 | struct sljit_jump *jump; | |
3125 | ||
3126 | if (nltype == NLTYPE_ANY) | if (nltype == NLTYPE_ANY) |
3127 | { | { |
3128 | add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); |
3129 | add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_NOT_ZERO : SLJIT_ZERO)); |
3130 | } | } |
3131 | else if (nltype == NLTYPE_ANYCRLF) | else if (nltype == NLTYPE_ANYCRLF) |
3132 | { | { |
3133 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR); | if (jumpifmatch) |
3134 | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); | { |
3135 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); | add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR)); |
3136 | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); | add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); |
3137 | add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); | } |
3138 | else | |
3139 | { | |
3140 | jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); | |
3141 | add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); | |
3142 | JUMPHERE(jump); | |
3143 | } | |
3144 | } | } |
3145 | else | else |
3146 | { | { |
3147 | SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); | SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); |
3148 | add_jump(compiler, backtracks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); | add_jump(compiler, backtracks, CMP(jumpifmatch ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); |
3149 | } | } |
3150 | } | } |
3151 | ||
# | Line 2613 else | Line 3155 else |
3155 | static void do_utfreadchar(compiler_common *common) | static void do_utfreadchar(compiler_common *common) |
3156 | { | { |
3157 | /* Fast decoding a UTF-8 character. TMP1 contains the first byte | /* Fast decoding a UTF-8 character. TMP1 contains the first byte |
3158 | of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */ | of the character (>= 0xc0). Return char value in TMP1, length in TMP2. */ |
3159 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3160 | struct sljit_jump *jump; | struct sljit_jump *jump; |
3161 | ||
3162 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
3163 | /* Searching for the first zero. */ | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
3164 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); |
jump = JUMP(SLJIT_C_NOT_ZERO); | ||
/* Two byte sequence. */ | ||
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | ||
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f); | ||
3165 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); |
3166 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
3167 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
3168 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); | |
3169 | /* Searching for the first zero. */ | |
3170 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); | |
3171 | jump = JUMP(SLJIT_NOT_ZERO); | |
3172 | /* Two byte sequence. */ | |
3173 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
3174 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2)); | |
3175 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
JUMPHERE(jump); | ||
3176 | ||
3177 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10); | JUMPHERE(jump); |
jump = JUMP(SLJIT_C_NOT_ZERO); | ||
/* Three byte sequence. */ | ||
3178 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
3179 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f); | OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x800); |
3180 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); |
3181 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); | ||
3182 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
3183 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); | |
3184 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000); | |
3185 | jump = JUMP(SLJIT_NOT_ZERO); | |
3186 | /* Three byte sequence. */ | |
3187 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
3188 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3)); |
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2)); | ||
3189 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
JUMPHERE(jump); | ||
3190 | ||
3191 | /* Four byte sequence. */ | /* Four byte sequence. */ |
3192 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | JUMPHERE(jump); |
3193 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); |
3194 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18); | OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000); |
3195 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); | |
3196 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); | |
3197 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12); | ||
3198 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
3199 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(4)); |
3200 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | |
3201 | } | |
3202 | ||
3203 | static void do_utfreadchar16(compiler_common *common) | |
3204 | { | |
3205 | /* Fast decoding a UTF-8 character. TMP1 contains the first byte | |
3206 | of the character (>= 0xc0). Return value in TMP1. */ | |
3207 | DEFINE_COMPILER; | |
3208 | struct sljit_jump *jump; | |
3209 | ||
3210 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); | |
3211 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | |
3212 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); | |
3213 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); | |
3214 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); | ||
3215 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
3216 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(3)); | |
3217 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); | /* Searching for the first zero. */ |
3218 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); | |
3219 | jump = JUMP(SLJIT_NOT_ZERO); | |
3220 | /* Two byte sequence. */ | |
3221 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
3222 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | |
3223 | ||
3224 | JUMPHERE(jump); | |
3225 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400); | |
3226 | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_NOT_ZERO); | |
3227 | /* This code runs only in 8 bit mode. No need to shift the value. */ | |
3228 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | |
3229 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | |
3230 | OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x800); | |
3231 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); | |
3232 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
3233 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
3234 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3)); | /* Three byte sequence. */ |
3235 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); | |
3236 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
3237 | } | } |
3238 | ||
# | Line 2679 struct sljit_jump *compare; | Line 3247 struct sljit_jump *compare; |
3247 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
3248 | ||
3249 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20); |
3250 | jump = JUMP(SLJIT_C_NOT_ZERO); | jump = JUMP(SLJIT_NOT_ZERO); |
3251 | /* Two byte sequence. */ | /* Two byte sequence. */ |
3252 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
3253 | 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)); |
3254 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f); |
3255 | /* The upper 5 bits are known at this point. */ | |
3256 | compare = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x3); | |
3257 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); |
3258 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); |
3259 | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); |
3260 | compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); |
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); | ||
3261 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
3262 | ||
3263 | JUMPHERE(compare); | JUMPHERE(compare); |
3264 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); |
3265 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
JUMPHERE(jump); | ||
3266 | ||
3267 | /* We only have types for characters less than 256. */ | /* We only have types for characters less than 256. */ |
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | ||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); | ||
sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | ||
} | ||
#elif defined COMPILE_PCRE16 | ||
static void do_utfreadchar(compiler_common *common) | ||
{ | ||
/* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char | ||
of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */ | ||
DEFINE_COMPILER; | ||
struct sljit_jump *jump; | ||
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); | ||
jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00); | ||
/* Do nothing, only return. */ | ||
sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | ||
3268 | JUMPHERE(jump); | JUMPHERE(jump); |
3269 | /* Combine two 16 bit characters. */ | OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); |
3270 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); |
3271 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff); | ||
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10); | ||
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3ff); | ||
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); | ||
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000); | ||
3272 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
3273 | } | } |
3274 | ||
3275 | #endif /* COMPILE_PCRE[8|16] */ | #endif /* COMPILE_PCRE8 */ |
3276 | ||
3277 | #endif /* SUPPORT_UTF */ | #endif /* SUPPORT_UTF */ |
3278 | ||
# | Line 2750 SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && si | Line 3292 SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && si |
3292 | ||
3293 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
3294 | OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); | OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); |
3295 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); | OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); |
3296 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); |
3297 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); |
3298 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); |
3299 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2)); |
3300 | OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); | OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); |
3301 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); |
3302 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); |
3303 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
3304 | } | } |
3305 | #endif | #endif |
3306 | ||
3307 | static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline) | static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf) |
3308 | { | { |
3309 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3310 | struct sljit_label *mainloop; | struct sljit_label *mainloop; |
3311 | struct sljit_label *newlinelabel = NULL; | struct sljit_label *newlinelabel = NULL; |
3312 | struct sljit_jump *start; | struct sljit_jump *start; |
3313 | struct sljit_jump *end = NULL; | struct sljit_jump *end = NULL; |
3314 | struct sljit_jump *nl = NULL; | struct sljit_jump *end2 = NULL; |
3315 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 |
3316 | struct sljit_jump *singlechar; | struct sljit_jump *singlechar; |
3317 | #endif | #endif |
# | Line 2777 jump_list *newline = NULL; | Line 3319 jump_list *newline = NULL; |
3319 | BOOL newlinecheck = FALSE; | BOOL newlinecheck = FALSE; |
3320 | BOOL readuchar = FALSE; | BOOL readuchar = FALSE; |
3321 | ||
3322 | if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY || | if (!(hascrorlf || (common->match_end_ptr != 0)) && |
3323 | common->nltype == NLTYPE_ANYCRLF || common->newline > 255)) | (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255)) |
3324 | newlinecheck = TRUE; | newlinecheck = TRUE; |
3325 | ||
3326 | if (firstline) | if (common->match_end_ptr != 0) |
3327 | { | { |
3328 | /* Search for the end of the first line. */ | /* Search for the end of the first line. */ |
SLJIT_ASSERT(common->first_line_end != 0); | ||
3329 | OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); | OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); |
3330 | ||
3331 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
3332 | { | { |
3333 | mainloop = LABEL(); | mainloop = LABEL(); |
3334 | 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)); |
3335 | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
3336 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); |
3337 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
3338 | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); | CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); |
3339 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); | CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); |
3340 | JUMPHERE(end); | JUMPHERE(end); |
3341 | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3342 | } | } |
3343 | else | else |
3344 | { | { |
3345 | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
3346 | mainloop = LABEL(); | mainloop = LABEL(); |
3347 | /* Continual stores does not cause data dependency. */ | /* Continual stores does not cause data dependency. */ |
3348 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0); |
3349 | read_char(common); | read_char_range(common, common->nlmin, common->nlmax, TRUE); |
3350 | check_newlinechar(common, common->nltype, &newline, TRUE); | check_newlinechar(common, common->nltype, &newline, TRUE); |
3351 | CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); | CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, mainloop); |
3352 | JUMPHERE(end); | JUMPHERE(end); |
3353 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0); |
3354 | set_jumps(newline, LABEL()); | set_jumps(newline, LABEL()); |
3355 | } | } |
3356 | ||
# | Line 2822 if (newlinecheck) | Line 3363 if (newlinecheck) |
3363 | { | { |
3364 | newlinelabel = LABEL(); | newlinelabel = LABEL(); |
3365 | 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)); |
3366 | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
3367 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
3368 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff); |
3369 | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); |
3370 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
3371 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); |
3372 | #endif | #endif |
3373 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
3374 | nl = JUMP(SLJIT_JUMP); | end2 = JUMP(SLJIT_JUMP); |
3375 | } | } |
3376 | ||
3377 | mainloop = LABEL(); | mainloop = LABEL(); |
# | Line 2845 if (readuchar) | Line 3386 if (readuchar) |
3386 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
3387 | ||
3388 | if (newlinecheck) | if (newlinecheck) |
3389 | CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); | CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); |
3390 | ||
3391 | 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)); |
3392 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 |
3393 | #if defined COMPILE_PCRE8 | #if defined COMPILE_PCRE8 |
3394 | if (common->utf) | if (common->utf) |
3395 | { | { |
3396 | singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); | singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); |
3397 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); |
3398 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
3399 | JUMPHERE(singlechar); | JUMPHERE(singlechar); |
3400 | } | } |
3401 | #elif defined COMPILE_PCRE16 | #elif defined COMPILE_PCRE16 |
3402 | if (common->utf) | if (common->utf) |
3403 | { | { |
3404 | singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800); |
3405 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); |
3406 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); |
3407 | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); |
3408 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
3409 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
3410 | JUMPHERE(singlechar); | JUMPHERE(singlechar); |
# | Line 2875 JUMPHERE(start); | Line 3416 JUMPHERE(start); |
3416 | if (newlinecheck) | if (newlinecheck) |
3417 | { | { |
3418 | JUMPHERE(end); | JUMPHERE(end); |
3419 | JUMPHERE(nl); | JUMPHERE(end2); |
3420 | } | } |
3421 | ||
3422 | return mainloop; | return mainloop; |
3423 | } | } |
3424 | ||
3425 | #define MAX_N_CHARS 3 | #define MAX_N_CHARS 16 |
3426 | #define MAX_DIFF_CHARS 6 | |
3427 | ||
3428 | static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common, BOOL firstline) | static SLJIT_INLINE void add_prefix_char(pcre_uchar chr, pcre_uchar *chars) |
3429 | { | { |
3430 | DEFINE_COMPILER; | pcre_uchar i, len; |
struct sljit_label *start; | ||
struct sljit_jump *quit; | ||
pcre_uint32 chars[MAX_N_CHARS * 2]; | ||
pcre_uchar *cc = common->start + 1 + LINK_SIZE; | ||
int location = 0; | ||
pcre_int32 len, c, bit, caseless; | ||
int must_stop; | ||
3431 | ||
3432 | /* We do not support alternatives now. */ | len = chars[0]; |
3433 | if (*(common->start + GET(common->start, 1)) == OP_ALT) | if (len == 255) |
3434 | return FALSE; | return; |
3435 | ||
3436 | if (len == 0) | |
3437 | { | |
3438 | chars[0] = 1; | |
3439 | chars[1] = chr; | |
3440 | return; | |
3441 | } | |
3442 | ||
3443 | for (i = len; i > 0; i--) | |
3444 | if (chars[i] == chr) | |
3445 | return; | |
3446 | ||
3447 | if (len >= MAX_DIFF_CHARS - 1) | |
3448 | { | |
3449 | chars[0] = 255; | |
3450 | return; | |
3451 | } | |
3452 | ||
3453 | len++; | |
3454 | chars[len] = chr; | |
3455 | chars[0] = len; | |
3456 | } | |
3457 | ||
3458 | static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uchar *chars, int max_chars, pcre_uint32 *rec_count) | |
3459 | { | |
3460 | /* Recursive function, which scans prefix literals. */ | |
3461 | BOOL last, any, class, caseless; | |
3462 | int len, repeat, len_save, consumed = 0; | |
3463 | sljit_u32 chr; | |
3464 | sljit_u8 *bytes, *bytes_end, byte; | |
3465 | pcre_uchar *alternative, *cc_save, *oc; | |
3466 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | |
3467 | pcre_uchar othercase[8]; | |
3468 | #elif defined SUPPORT_UTF && defined COMPILE_PCRE16 | |
3469 | pcre_uchar othercase[2]; | |
3470 | #else | |
3471 | pcre_uchar othercase[1]; | |
3472 | #endif | |
3473 | ||
3474 | repeat = 1; | |
3475 | while (TRUE) | while (TRUE) |
3476 | { | { |
3477 | caseless = 0; | if (*rec_count == 0) |
3478 | must_stop = 1; | return 0; |
3479 | switch(*cc) | (*rec_count)--; |
{ | ||
case OP_CHAR: | ||
must_stop = 0; | ||
cc++; | ||
break; | ||
3480 | ||
3481 | last = TRUE; | |
3482 | any = FALSE; | |
3483 | class = FALSE; | |
3484 | caseless = FALSE; | |
3485 | ||
3486 | switch (*cc) | |
3487 | { | |
3488 | case OP_CHARI: | case OP_CHARI: |
3489 | caseless = 1; | caseless = TRUE; |
3490 | must_stop = 0; | case OP_CHAR: |
3491 | last = FALSE; | |
3492 | cc++; | cc++; |
3493 | break; | break; |
3494 | ||
# | Line 2930 while (TRUE) | Line 3507 while (TRUE) |
3507 | cc++; | cc++; |
3508 | continue; | continue; |
3509 | ||
3510 | case OP_ASSERT: | |
3511 | case OP_ASSERT_NOT: | |
3512 | case OP_ASSERTBACK: | |
3513 | case OP_ASSERTBACK_NOT: | |
3514 | cc = bracketend(cc); | |
3515 | continue; | |
3516 | ||
3517 | case OP_PLUSI: | |
3518 | case OP_MINPLUSI: | |
3519 | case OP_POSPLUSI: | |
3520 | caseless = TRUE; | |
3521 | case OP_PLUS: | case OP_PLUS: |
3522 | case OP_MINPLUS: | case OP_MINPLUS: |
3523 | case OP_POSPLUS: | case OP_POSPLUS: |
3524 | cc++; | cc++; |
3525 | break; | break; |
3526 | ||
3527 | case OP_EXACTI: | |
3528 | caseless = TRUE; | |
3529 | case OP_EXACT: | case OP_EXACT: |
3530 | repeat = GET2(cc, 1); | |
3531 | last = FALSE; | |
3532 | cc += 1 + IMM2_SIZE; | cc += 1 + IMM2_SIZE; |
3533 | break; | break; |
3534 | ||
3535 | case OP_PLUSI: | case OP_QUERYI: |
3536 | case OP_MINPLUSI: | case OP_MINQUERYI: |
3537 | case OP_POSPLUSI: | case OP_POSQUERYI: |
3538 | caseless = 1; | caseless = TRUE; |
3539 | case OP_QUERY: | |
3540 | case OP_MINQUERY: | |
3541 | case OP_POSQUERY: | |
3542 | len = 1; | |
3543 | cc++; | cc++; |
3544 | #ifdef SUPPORT_UTF | |
3545 | if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc); | |
3546 | #endif | |
3547 | max_chars = scan_prefix(common, cc + len, chars, max_chars, rec_count); | |
3548 | if (max_chars == 0) | |
3549 | return consumed; | |
3550 | last = FALSE; | |
3551 | break; | break; |
3552 | ||
3553 | case OP_EXACTI: | case OP_KET: |
3554 | caseless = 1; | cc += 1 + LINK_SIZE; |
3555 | cc += 1 + IMM2_SIZE; | continue; |
break; | ||
3556 | ||
3557 | default: | case OP_ALT: |
3558 | must_stop = 2; | cc += GET(cc, 1); |
3559 | continue; | |
3560 | ||
3561 | case OP_ONCE: | |
3562 | case OP_ONCE_NC: | |
3563 | case OP_BRA: | |
3564 | case OP_BRAPOS: | |
3565 | case OP_CBRA: | |
3566 | case OP_CBRAPOS: | |
3567 | alternative = cc + GET(cc, 1); | |
3568 | while (*alternative == OP_ALT) | |
3569 | { | |
3570 | max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, max_chars, rec_count); | |
3571 | if (max_chars == 0) | |
3572 | return consumed; | |
3573 | alternative += GET(alternative, 1); | |
3574 | } | |
3575 | ||
3576 | if (*cc == OP_CBRA || *cc == OP_CBRAPOS) | |
3577 | cc += IMM2_SIZE; | |
3578 | cc += 1 + LINK_SIZE; | |
3579 | continue; | |
3580 | ||
3581 | case OP_CLASS: | |
3582 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | |
3583 | if (common->utf && !is_char7_bitset((const sljit_u8 *)(cc + 1), FALSE)) | |
3584 | return consumed; | |
3585 | #endif | |
3586 | class = TRUE; | |
3587 | break; | |
3588 | ||
3589 | case OP_NCLASS: | |
3590 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | |
3591 | if (common->utf) return consumed; | |
3592 | #endif | |
3593 | class = TRUE; | |
3594 | break; | |
3595 | ||
3596 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | |
3597 | case OP_XCLASS: | |
3598 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | |
3599 | if (common->utf) return consumed; | |
3600 | #endif | |
3601 | any = TRUE; | |
3602 | cc += GET(cc, 1); | |
3603 | break; | |
3604 | #endif | |
3605 | ||
3606 | case OP_DIGIT: | |
3607 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | |
3608 | if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE)) | |
3609 | return consumed; | |
3610 | #endif | |
3611 | any = TRUE; | |
3612 | cc++; | |
3613 | break; | |
3614 | ||
3615 | case OP_WHITESPACE: | |
3616 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | |
3617 | if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE)) | |
3618 | return consumed; | |
3619 | #endif | |
3620 | any = TRUE; | |
3621 | cc++; | |
3622 | break; | |
3623 | ||
3624 | case OP_WORDCHAR: | |
3625 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | |
3626 | if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE)) | |
3627 | return consumed; | |
3628 | #endif | |
3629 | any = TRUE; | |
3630 | cc++; | |
3631 | break; | |
3632 | ||
3633 | case OP_NOT: | |
3634 | case OP_NOTI: | |
3635 | cc++; | |
3636 | /* Fall through. */ | |
3637 | case OP_NOT_DIGIT: | |
3638 | case OP_NOT_WHITESPACE: | |
3639 | case OP_NOT_WORDCHAR: | |
3640 | case OP_ANY: | |
3641 | case OP_ALLANY: | |
3642 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | |
3643 | if (common->utf) return consumed; | |
3644 | #endif | |
3645 | any = TRUE; | |
3646 | cc++; | |
3647 | break; | |
3648 | ||
3649 | #ifdef SUPPORT_UTF | |
3650 | case OP_NOTPROP: | |
3651 | case OP_PROP: | |
3652 | #ifndef COMPILE_PCRE32 | |
3653 | if (common->utf) return consumed; | |
3654 | #endif | |
3655 | any = TRUE; | |
3656 | cc += 1 + 2; | |
3657 | break; | |
3658 | #endif | |
3659 | ||
3660 | case OP_TYPEEXACT: | |
3661 | repeat = GET2(cc, 1); | |
3662 | cc += 1 + IMM2_SIZE; | |
3663 | continue; | |
3664 | ||
3665 | case OP_NOTEXACT: | |
3666 | case OP_NOTEXACTI: | |
3667 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | |
3668 | if (common->utf) return consumed; | |
3669 | #endif | |
3670 | any = TRUE; | |
3671 | repeat = GET2(cc, 1); | |
3672 | cc += 1 + IMM2_SIZE + 1; | |
3673 | break; | break; |
3674 | ||
3675 | default: | |
3676 | return consumed; | |
3677 | } | |
3678 | ||
3679 | if (any) | |
3680 | { | |
3681 | do | |
3682 | { | |
3683 | chars[0] = 255; | |
3684 | ||
3685 | consumed++; | |
3686 | if (--max_chars == 0) | |
3687 | return consumed; | |
3688 | chars += MAX_DIFF_CHARS; | |
3689 | } | |
3690 | while (--repeat > 0); | |
3691 | ||
3692 | repeat = 1; | |
3693 | continue; | |
3694 | } | } |
3695 | ||
3696 | if (must_stop == 2) | if (class) |
3697 | { | |
3698 | bytes = (sljit_u8*) (cc + 1); | |
3699 | cc += 1 + 32 / sizeof(pcre_uchar); | |
3700 | ||
3701 | switch (*cc) | |
3702 | { | |
3703 | case OP_CRSTAR: | |
3704 | case OP_CRMINSTAR: | |
3705 | case OP_CRPOSSTAR: | |
3706 | case OP_CRQUERY: | |
3707 | case OP_CRMINQUERY: | |
3708 | case OP_CRPOSQUERY: | |
3709 | max_chars = scan_prefix(common, cc + 1, chars, max_chars, rec_count); | |
3710 | if (max_chars == 0) | |
3711 | return consumed; | |
3712 | break; | |
3713 | ||
3714 | default: | |
3715 | case OP_CRPLUS: | |
3716 | case OP_CRMINPLUS: | |
3717 | case OP_CRPOSPLUS: | |
3718 | break; | |
3719 | ||
3720 | case OP_CRRANGE: | |
3721 | case OP_CRMINRANGE: | |
3722 | case OP_CRPOSRANGE: | |
3723 | repeat = GET2(cc, 1); | |
3724 | if (repeat <= 0) | |
3725 | return consumed; | |
3726 | break; | |
3727 | } | |
3728 | ||
3729 | do | |
3730 | { | |
3731 | if (bytes[31] & 0x80) | |
3732 | chars[0] = 255; | |
3733 | else if (chars[0] != 255) | |
3734 | { | |
3735 | bytes_end = bytes + 32; | |
3736 | chr = 0; | |
3737 | do | |
3738 | { | |
3739 | byte = *bytes++; | |
3740 | SLJIT_ASSERT((chr & 0x7) == 0); | |
3741 | if (byte == 0) | |
3742 | chr += 8; | |
3743 | else | |
3744 | { | |
3745 | do | |
3746 | { | |
3747 | if ((byte & 0x1) != 0) | |
3748 | add_prefix_char(chr, chars); | |
3749 | byte >>= 1; | |
3750 | chr++; | |
3751 | } | |
3752 | while (byte != 0); | |
3753 | chr = (chr + 7) & ~7; | |
3754 | } | |
3755 | } | |
3756 | while (chars[0] != 255 && bytes < bytes_end); | |
3757 | bytes = bytes_end - 32; | |
3758 | } | |
3759 | ||
3760 | consumed++; | |
3761 | if (--max_chars == 0) | |
3762 | return consumed; | |
3763 | chars += MAX_DIFF_CHARS; | |
3764 | } | |
3765 | while (--repeat > 0); | |
3766 | ||
3767 | switch (*cc) | |
3768 | { | |
3769 | case OP_CRSTAR: | |
3770 | case OP_CRMINSTAR: | |
3771 | case OP_CRPOSSTAR: | |
3772 | return consumed; | |
3773 | ||
3774 | case OP_CRQUERY: | |
3775 | case OP_CRMINQUERY: | |
3776 | case OP_CRPOSQUERY: | |
3777 | cc++; | |
3778 | break; | break; |
3779 | ||
3780 | case OP_CRRANGE: | |
3781 | case OP_CRMINRANGE: | |
3782 | case OP_CRPOSRANGE: | |
3783 | if (GET2(cc, 1) != GET2(cc, 1 + IMM2_SIZE)) | |
3784 | return consumed; | |
3785 | cc += 1 + 2 * IMM2_SIZE; | |
3786 | break; | |
3787 | } | |
3788 | ||
3789 | repeat = 1; | |
3790 | continue; | |
3791 | } | |
3792 | ||
3793 | len = 1; | len = 1; |
3794 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
3795 | if (common->utf && HAS_EXTRALEN(cc[0])) len += GET_EXTRALEN(cc[0]); | if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc); |
3796 | #endif | #endif |
3797 | ||
3798 | if (caseless && char_has_othercase(common, cc)) | if (caseless && char_has_othercase(common, cc)) |
3799 | { | { |
3800 | caseless = char_get_othercase_bit(common, cc); | #ifdef SUPPORT_UTF |
3801 | if (caseless == 0) | if (common->utf) |
3802 | return FALSE; | { |
3803 | #ifdef COMPILE_PCRE8 | GETCHAR(chr, cc); |
3804 | caseless = ((caseless & 0xff) << 8) | (len - (caseless >> 8)); | if ((int)PRIV(ord2utf)(char_othercase(common, chr), othercase) != len) |
3805 | #else | return consumed; |
3806 | if ((caseless & 0x100) != 0) | } |
caseless = ((caseless & 0xff) << 16) | (len - (caseless >> 9)); | ||
3807 | else | else |
caseless = ((caseless & 0xff) << 8) | (len - (caseless >> 9)); | ||
3808 | #endif | #endif |
3809 | { | |
3810 | chr = *cc; | |
3811 | othercase[0] = TABLE_GET(chr, common->fcc, chr); | |
3812 | } | |
3813 | } | } |
3814 | else | else |
3815 | caseless = 0; | { |
3816 | caseless = FALSE; | |
3817 | othercase[0] = 0; /* Stops compiler warning - PH */ | |
3818 | } | |
3819 | ||
3820 | while (len > 0 && location < MAX_N_CHARS * 2) | len_save = len; |
3821 | cc_save = cc; | |
3822 | while (TRUE) | |
3823 | { | { |
3824 | c = *cc; | oc = othercase; |
3825 | bit = 0; | do |
if (len == (caseless & 0xff)) | ||
3826 | { | { |
3827 | bit = caseless >> 8; | chr = *cc; |
3828 | c |= bit; | add_prefix_char(*cc, chars); |
3829 | ||
3830 | if (caseless) | |
3831 | add_prefix_char(*oc, chars); | |
3832 | ||
3833 | len--; | |
3834 | consumed++; | |
3835 | if (--max_chars == 0) | |
3836 | return consumed; | |
3837 | chars += MAX_DIFF_CHARS; | |
3838 | cc++; | |
3839 | oc++; | |
3840 | } | } |
3841 | while (len > 0); | |
3842 | ||
3843 | chars[location] = c; | if (--repeat == 0) |
3844 | chars[location + 1] = bit; | break; |
3845 | ||
3846 | len--; | len = len_save; |
3847 | location += 2; | cc = cc_save; |
cc++; | ||
3848 | } | } |
3849 | ||
3850 | if (location >= MAX_N_CHARS * 2 || must_stop != 0) | repeat = 1; |
3851 | break; | if (last) |
3852 | return consumed; | |
3853 | } | |
3854 | } | |
3855 | ||
3856 | #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) | |
3857 | ||
3858 | static sljit_s32 character_to_int32(pcre_uchar chr) | |
3859 | { | |
3860 | sljit_s32 value = (sljit_s32)chr; | |
3861 | #if defined COMPILE_PCRE8 | |
3862 | #define SSE2_COMPARE_TYPE_INDEX 0 | |
3863 | return (value << 24) | (value << 16) | (value << 8) | value; | |
3864 | #elif defined COMPILE_PCRE16 | |
3865 | #define SSE2_COMPARE_TYPE_INDEX 1 | |
3866 | return (value << 16) | value; | |
3867 | #elif defined COMPILE_PCRE32 | |
3868 | #define SSE2_COMPARE_TYPE_INDEX 2 | |
3869 | return value; | |
3870 | #else | |
3871 | #error "Unsupported unit width" | |
3872 | #endif | |
3873 | } | |
3874 | ||
3875 | static SLJIT_INLINE void fast_forward_first_char2_sse2(compiler_common *common, pcre_uchar char1, pcre_uchar char2) | |
3876 | { | |
3877 | DEFINE_COMPILER; | |
3878 | struct sljit_label *start; | |
3879 | struct sljit_jump *quit[3]; | |
3880 | struct sljit_jump *nomatch; | |
3881 | sljit_u8 instruction[8]; | |
3882 | sljit_s32 tmp1_ind = sljit_get_register_index(TMP1); | |
3883 | sljit_s32 tmp2_ind = sljit_get_register_index(TMP2); | |
3884 | sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR); | |
3885 | BOOL load_twice = FALSE; | |
3886 | pcre_uchar bit; | |
3887 | ||
3888 | bit = char1 ^ char2; | |
3889 | if (!is_powerof2(bit)) | |
3890 | bit = 0; | |
3891 | ||
3892 | if ((char1 != char2) && bit == 0) | |
3893 | load_twice = TRUE; | |
3894 | ||
3895 | quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | |
3896 | ||
3897 | /* First part (unaligned start) */ | |
3898 | ||
3899 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit)); | |
3900 | ||
3901 | SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1); | |
3902 | ||
3903 | /* MOVD xmm, r/m32 */ | |
3904 | instruction[0] = 0x66; | |
3905 | instruction[1] = 0x0f; | |
3906 | instruction[2] = 0x6e; | |
3907 | instruction[3] = 0xc0 | (2 << 3) | tmp1_ind; | |
3908 | sljit_emit_op_custom(compiler, instruction, 4); | |
3909 | ||
3910 | if (char1 != char2) | |
3911 | { | |
3912 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2)); | |
3913 | ||
3914 | /* MOVD xmm, r/m32 */ | |
3915 | instruction[3] = 0xc0 | (3 << 3) | tmp1_ind; | |
3916 | sljit_emit_op_custom(compiler, instruction, 4); | |
3917 | } | |
3918 | ||
3919 | /* PSHUFD xmm1, xmm2/m128, imm8 */ | |
3920 | instruction[2] = 0x70; | |
3921 | instruction[3] = 0xc0 | (2 << 3) | 2; | |
3922 | instruction[4] = 0; | |
3923 | sljit_emit_op_custom(compiler, instruction, 5); | |
3924 | ||
3925 | if (char1 != char2) | |
3926 | { | |
3927 | /* PSHUFD xmm1, xmm2/m128, imm8 */ | |
3928 | instruction[3] = 0xc0 | (3 << 3) | 3; | |
3929 | instruction[4] = 0; | |
3930 | sljit_emit_op_custom(compiler, instruction, 5); | |
3931 | } | |
3932 | ||
3933 | OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 0xf); | |
3934 | OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf); | |
3935 | ||
3936 | /* MOVDQA xmm1, xmm2/m128 */ | |
3937 | #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) | |
3938 | ||
3939 | if (str_ptr_ind < 8) | |
3940 | { | |
3941 | instruction[2] = 0x6f; | |
3942 | instruction[3] = (0 << 3) | str_ptr_ind; | |
3943 | sljit_emit_op_custom(compiler, instruction, 4); | |
3944 | ||
3945 | if (load_twice) | |
3946 | { | |
3947 | instruction[3] = (1 << 3) | str_ptr_ind; | |
3948 | sljit_emit_op_custom(compiler, instruction, 4); | |
3949 | } | |
3950 | } | |
3951 | else | |
3952 | { | |
3953 | instruction[1] = 0x41; | |
3954 | instruction[2] = 0x0f; | |
3955 | instruction[3] = 0x6f; | |
3956 | instruction[4] = (0 << 3) | (str_ptr_ind & 0x7); | |
3957 | sljit_emit_op_custom(compiler, instruction, 5); | |
3958 | ||
3959 | if (load_twice) | |
3960 | { | |
3961 | instruction[4] = (1 << 3) | str_ptr_ind; | |
3962 | sljit_emit_op_custom(compiler, instruction, 5); | |
3963 | } | |
3964 | instruction[1] = 0x0f; | |
3965 | } | |
3966 | ||
3967 | #else | |
3968 | ||
3969 | instruction[2] = 0x6f; | |
3970 | instruction[3] = (0 << 3) | str_ptr_ind; | |
3971 | sljit_emit_op_custom(compiler, instruction, 4); | |
3972 | ||
3973 | if (load_twice) | |
3974 | { | |
3975 | instruction[3] = (1 << 3) | str_ptr_ind; | |
3976 | sljit_emit_op_custom(compiler, instruction, 4); | |
3977 | } | |
3978 | ||
3979 | #endif | |
3980 | ||
3981 | if (bit != 0) | |
3982 | { | |
3983 | /* POR xmm1, xmm2/m128 */ | |
3984 | instruction[2] = 0xeb; | |
3985 | instruction[3] = 0xc0 | (0 << 3) | 3; | |
3986 | sljit_emit_op_custom(compiler, instruction, 4); | |
3987 | } | |
3988 | ||
3989 | /* PCMPEQB/W/D xmm1, xmm2/m128 */ | |
3990 | instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX; | |
3991 | instruction[3] = 0xc0 | (0 << 3) | 2; | |
3992 | sljit_emit_op_custom(compiler, instruction, 4); | |
3993 | ||
3994 | if (load_twice) | |
3995 | { | |
3996 | instruction[3] = 0xc0 | (1 << 3) | 3; | |
3997 | sljit_emit_op_custom(compiler, instruction, 4); | |
3998 | } | |
3999 | ||
4000 | /* PMOVMSKB reg, xmm */ | |
4001 | instruction[2] = 0xd7; | |
4002 | instruction[3] = 0xc0 | (tmp1_ind << 3) | 0; | |
4003 | sljit_emit_op_custom(compiler, instruction, 4); | |
4004 | ||
4005 | if (load_twice) | |
4006 | { | |
4007 | OP1(SLJIT_MOV, TMP3, 0, TMP2, 0); | |
4008 | instruction[3] = 0xc0 | (tmp2_ind << 3) | 1; | |
4009 | sljit_emit_op_custom(compiler, instruction, 4); | |
4010 | ||
4011 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
4012 | OP1(SLJIT_MOV, TMP2, 0, TMP3, 0); | |
4013 | } | } |
4014 | ||
4015 | /* At least two characters are required. */ | OP2(SLJIT_ASHR, TMP1, 0, TMP1, 0, TMP2, 0); |
4016 | if (location < 2 * 2) | |
4017 | /* BSF r32, r/m32 */ | |
4018 | instruction[0] = 0x0f; | |
4019 | instruction[1] = 0xbc; | |
4020 | instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind; | |
4021 | sljit_emit_op_custom(compiler, instruction, 3); | |
4022 | ||
4023 | nomatch = JUMP(SLJIT_ZERO); | |
4024 | ||
4025 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | |
4026 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
4027 | quit[1] = JUMP(SLJIT_JUMP); | |
4028 | ||
4029 | JUMPHERE(nomatch); | |
4030 | ||
4031 | start = LABEL(); | |
4032 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16); | |
4033 | quit[2] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | |
4034 | ||
4035 | /* Second part (aligned) */ | |
4036 | ||
4037 | instruction[0] = 0x66; | |
4038 | instruction[1] = 0x0f; | |
4039 | ||
4040 | /* MOVDQA xmm1, xmm2/m128 */ | |
4041 | #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) | |
4042 | ||
4043 | if (str_ptr_ind < 8) | |
4044 | { | |
4045 | instruction[2] = 0x6f; | |
4046 | instruction[3] = (0 << 3) | str_ptr_ind; | |
4047 | sljit_emit_op_custom(compiler, instruction, 4); | |
4048 | ||
4049 | if (load_twice) | |
4050 | { | |
4051 | instruction[3] = (1 << 3) | str_ptr_ind; | |
4052 | sljit_emit_op_custom(compiler, instruction, 4); | |
4053 | } | |
4054 | } | |
4055 | else | |
4056 | { | |
4057 | instruction[1] = 0x41; | |
4058 | instruction[2] = 0x0f; | |
4059 | instruction[3] = 0x6f; | |
4060 | instruction[4] = (0 << 3) | (str_ptr_ind & 0x7); | |
4061 | sljit_emit_op_custom(compiler, instruction, 5); | |
4062 | ||
4063 | if (load_twice) | |
4064 | { | |
4065 | instruction[4] = (1 << 3) | str_ptr_ind; | |
4066 | sljit_emit_op_custom(compiler, instruction, 5); | |
4067 | } | |
4068 | instruction[1] = 0x0f; | |
4069 | } | |
4070 | ||
4071 | #else | |
4072 | ||
4073 | instruction[2] = 0x6f; | |
4074 | instruction[3] = (0 << 3) | str_ptr_ind; | |
4075 | sljit_emit_op_custom(compiler, instruction, 4); | |
4076 | ||
4077 | if (load_twice) | |
4078 | { | |
4079 | instruction[3] = (1 << 3) | str_ptr_ind; | |
4080 | sljit_emit_op_custom(compiler, instruction, 4); | |
4081 | } | |
4082 | ||
4083 | #endif | |
4084 | ||
4085 | if (bit != 0) | |
4086 | { | |
4087 | /* POR xmm1, xmm2/m128 */ | |
4088 | instruction[2] = 0xeb; | |
4089 | instruction[3] = 0xc0 | (0 << 3) | 3; | |
4090 | sljit_emit_op_custom(compiler, instruction, 4); | |
4091 | } | |
4092 | ||
4093 | /* PCMPEQB/W/D xmm1, xmm2/m128 */ | |
4094 | instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX; | |
4095 | instruction[3] = 0xc0 | (0 << 3) | 2; | |
4096 | sljit_emit_op_custom(compiler, instruction, 4); | |
4097 | ||
4098 | if (load_twice) | |
4099 | { | |
4100 | instruction[3] = 0xc0 | (1 << 3) | 3; | |
4101 | sljit_emit_op_custom(compiler, instruction, 4); | |
4102 | } | |
4103 | ||
4104 | /* PMOVMSKB reg, xmm */ | |
4105 | instruction[2] = 0xd7; | |
4106 | instruction[3] = 0xc0 | (tmp1_ind << 3) | 0; | |
4107 | sljit_emit_op_custom(compiler, instruction, 4); | |
4108 | ||
4109 | if (load_twice) | |
4110 | { | |
4111 | instruction[3] = 0xc0 | (tmp2_ind << 3) | 1; | |
4112 | sljit_emit_op_custom(compiler, instruction, 4); | |
4113 | ||
4114 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
4115 | } | |
4116 | ||
4117 | /* BSF r32, r/m32 */ | |
4118 | instruction[0] = 0x0f; | |
4119 | instruction[1] = 0xbc; | |
4120 | instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind; | |
4121 | sljit_emit_op_custom(compiler, instruction, 3); | |
4122 | ||
4123 | JUMPTO(SLJIT_ZERO, start); | |
4124 | ||
4125 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
4126 | ||
4127 | start = LABEL(); | |
4128 | SET_LABEL(quit[0], start); | |
4129 | SET_LABEL(quit[1], start); | |
4130 | SET_LABEL(quit[2], start); | |
4131 | } | |
4132 | ||
4133 | #undef SSE2_COMPARE_TYPE_INDEX | |
4134 | ||
4135 | #endif | |
4136 | ||
4137 | static void fast_forward_first_char2(compiler_common *common, pcre_uchar char1, pcre_uchar char2, sljit_s32 offset) | |
4138 | { | |
4139 | DEFINE_COMPILER; | |
4140 | struct sljit_label *start; | |
4141 | struct sljit_jump *quit; | |
4142 | struct sljit_jump *found; | |
4143 | pcre_uchar mask; | |
4144 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | |
4145 | struct sljit_label *utf_start = NULL; | |
4146 | struct sljit_jump *utf_quit = NULL; | |
4147 | #endif | |
4148 | BOOL has_match_end_ptr = (common->match_end_ptr != 0); | |
4149 | ||
4150 | if (offset > 0) | |
4151 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); | |
4152 | ||
4153 | if (has_match_end_ptr) | |
4154 | { | |
4155 | OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); | |
4156 | ||
4157 | OP2(SLJIT_ADD, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, SLJIT_IMM, IN_UCHARS(offset + 1)); | |
4158 | #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) | |
4159 | if (sljit_x86_is_cmov_available()) | |
4160 | { | |
4161 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0); | |
4162 | sljit_x86_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0); | |
4163 | } | |
4164 | #endif | |
4165 | { | |
4166 | quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP3, 0); | |
4167 | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); | |
4168 | JUMPHERE(quit); | |
4169 | } | |
4170 | } | |
4171 | ||
4172 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | |
4173 | if (common->utf && offset > 0) | |
4174 | utf_start = LABEL(); | |
4175 | #endif | |
4176 | ||
4177 | #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) | |
4178 | ||
4179 | /* SSE2 accelerated first character search. */ | |
4180 | ||
4181 | if (sljit_x86_is_sse2_available()) | |
4182 | { | |
4183 | fast_forward_first_char2_sse2(common, char1, char2); | |
4184 | ||
4185 | SLJIT_ASSERT(common->mode == JIT_COMPILE || offset == 0); | |
4186 | if (common->mode == JIT_COMPILE) | |
4187 | { | |
4188 | /* In complete mode, we don't need to run a match when STR_PTR == STR_END. */ | |
4189 | SLJIT_ASSERT(common->forced_quit_label == NULL); | |
4190 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); | |
4191 | add_jump(compiler, &common->forced_quit, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | |
4192 | ||
4193 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | |
4194 | if (common->utf && offset > 0) | |
4195 | { | |
4196 | SLJIT_ASSERT(common->mode == JIT_COMPILE); | |
4197 | ||
4198 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset)); | |
4199 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
4200 | #if defined COMPILE_PCRE8 | |
4201 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); | |
4202 | CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start); | |
4203 | #elif defined COMPILE_PCRE16 | |
4204 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | |
4205 | CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start); | |
4206 | #else | |
4207 | #error "Unknown code width" | |
4208 | #endif | |
4209 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
4210 | } | |
4211 | #endif | |
4212 | ||
4213 | if (offset > 0) | |
4214 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); | |
4215 | } | |
4216 | else if (sljit_x86_is_cmov_available()) | |
4217 | { | |
4218 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0); | |
4219 | sljit_x86_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, has_match_end_ptr ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_match_end_ptr ? common->match_end_ptr : 0); | |
4220 | } | |
4221 | else | |
4222 | { | |
4223 | quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); | |
4224 | OP1(SLJIT_MOV, STR_PTR, 0, has_match_end_ptr ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_match_end_ptr ? common->match_end_ptr : 0); | |
4225 | JUMPHERE(quit); | |
4226 | } | |
4227 | ||
4228 | if (has_match_end_ptr) | |
4229 | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); | |
4230 | return; | |
4231 | } | |
4232 | ||
4233 | #endif | |
4234 | ||
4235 | quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | |
4236 | ||
4237 | start = LABEL(); | |
4238 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | |
4239 | ||
4240 | if (char1 == char2) | |
4241 | found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1); | |
4242 | else | |
4243 | { | |
4244 | mask = char1 ^ char2; | |
4245 | if (is_powerof2(mask)) | |
4246 | { | |
4247 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask); | |
4248 | found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask); | |
4249 | } | |
4250 | else | |
4251 | { | |
4252 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char1); | |
4253 | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); | |
4254 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char2); | |
4255 | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); | |
4256 | found = JUMP(SLJIT_NOT_ZERO); | |
4257 | } | |
4258 | } | |
4259 | ||
4260 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
4261 | CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, start); | |
4262 | ||
4263 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | |
4264 | if (common->utf && offset > 0) | |
4265 | utf_quit = JUMP(SLJIT_JUMP); | |
4266 | #endif | |
4267 | ||
4268 | JUMPHERE(found); | |
4269 | ||
4270 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | |
4271 | if (common->utf && offset > 0) | |
4272 | { | |
4273 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset)); | |
4274 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
4275 | #if defined COMPILE_PCRE8 | |
4276 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); | |
4277 | CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start); | |
4278 | #elif defined COMPILE_PCRE16 | |
4279 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | |
4280 | CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start); | |
4281 | #else | |
4282 | #error "Unknown code width" | |
4283 | #endif | |
4284 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
4285 | JUMPHERE(utf_quit); | |
4286 | } | |
4287 | #endif | |
4288 | ||
4289 | JUMPHERE(quit); | |
4290 | ||
4291 | if (has_match_end_ptr) | |
4292 | { | |
4293 | quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); | |
4294 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); | |
4295 | if (offset > 0) | |
4296 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); | |
4297 | JUMPHERE(quit); | |
4298 | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); | |
4299 | } | |
4300 | ||
4301 | if (offset > 0) | |
4302 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); | |
4303 | } | |
4304 | ||
4305 | static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common) | |
4306 | { | |
4307 | DEFINE_COMPILER; | |
4308 | struct sljit_label *start; | |
4309 | struct sljit_jump *quit; | |
4310 | struct sljit_jump *match; | |
4311 | /* bytes[0] represent the number of characters between 0 | |
4312 | and MAX_N_BYTES - 1, 255 represents any character. */ | |
4313 | pcre_uchar chars[MAX_N_CHARS * MAX_DIFF_CHARS]; | |
4314 | sljit_s32 offset; | |
4315 | pcre_uchar mask; | |
4316 | pcre_uchar *char_set, *char_set_end; | |
4317 | int i, max, from; | |
4318 | int range_right = -1, range_len; | |
4319 | sljit_u8 *update_table = NULL; | |
4320 | BOOL in_range; | |
4321 | sljit_u32 rec_count; | |
4322 | ||
4323 | for (i = 0; i < MAX_N_CHARS; i++) | |
4324 | chars[i * MAX_DIFF_CHARS] = 0; | |
4325 | ||
4326 | rec_count = 10000; | |
4327 | max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count); | |
4328 | ||
4329 | if (max < 1) | |
4330 | return FALSE; | |
4331 | ||
4332 | in_range = FALSE; | |
4333 | /* Prevent compiler "uninitialized" warning */ | |
4334 | from = 0; | |
4335 | range_len = 4 /* minimum length */ - 1; | |
4336 | for (i = 0; i <= max; i++) | |
4337 | { | |
4338 | if (in_range && (i - from) > range_len && (chars[(i - 1) * MAX_DIFF_CHARS] < 255)) | |
4339 | { | |
4340 | range_len = i - from; | |
4341 | range_right = i - 1; | |
4342 | } | |
4343 | ||
4344 | if (i < max && chars[i * MAX_DIFF_CHARS] < 255) | |
4345 | { | |
4346 | SLJIT_ASSERT(chars[i * MAX_DIFF_CHARS] > 0); | |
4347 | if (!in_range) | |
4348 | { | |
4349 | in_range = TRUE; | |
4350 | from = i; | |
4351 | } | |
4352 | } | |
4353 | else | |
4354 | in_range = FALSE; | |
4355 | } | |
4356 | ||
4357 | if (range_right >= 0) | |
4358 | { | |
4359 | update_table = (sljit_u8 *)allocate_read_only_data(common, 256); | |
4360 | if (update_table == NULL) | |
4361 | return TRUE; | |
4362 | memset(update_table, IN_UCHARS(range_len), 256); | |
4363 | ||
4364 | for (i = 0; i < range_len; i++) | |
4365 | { | |
4366 | char_set = chars + ((range_right - i) * MAX_DIFF_CHARS); | |
4367 | SLJIT_ASSERT(char_set[0] > 0 && char_set[0] < 255); | |
4368 | char_set_end = char_set + char_set[0]; | |
4369 | char_set++; | |
4370 | while (char_set <= char_set_end) | |
4371 | { | |
4372 | if (update_table[(*char_set) & 0xff] > IN_UCHARS(i)) | |
4373 | update_table[(*char_set) & 0xff] = IN_UCHARS(i); | |
4374 | char_set++; | |
4375 | } | |
4376 | } | |
4377 | } | |
4378 | ||
4379 | offset = -1; | |
4380 | /* Scan forward. */ | |
4381 | for (i = 0; i < max; i++) | |
4382 | { | |
4383 | if (offset == -1) | |
4384 | { | |
4385 | if (chars[i * MAX_DIFF_CHARS] <= 2) | |
4386 | offset = i; | |
4387 | } | |
4388 | else if (chars[offset * MAX_DIFF_CHARS] == 2 && chars[i * MAX_DIFF_CHARS] <= 2) | |
4389 | { | |
4390 | if (chars[i * MAX_DIFF_CHARS] == 1) | |
4391 | offset = i; | |
4392 | else | |
4393 | { | |
4394 | mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2]; | |
4395 | if (!is_powerof2(mask)) | |
4396 | { | |
4397 | mask = chars[i * MAX_DIFF_CHARS + 1] ^ chars[i * MAX_DIFF_CHARS + 2]; | |
4398 | if (is_powerof2(mask)) | |
4399 | offset = i; | |
4400 | } | |
4401 | } | |
4402 | } | |
4403 | } | |
4404 | ||
4405 | if (range_right < 0) | |
4406 | { | |
4407 | if (offset < 0) | |
4408 | return FALSE; | return FALSE; |
4409 | SLJIT_ASSERT(chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2); | |
4410 | /* Works regardless the value is 1 or 2. */ | |
4411 | mask = chars[offset * MAX_DIFF_CHARS + chars[offset * MAX_DIFF_CHARS]]; | |
4412 | fast_forward_first_char2(common, chars[offset * MAX_DIFF_CHARS + 1], mask, offset); | |
4413 | return TRUE; | |
4414 | } | |
4415 | ||
4416 | if (range_right == offset) | |
4417 | offset = -1; | |
4418 | ||
4419 | if (firstline) | SLJIT_ASSERT(offset == -1 || (chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2)); |
4420 | ||
4421 | max -= 1; | |
4422 | SLJIT_ASSERT(max > 0); | |
4423 | if (common->match_end_ptr != 0) | |
4424 | { | { |
4425 | SLJIT_ASSERT(common->first_line_end != 0); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); |
4426 | OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); | OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); |
4427 | OP2(SLJIT_SUB, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, SLJIT_IMM, IN_UCHARS((location >> 1) - 1)); | OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); |
4428 | quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP1, 0); | |
4429 | OP1(SLJIT_MOV, STR_END, 0, TMP1, 0); | |
4430 | JUMPHERE(quit); | |
4431 | } | } |
4432 | else | else |
4433 | OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS((location >> 1) - 1)); | OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); |
4434 | ||
4435 | SLJIT_ASSERT(range_right >= 0); | |
4436 | ||
4437 | #if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) | |
4438 | OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table); | |
4439 | #endif | |
4440 | ||
4441 | start = LABEL(); | start = LABEL(); |
4442 | quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
4443 | ||
4444 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | #if defined COMPILE_PCRE8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) |
4445 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right)); |
4446 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | #else |
4447 | if (chars[1] != 0) | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1); |
4448 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[1]); | #endif |
4449 | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[0], start); | |
4450 | if (location > 2 * 2) | #if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) |
4451 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0); |
4452 | if (chars[3] != 0) | #else |
4453 | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, chars[3]); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table); |
4454 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, chars[2], start); | #endif |
4455 | if (location > 2 * 2) | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
4456 | { | CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start); |
4457 | if (chars[5] != 0) | |
4458 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[5]); | if (offset >= 0) |
4459 | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[4], start); | { |
4460 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offset)); | |
4461 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
4462 | ||
4463 | if (chars[offset * MAX_DIFF_CHARS] == 1) | |
4464 | CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1], start); | |
4465 | else | |
4466 | { | |
4467 | mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2]; | |
4468 | if (is_powerof2(mask)) | |
4469 | { | |
4470 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask); | |
4471 | CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1] | mask, start); | |
4472 | } | |
4473 | else | |
4474 | { | |
4475 | match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1]); | |
4476 | CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 2], start); | |
4477 | JUMPHERE(match); | |
4478 | } | |
4479 | } | |
4480 | } | |
4481 | ||
4482 | #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 | |
4483 | if (common->utf && offset != 0) | |
4484 | { | |
4485 | if (offset < 0) | |
4486 | { | |
4487 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | |
4488 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
4489 | } | |
4490 | else | |
4491 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); | |
4492 | #if defined COMPILE_PCRE8 | |
4493 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); | |
4494 | CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, start); | |
4495 | #elif defined COMPILE_PCRE16 | |
4496 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | |
4497 | CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, start); | |
4498 | #else | |
4499 | #error "Unknown code width" | |
4500 | #endif | |
4501 | if (offset < 0) | |
4502 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
4503 | } | } |
4504 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | #endif |
4505 | ||
4506 | if (offset >= 0) | |
4507 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
4508 | ||
4509 | JUMPHERE(quit); | JUMPHERE(quit); |
4510 | ||
4511 | if (firstline) | if (common->match_end_ptr != 0) |
4512 | { | |
4513 | if (range_right >= 0) | |
4514 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); | |
4515 | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); |
4516 | if (range_right >= 0) | |
4517 | { | |
4518 | quit = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP1, 0); | |
4519 | OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); | |
4520 | JUMPHERE(quit); | |
4521 | } | |
4522 | } | |
4523 | else | else |
4524 | OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS((location >> 1) - 1)); | OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); |
4525 | return TRUE; | return TRUE; |
4526 | } | } |
4527 | ||
4528 | #undef MAX_N_CHARS | #undef MAX_N_CHARS |
4529 | #undef MAX_DIFF_CHARS | |
4530 | ||
4531 | static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline) | static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless) |
4532 | { | { |
4533 | DEFINE_COMPILER; | pcre_uchar oc; |
struct sljit_label *start; | ||
struct sljit_jump *quit; | ||
struct sljit_jump *found; | ||
pcre_uchar oc, bit; | ||
if (firstline) | ||
{ | ||
SLJIT_ASSERT(common->first_line_end != 0); | ||
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); | ||
OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); | ||
} | ||
start = LABEL(); | ||
quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | ||
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | ||
4534 | ||
4535 | oc = first_char; | oc = first_char; |
4536 | if (caseless) | if (caseless) |
4537 | { | { |
4538 | oc = TABLE_GET(first_char, common->fcc, first_char); | oc = TABLE_GET(first_char, common->fcc, first_char); |
4539 | #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) | #if defined SUPPORT_UTF && !defined COMPILE_PCRE8 |
4540 | if (first_char > 127 && common->utf) | if (first_char > 127 && common->utf) |
4541 | oc = UCD_OTHERCASE(first_char); | oc = UCD_OTHERCASE(first_char); |
4542 | #endif | #endif |
4543 | } | } |
if (first_char == oc) | ||
found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, first_char); | ||
else | ||
{ | ||
bit = first_char ^ oc; | ||
if (is_powerof2(bit)) | ||
{ | ||
OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit); | ||
found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit); | ||
} | ||
else | ||
{ | ||
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char); | ||
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); | ||
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc); | ||
OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); | ||
found = JUMP(SLJIT_C_NOT_ZERO); | ||
} | ||
} | ||
4544 | ||
4545 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | fast_forward_first_char2(common, first_char, oc, 0); |
JUMPTO(SLJIT_JUMP, start); | ||
JUMPHERE(found); | ||
JUMPHERE(quit); | ||
if (firstline) | ||
OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); | ||
4546 | } | } |
4547 | ||
4548 | static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline) | static SLJIT_INLINE void fast_forward_newline(compiler_common *common) |
4549 | { | { |
4550 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4551 | struct sljit_label *loop; | struct sljit_label *loop; |
# | Line 3118 struct sljit_jump *foundcr = NULL; | Line 4556 struct sljit_jump *foundcr = NULL; |
4556 | struct sljit_jump *notfoundnl; | struct sljit_jump *notfoundnl; |
4557 | jump_list *newline = NULL; | jump_list *newline = NULL; |
4558 | ||
4559 | if (firstline) | if (common->match_end_ptr != 0) |
4560 | { | { |
SLJIT_ASSERT(common->first_line_end != 0); | ||
4561 | OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); | OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); |
4562 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); |
4563 | } | } |
4564 | ||
4565 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
4566 | { | { |
4567 | lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
4568 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
4569 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); |
4570 | 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)); |
4571 | firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0); | firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); |
4572 | ||
4573 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); |
4574 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); |
4575 | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_GREATER_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER_EQUAL); |
4576 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
4577 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT); |
4578 | #endif | #endif |
# | Line 3143 if (common->nltype == NLTYPE_FIXED && co | Line 4580 if (common->nltype == NLTYPE_FIXED && co |
4580 | ||
4581 | loop = LABEL(); | loop = LABEL(); |
4582 | 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)); |
4583 | quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
4584 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); |
4585 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); |
4586 | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); | CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); |
4587 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); | CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); |
4588 | ||
4589 | JUMPHERE(quit); | JUMPHERE(quit); |
4590 | JUMPHERE(firstchar); | JUMPHERE(firstchar); |
4591 | JUMPHERE(lastchar); | JUMPHERE(lastchar); |
4592 | ||
4593 | if (firstline) | if (common->match_end_ptr != 0) |
4594 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); |
4595 | return; | return; |
4596 | } | } |
4597 | ||
4598 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
4599 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); |
4600 | firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0); | firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); |
4601 | skip_char_back(common); | skip_char_back(common); |
4602 | ||
4603 | loop = LABEL(); | loop = LABEL(); |
4604 | read_char(common); | common->ff_newline_shortcut = loop; |
4605 | lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | |
4606 | read_char_range(common, common->nlmin, common->nlmax, TRUE); | |
4607 | lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | |
4608 | if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) | if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) |
4609 | foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); | foundcr = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); |
4610 | check_newlinechar(common, common->nltype, &newline, FALSE); | check_newlinechar(common, common->nltype, &newline, FALSE); |
4611 | set_jumps(newline, loop); | set_jumps(newline, loop); |
4612 | ||
# | Line 3175 if (common->nltype == NLTYPE_ANY || comm | Line 4614 if (common->nltype == NLTYPE_ANY || comm |
4614 | { | { |
4615 | quit = JUMP(SLJIT_JUMP); | quit = JUMP(SLJIT_JUMP); |
4616 | JUMPHERE(foundcr); | JUMPHERE(foundcr); |
4617 | notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
4618 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
4619 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); |
4620 | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); |
4621 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
4622 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); |
4623 | #endif | #endif |
# | Line 3189 if (common->nltype == NLTYPE_ANY || comm | Line 4628 if (common->nltype == NLTYPE_ANY || comm |
4628 | JUMPHERE(lastchar); | JUMPHERE(lastchar); |
4629 | JUMPHERE(firstchar); | JUMPHERE(firstchar); |
4630 | ||
4631 | if (firstline) | if (common->match_end_ptr != 0) |
4632 | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); |
4633 | } | } |
4634 | ||
4635 | static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, jump_list **backtracks); | static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks); |
4636 | ||
4637 | static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline) | static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_u8 *start_bits) |
4638 | { | { |
4639 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4640 | struct sljit_label *start; | struct sljit_label *start; |
4641 | struct sljit_jump *quit; | struct sljit_jump *quit; |
4642 | struct sljit_jump *found = NULL; | struct sljit_jump *found = NULL; |
4643 | jump_list *matches = NULL; | jump_list *matches = NULL; |
pcre_uint8 inverted_start_bits[32]; | ||
int i; | ||
4644 | #ifndef COMPILE_PCRE8 | #ifndef COMPILE_PCRE8 |
4645 | struct sljit_jump *jump; | struct sljit_jump *jump; |
4646 | #endif | #endif |
4647 | ||
4648 | for (i = 0; i < 32; ++i) | if (common->match_end_ptr != 0) |
inverted_start_bits[i] = ~(((pcre_uint8*)start_bits)[i]); | ||
if (firstline) | ||
4649 | { | { |
SLJIT_ASSERT(common->first_line_end != 0); | ||
4650 | OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0); | OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0); |
4651 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); |
4652 | } | } |
4653 | ||
4654 | start = LABEL(); | start = LABEL(); |
4655 | quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
4656 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
4657 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
4658 | if (common->utf) | if (common->utf) |
4659 | OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); | OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); |
4660 | #endif | #endif |
4661 | ||
4662 | if (!check_class_ranges(common, inverted_start_bits, (inverted_start_bits[31] & 0x80) != 0, &matches)) | if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE, &matches)) |
4663 | { | { |
4664 | #ifndef COMPILE_PCRE8 | #ifndef COMPILE_PCRE8 |
4665 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 255); |
4666 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255); |
4667 | JUMPHERE(jump); | JUMPHERE(jump); |
4668 | #endif | #endif |
4669 | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); |
4670 | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); |
4671 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits); |
4672 | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); |
4673 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); |
4674 | found = JUMP(SLJIT_C_NOT_ZERO); | found = JUMP(SLJIT_NOT_ZERO); |
4675 | } | } |
4676 | ||
4677 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
# | Line 3250 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, S | Line 4683 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, S |
4683 | #if defined COMPILE_PCRE8 | #if defined COMPILE_PCRE8 |
4684 | if (common->utf) | if (common->utf) |
4685 | { | { |
4686 | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); | CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); |
4687 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); |
4688 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
4689 | } | } |
4690 | #elif defined COMPILE_PCRE16 | #elif defined COMPILE_PCRE16 |
4691 | if (common->utf) | if (common->utf) |
4692 | { | { |
4693 | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); | CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); |
4694 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); |
4695 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); |
4696 | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); |
4697 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
4698 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
4699 | } | } |
# | Line 3273 if (matches != NULL) | Line 4706 if (matches != NULL) |
4706 | set_jumps(matches, LABEL()); | set_jumps(matches, LABEL()); |
4707 | JUMPHERE(quit); | JUMPHERE(quit); |
4708 | ||
4709 | if (firstline) | if (common->match_end_ptr != 0) |
4710 | OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0); | OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0); |
4711 | } | } |
4712 | ||
# | Line 3289 struct sljit_jump *notfound; | Line 4722 struct sljit_jump *notfound; |
4722 | pcre_uint32 oc, bit; | pcre_uint32 oc, bit; |
4723 | ||
4724 | SLJIT_ASSERT(common->req_char_ptr != 0); | SLJIT_ASSERT(common->req_char_ptr != 0); |
4725 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr); |
4726 | OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX); | OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX); |
4727 | toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0); | toolong = CMP(SLJIT_LESS, TMP1, 0, STR_END, 0); |
4728 | alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0); | alreadyfound = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0); |
4729 | ||
4730 | if (has_firstchar) | if (has_firstchar) |
4731 | OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
# | Line 3300 else | Line 4733 else |
4733 | OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0); | OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0); |
4734 | ||
4735 | loop = LABEL(); | loop = LABEL(); |
4736 | notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0); | notfound = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0); |
4737 | ||
4738 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0); |
4739 | oc = req_char; | oc = req_char; |
# | Line 3313 if (caseless) | Line 4746 if (caseless) |
4746 | #endif | #endif |
4747 | } | } |
4748 | if (req_char == oc) | if (req_char == oc) |
4749 | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char); | found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char); |
4750 | else | else |
4751 | { | { |
4752 | bit = req_char ^ oc; | bit = req_char ^ oc; |
4753 | if (is_powerof2(bit)) | if (is_powerof2(bit)) |
4754 | { | { |
4755 | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit); | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit); |
4756 | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit); | found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit); |
4757 | } | } |
4758 | else | else |
4759 | { | { |
4760 | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char); | found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char); |
4761 | foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc); | foundoc = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, oc); |
4762 | } | } |
4763 | } | } |
4764 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); |
# | Line 3334 JUMPTO(SLJIT_JUMP, loop); | Line 4767 JUMPTO(SLJIT_JUMP, loop); |
4767 | JUMPHERE(found); | JUMPHERE(found); |
4768 | if (foundoc) | if (foundoc) |
4769 | JUMPHERE(foundoc); | JUMPHERE(foundoc); |
4770 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, TMP1, 0); |
4771 | JUMPHERE(alreadyfound); | JUMPHERE(alreadyfound); |
4772 | JUMPHERE(toolong); | JUMPHERE(toolong); |
4773 | return notfound; | return notfound; |
# | Line 3354 GET_LOCAL_BASE(TMP3, 0, 0); | Line 4787 GET_LOCAL_BASE(TMP3, 0, 0); |
4787 | mainloop = LABEL(); | mainloop = LABEL(); |
4788 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); |
4789 | OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0); | OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0); |
4790 | jump = JUMP(SLJIT_C_SIG_LESS_EQUAL); | jump = JUMP(SLJIT_SIG_LESS_EQUAL); |
4791 | ||
4792 | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); |
4793 | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw)); | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw)); |
# | Line 3363 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_I | Line 4796 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_I |
4796 | JUMPTO(SLJIT_JUMP, mainloop); | JUMPTO(SLJIT_JUMP, mainloop); |
4797 | ||
4798 | JUMPHERE(jump); | JUMPHERE(jump); |
4799 | jump = JUMP(SLJIT_C_SIG_LESS); | jump = JUMP(SLJIT_SIG_LESS); |
4800 | /* End of dropping frames. */ | /* End of dropping frames. */ |
4801 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
4802 | ||
# | Line 3386 struct sljit_jump *jump; | Line 4819 struct sljit_jump *jump; |
4819 | ||
4820 | SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); | SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); |
4821 | ||
4822 | sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); |
4823 | /* Get type of the previous char, and put it to LOCALS1. */ | /* Get type of the previous char, and put it to LOCALS1. */ |
4824 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
4825 | 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)); |
4826 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, SLJIT_IMM, 0); |
4827 | skipread = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); | skipread = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP1, 0); |
4828 | skip_char_back(common); | skip_char_back(common); |
4829 | check_start_used_ptr(common); | check_start_used_ptr(common); |
4830 | read_char(common); | read_char(common); |
# | Line 3401 read_char(common); | Line 4834 read_char(common); |
4834 | if (common->use_ucp) | if (common->use_ucp) |
4835 | { | { |
4836 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); |
4837 | jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); | jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); |
4838 | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); |
4839 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); |
4840 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); |
4841 | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); |
4842 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); |
4843 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); |
4844 | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); |
4845 | JUMPHERE(jump); | JUMPHERE(jump); |
4846 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0); |
4847 | } | } |
4848 | else | else |
4849 | #endif | #endif |
4850 | { | { |
4851 | #ifndef COMPILE_PCRE8 | #ifndef COMPILE_PCRE8 |
4852 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); |
4853 | #elif defined SUPPORT_UTF | #elif defined SUPPORT_UTF |
4854 | /* Here LOCALS1 has already been zeroed. */ | /* Here LOCALS1 has already been zeroed. */ |
4855 | jump = NULL; | jump = NULL; |
4856 | if (common->utf) | if (common->utf) |
4857 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); |
4858 | #endif /* COMPILE_PCRE8 */ | #endif /* COMPILE_PCRE8 */ |
4859 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes); | OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes); |
4860 | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */); | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */); |
4861 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
4862 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0); |
4863 | #ifndef COMPILE_PCRE8 | #ifndef COMPILE_PCRE8 |
4864 | JUMPHERE(jump); | JUMPHERE(jump); |
4865 | #elif defined SUPPORT_UTF | #elif defined SUPPORT_UTF |
# | Line 3438 JUMPHERE(skipread); | Line 4871 JUMPHERE(skipread); |
4871 | ||
4872 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
4873 | check_str_end(common, &skipread_list); | check_str_end(common, &skipread_list); |
4874 | peek_char(common); | peek_char(common, READ_CHAR_MAX); |
4875 | ||
4876 | /* Testing char type. This is a code duplication. */ | /* Testing char type. This is a code duplication. */ |
4877 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
4878 | if (common->use_ucp) | if (common->use_ucp) |
4879 | { | { |
4880 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); |
4881 | jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); | jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); |
4882 | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); |
4883 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); |
4884 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); |
4885 | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); |
4886 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); |
4887 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); |
4888 | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); |
4889 | JUMPHERE(jump); | JUMPHERE(jump); |
4890 | } | } |
4891 | else | else |
# | Line 3461 else | Line 4894 else |
4894 | #ifndef COMPILE_PCRE8 | #ifndef COMPILE_PCRE8 |
4895 | /* TMP2 may be destroyed by peek_char. */ | /* TMP2 may be destroyed by peek_char. */ |
4896 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
4897 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); |
4898 | #elif defined SUPPORT_UTF | #elif defined SUPPORT_UTF |
4899 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
4900 | jump = NULL; | jump = NULL; |
4901 | if (common->utf) | if (common->utf) |
4902 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); |
4903 | #endif | #endif |
4904 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes); | OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes); |
4905 | OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */); | OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */); |
4906 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); |
4907 | #ifndef COMPILE_PCRE8 | #ifndef COMPILE_PCRE8 |
# | Line 3480 else | Line 4913 else |
4913 | } | } |
4914 | set_jumps(skipread_list, LABEL()); | set_jumps(skipread_list, LABEL()); |
4915 | ||
4916 | 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_SP), LOCALS1); |
4917 | sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); |
4918 | } | } |
4919 | ||
4920 | /* | static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks) |
range format: | ||
ranges[0] = length of the range (max MAX_RANGE_SIZE, -1 means invalid range). | ||
ranges[1] = first bit (0 or 1) | ||
ranges[2-length] = position of the bit change (when the current bit is not equal to the previous) | ||
*/ | ||
static BOOL check_ranges(compiler_common *common, int *ranges, jump_list **backtracks, BOOL readch) | ||
4921 | { | { |
4922 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4923 | struct sljit_jump *jump; | int ranges[MAX_RANGE_SIZE]; |
if (ranges[0] < 0) | ||
return FALSE; | ||
switch(ranges[0]) | ||
{ | ||
case 1: | ||
if (readch) | ||
read_char(common); | ||
add_jump(compiler, backtracks, CMP(ranges[1] == 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2])); | ||
return TRUE; | ||
case 2: | ||
if (readch) | ||
read_char(common); | ||
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]); | ||
add_jump(compiler, backtracks, CMP(ranges[1] != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2])); | ||
return TRUE; | ||
case 4: | ||
if (ranges[2] + 1 == ranges[3] && ranges[4] + 1 == ranges[5]) | ||
{ | ||
if (readch) | ||
read_char(common); | ||
if (ranges[1] != 0) | ||
{ | ||
add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2])); | ||
add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[4])); | ||
} | ||
else | ||
{ | ||
jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]); | ||
add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[4])); | ||
JUMPHERE(jump); | ||
} | ||
return TRUE; | ||
} | ||
if ((ranges[3] - ranges[2]) == (ranges[5] - ranges[4]) && is_powerof2(ranges[4] - ranges[2])) | ||
{ | ||
if (readch) | ||
read_char(common); | ||
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[4] - ranges[2]); | ||
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[4]); | ||
add_jump(compiler, backtracks, CMP(ranges[1] != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[5] - ranges[4])); | ||
return TRUE; | ||
} | ||
return FALSE; | ||
default: | ||
return FALSE; | ||
} | ||
} | ||
static void get_ctype_ranges(compiler_common *common, int flag, int *ranges) | ||
{ | ||
int i, bit, length; | ||
const pcre_uint8 *ctypes = (const pcre_uint8*)common->ctypes; | ||
bit = ctypes[0] & flag; | ||
ranges[0] = -1; | ||
ranges[1] = bit != 0 ? 1 : 0; | ||
length = 0; | ||
for (i = 1; i < 256; i++) | ||
if ((ctypes[i] & flag) != bit) | ||
{ | ||
if (length >= MAX_RANGE_SIZE) | ||
return; | ||
ranges[2 + length] = i; | ||
length++; | ||
bit ^= flag; | ||
} | ||
if (bit != 0) | ||
{ | ||
if (length >= MAX_RANGE_SIZE) | ||
return; | ||
ranges[2 + length] = 256; | ||
length++; | ||
} | ||
ranges[0] = length; | ||
} | ||
static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, jump_list **backtracks) | ||
{ | ||
int ranges[2 + MAX_RANGE_SIZE]; | ||
4924 | pcre_uint8 bit, cbit, all; | pcre_uint8 bit, cbit, all; |
4925 | int i, byte, length = 0; | int i, byte, length = 0; |
4926 | ||
4927 | bit = bits[0] & 0x1; | bit = bits[0] & 0x1; |
4928 | ranges[1] = bit; | /* All bits will be zero or one (since bit is zero or one). */ |
/* Can be 0 or 255. */ | ||
4929 | all = -bit; | all = -bit; |
4930 | ||
4931 | for (i = 0; i < 256; ) | for (i = 0; i < 256; ) |
# | Line 3602 for (i = 0; i < 256; ) | Line 4940 for (i = 0; i < 256; ) |
4940 | { | { |
4941 | if (length >= MA |