Parent Directory
|
Revision Log
|
Patch
| revision 850 by zherczeg, Wed Jan 4 17:29:11 2012 UTC | revision 970 by zherczeg, Sun May 27 05:28:19 2012 UTC | |
|---|---|---|
| # | Line 82 The code generator follows the recursive | Line 82 The code generator follows the recursive |
| 82 | expressions. The basic blocks of regular expressions are condition checkers | expressions. The basic blocks of regular expressions are condition checkers |
| 83 | whose execute different commands depending on the result of the condition check. | whose execute different commands depending on the result of the condition check. |
| 84 | The relationship between the operators can be horizontal (concatenation) and | The relationship between the operators can be horizontal (concatenation) and |
| 85 | vertical (sub-expression) (See struct fallback_common for more details). | vertical (sub-expression) (See struct backtrack_common for more details). |
| 86 | ||
| 87 | 'ab' - 'a' and 'b' regexps are concatenated | 'ab' - 'a' and 'b' regexps are concatenated |
| 88 | 'a+' - 'a' is the sub-expression of the '+' operator | 'a+' - 'a' is the sub-expression of the '+' operator |
| 89 | ||
| 90 | The condition checkers are boolean (true/false) checkers. Machine code is generated | The condition checkers are boolean (true/false) checkers. Machine code is generated |
| 91 | for the checker itself and for the actions depending on the result of the checker. | for the checker itself and for the actions depending on the result of the checker. |
| 92 | The 'true' case is called as the hot path (expected path), and the other is called as | The 'true' case is called as the try path (expected path), and the other is called as |
| 93 | the 'fallback' path. Branch instructions are expesive for all CPUs, so we avoid taken | the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken |
| 94 | branches on the hot path. | branches on the try path. |
| 95 | ||
| 96 | Greedy star operator (*) : | Greedy star operator (*) : |
| 97 | Hot path: match happens. | Try path: match happens. |
| 98 | Fallback path: match failed. | Backtrack path: match failed. |
| 99 | Non-greedy star operator (*?) : | Non-greedy star operator (*?) : |
| 100 | Hot path: no need to perform a match. | Try path: no need to perform a match. |
| 101 | Fallback path: match is required. | Backtrack path: match is required. |
| 102 | ||
| 103 | The following example shows how the code generated for a capturing bracket | The following example shows how the code generated for a capturing bracket |
| 104 | with two alternatives. Let A, B, C, D are arbirary regular expressions, and | with two alternatives. Let A, B, C, D are arbirary regular expressions, and |
| # | Line 108 we have the following regular expression | Line 108 we have the following regular expression |
| 108 | ||
| 109 | The generated code will be the following: | The generated code will be the following: |
| 110 | ||
| 111 | A hot path | A try path |
| 112 | '(' hot path (pushing arguments to the stack) | '(' try path (pushing arguments to the stack) |
| 113 | B hot path | B try path |
| 114 | ')' hot path (pushing arguments to the stack) | ')' try path (pushing arguments to the stack) |
| 115 | D hot path | D try path |
| 116 | return with successful match | return with successful match |
| 117 | ||
| 118 | D fallback path | D backtrack path |
| 119 | ')' fallback path (If we arrived from "C" jump to the fallback of "C") | ')' backtrack path (If we arrived from "C" jump to the backtrack of "C") |
| 120 | B fallback path | B backtrack path |
| 121 | C expected path | C expected path |
| 122 | jump to D hot path | jump to D try path |
| 123 | C fallback path | C backtrack path |
| 124 | A fallback path | A backtrack path |
| 125 | ||
| 126 | Notice, that the order of fallback code paths are the opposite of the fast | Notice, that the order of backtrack code paths are the opposite of the fast |
| 127 | code paths. In this way the topmost value on the stack is always belong | code paths. In this way the topmost value on the stack is always belong |
| 128 | to the current fallback code path. The fallback code path must check | to the current backtrack code path. The backtrack path must check |
| 129 | whether there is a next alternative. If so, it needs to jump back to | whether there is a next alternative. If so, it needs to jump back to |
| 130 | the hot path eventually. Otherwise it needs to clear out its own stack | the try path eventually. Otherwise it needs to clear out its own stack |
| 131 | frame and continue the execution on the fallback code paths. | frame and continue the execution on the backtrack code paths. |
| 132 | */ | */ |
| 133 | ||
| 134 | /* | /* |
| 135 | Saved stack frames: | Saved stack frames: |
| 136 | ||
| 137 | Atomic blocks and asserts require reloading the values of local variables | Atomic blocks and asserts require reloading the values of local variables |
| 138 | when the fallback mechanism performed. Because of OP_RECURSE, the locals | when the backtrack mechanism performed. Because of OP_RECURSE, the locals |
| 139 | are not necessarly known in compile time, thus we need a dynamic restore | are not necessarly known in compile time, thus we need a dynamic restore |
| 140 | mechanism. | mechanism. |
| 141 | ||
| # | Line 152 typedef struct jit_arguments { | Line 152 typedef struct jit_arguments { |
| 152 | const pcre_uchar *begin; | const pcre_uchar *begin; |
| 153 | const pcre_uchar *end; | const pcre_uchar *end; |
| 154 | int *offsets; | int *offsets; |
| 155 | pcre_uchar *ptr; | pcre_uchar *uchar_ptr; |
| 156 | pcre_uchar *mark_ptr; | |
| 157 | /* Everything else after. */ | /* Everything else after. */ |
| 158 | int offsetcount; | int offsetcount; |
| 159 | int calllimit; | int calllimit; |
| # | Line 162 typedef struct jit_arguments { | Line 163 typedef struct jit_arguments { |
| 163 | pcre_uint8 notempty_atstart; | pcre_uint8 notempty_atstart; |
| 164 | } jit_arguments; | } jit_arguments; |
| 165 | ||
| 166 | typedef struct executable_function { | typedef struct executable_functions { |
| 167 | void *executable_func; | void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES]; |
| 168 | pcre_jit_callback callback; | PUBL(jit_callback) callback; |
| 169 | void *userdata; | void *userdata; |
| 170 | sljit_uw executable_size; | sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES]; |
| 171 | } executable_function; | } executable_functions; |
| 172 | ||
| 173 | typedef struct jump_list { | typedef struct jump_list { |
| 174 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| # | Line 187 typedef struct stub_list { | Line 188 typedef struct stub_list { |
| 188 | typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); | typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); |
| 189 | ||
| 190 | /* The following structure is the key data type for the recursive | /* The following structure is the key data type for the recursive |
| 191 | code generator. It is allocated by compile_hotpath, and contains | code generator. It is allocated by compile_trypath, and contains |
| 192 | the aguments for compile_fallbackpath. Must be the first member | the aguments for compile_backtrackpath. Must be the first member |
| 193 | of its descendants. */ | of its descendants. */ |
| 194 | typedef struct fallback_common { | typedef struct backtrack_common { |
| 195 | /* Concatenation stack. */ | /* Concatenation stack. */ |
| 196 | struct fallback_common *prev; | struct backtrack_common *prev; |
| 197 | jump_list *nextfallbacks; | jump_list *nextbacktracks; |
| 198 | /* Internal stack (for component operators). */ | /* Internal stack (for component operators). */ |
| 199 | struct fallback_common *top; | struct backtrack_common *top; |
| 200 | jump_list *topfallbacks; | jump_list *topbacktracks; |
| 201 | /* Opcode pointer. */ | /* Opcode pointer. */ |
| 202 | pcre_uchar *cc; | pcre_uchar *cc; |
| 203 | } fallback_common; | } backtrack_common; |
| 204 | ||
| 205 | typedef struct assert_fallback { | typedef struct assert_backtrack { |
| 206 | fallback_common common; | backtrack_common common; |
| 207 | jump_list *condfailed; | jump_list *condfailed; |
| 208 | /* Less than 0 (-1) if a frame is not needed. */ | /* Less than 0 (-1) if a frame is not needed. */ |
| 209 | int framesize; | int framesize; |
| 210 | /* Points to our private memory word on the stack. */ | /* Points to our private memory word on the stack. */ |
| 211 | int localptr; | int localptr; |
| 212 | /* For iterators. */ | /* For iterators. */ |
| 213 | struct sljit_label *hotpath; | struct sljit_label *trypath; |
| 214 | } assert_fallback; | } assert_backtrack; |
| 215 | ||
| 216 | typedef struct bracket_fallback { | typedef struct bracket_backtrack { |
| 217 | fallback_common common; | backtrack_common common; |
| 218 | /* Where to coninue if an alternative is successfully matched. */ | /* Where to coninue if an alternative is successfully matched. */ |
| 219 | struct sljit_label *althotpath; | struct sljit_label *alttrypath; |
| 220 | /* For rmin and rmax iterators. */ | /* For rmin and rmax iterators. */ |
| 221 | struct sljit_label *recursivehotpath; | struct sljit_label *recursivetrypath; |
| 222 | /* For greedy ? operator. */ | /* For greedy ? operator. */ |
| 223 | struct sljit_label *zerohotpath; | struct sljit_label *zerotrypath; |
| 224 | /* Contains the branches of a failed condition. */ | /* Contains the branches of a failed condition. */ |
| 225 | union { | union { |
| 226 | /* Both for OP_COND, OP_SCOND. */ | /* Both for OP_COND, OP_SCOND. */ |
| 227 | jump_list *condfailed; | jump_list *condfailed; |
| 228 | assert_fallback *assert; | assert_backtrack *assert; |
| 229 | /* For OP_ONCE. -1 if not needed. */ | /* For OP_ONCE. -1 if not needed. */ |
| 230 | int framesize; | int framesize; |
| 231 | } u; | } u; |
| 232 | /* Points to our private memory word on the stack. */ | /* Points to our private memory word on the stack. */ |
| 233 | int localptr; | int localptr; |
| 234 | } bracket_fallback; | } bracket_backtrack; |
| 235 | ||
| 236 | typedef struct bracketpos_fallback { | typedef struct bracketpos_backtrack { |
| 237 | fallback_common common; | backtrack_common common; |
| 238 | /* Points to our private memory word on the stack. */ | /* Points to our private memory word on the stack. */ |
| 239 | int localptr; | int localptr; |
| 240 | /* Reverting stack is needed. */ | /* Reverting stack is needed. */ |
| 241 | int framesize; | int framesize; |
| 242 | /* Allocated stack size. */ | /* Allocated stack size. */ |
| 243 | int stacksize; | int stacksize; |
| 244 | } bracketpos_fallback; | } bracketpos_backtrack; |
| 245 | ||
| 246 | typedef struct braminzero_fallback { | typedef struct braminzero_backtrack { |
| 247 | fallback_common common; | backtrack_common common; |
| 248 | struct sljit_label *hotpath; | struct sljit_label *trypath; |
| 249 | } braminzero_fallback; | } braminzero_backtrack; |
| 250 | ||
| 251 | typedef struct iterator_fallback { | typedef struct iterator_backtrack { |
| 252 | fallback_common common; | backtrack_common common; |
| 253 | /* Next iteration. */ | /* Next iteration. */ |
| 254 | struct sljit_label *hotpath; | struct sljit_label *trypath; |
| 255 | } iterator_fallback; | } iterator_backtrack; |
| 256 | ||
| 257 | typedef struct recurse_entry { | typedef struct recurse_entry { |
| 258 | struct recurse_entry *next; | struct recurse_entry *next; |
| # | Line 263 typedef struct recurse_entry { | Line 264 typedef struct recurse_entry { |
| 264 | int start; | int start; |
| 265 | } recurse_entry; | } recurse_entry; |
| 266 | ||
| 267 | typedef struct recurse_fallback { | typedef struct recurse_backtrack { |
| 268 | fallback_common common; | backtrack_common common; |
| 269 | } recurse_fallback; | } recurse_backtrack; |
| 270 | ||
| 271 | typedef struct compiler_common { | typedef struct compiler_common { |
| 272 | struct sljit_compiler *compiler; | struct sljit_compiler *compiler; |
| 273 | pcre_uchar *start; | pcre_uchar *start; |
| 274 | int localsize; | |
| 275 | /* Opcode local area direct map. */ | |
| 276 | int *localptrs; | int *localptrs; |
| 277 | int cbraptr; | |
| 278 | /* OVector starting point. Must be divisible by 2. */ | |
| 279 | int ovector_start; | |
| 280 | /* Last known position of the requested byte. */ | |
| 281 | int req_char_ptr; | |
| 282 | /* Head of the last recursion. */ | |
| 283 | int recursive_head; | |
| 284 | /* First inspected character for partial matching. */ | |
| 285 | int start_used_ptr; | |
| 286 | /* Starting pointer for partial soft matches. */ | |
| 287 | int hit_start; | |
| 288 | /* End pointer of the first line. */ | |
| 289 | int first_line_end; | |
| 290 | /* Points to the marked string. */ | |
| 291 | int mark_ptr; | |
| 292 | ||
| 293 | /* Other */ | |
| 294 | const pcre_uint8 *fcc; | const pcre_uint8 *fcc; |
| 295 | sljit_w lcc; | sljit_w lcc; |
| 296 | int cbraptr; | int mode; |
| 297 | int nltype; | int nltype; |
| 298 | int newline; | int newline; |
| 299 | int bsr_nltype; | int bsr_nltype; |
| 300 | int endonly; | int endonly; |
| 301 | BOOL has_set_som; | |
| 302 | sljit_w ctypes; | sljit_w ctypes; |
| 303 | sljit_uw name_table; | sljit_uw name_table; |
| 304 | sljit_w name_count; | sljit_w name_count; |
| 305 | sljit_w name_entry_size; | sljit_w name_entry_size; |
| 306 | ||
| 307 | /* Labels and jump lists. */ | |
| 308 | struct sljit_label *partialmatchlabel; | |
| 309 | struct sljit_label *leavelabel; | |
| 310 | struct sljit_label *acceptlabel; | struct sljit_label *acceptlabel; |
| 311 | stub_list *stubs; | stub_list *stubs; |
| 312 | recurse_entry *entries; | recurse_entry *entries; |
| 313 | recurse_entry *currententry; | recurse_entry *currententry; |
| 314 | jump_list *partialmatch; | |
| 315 | jump_list *leave; | |
| 316 | jump_list *accept; | jump_list *accept; |
| 317 | jump_list *calllimit; | jump_list *calllimit; |
| 318 | jump_list *stackalloc; | jump_list *stackalloc; |
| # | Line 349 typedef struct compare_context { | Line 375 typedef struct compare_context { |
| 375 | ||
| 376 | enum { | enum { |
| 377 | frame_end = 0, | frame_end = 0, |
| 378 | frame_setstrbegin = -1 | frame_setstrbegin = -1, |
| 379 | frame_setmark = -2 | |
| 380 | }; | }; |
| 381 | ||
| 382 | /* Undefine sljit macros. */ | |
| 383 | #undef CMP | |
| 384 | ||
| 385 | /* Used for accessing the elements of the stack. */ | /* Used for accessing the elements of the stack. */ |
| 386 | #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w)) | #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w)) |
| 387 | ||
| 388 | #define TMP1 SLJIT_TEMPORARY_REG1 | #define TMP1 SLJIT_TEMPORARY_REG1 |
| 389 | #define TMP2 SLJIT_TEMPORARY_REG3 | #define TMP2 SLJIT_TEMPORARY_REG3 |
| 390 | #define TMP3 SLJIT_TEMPORARY_EREG2 | #define TMP3 SLJIT_TEMPORARY_EREG2 |
| 391 | #define STR_PTR SLJIT_GENERAL_REG1 | #define STR_PTR SLJIT_SAVED_REG1 |
| 392 | #define STR_END SLJIT_GENERAL_REG2 | #define STR_END SLJIT_SAVED_REG2 |
| 393 | #define STACK_TOP SLJIT_TEMPORARY_REG2 | #define STACK_TOP SLJIT_TEMPORARY_REG2 |
| 394 | #define STACK_LIMIT SLJIT_GENERAL_REG3 | #define STACK_LIMIT SLJIT_SAVED_REG3 |
| 395 | #define ARGUMENTS SLJIT_GENERAL_EREG1 | #define ARGUMENTS SLJIT_SAVED_EREG1 |
| 396 | #define CALL_COUNT SLJIT_GENERAL_EREG2 | #define CALL_COUNT SLJIT_SAVED_EREG2 |
| 397 | #define RETURN_ADDR SLJIT_TEMPORARY_EREG1 | #define RETURN_ADDR SLJIT_TEMPORARY_EREG1 |
| 398 | ||
| 399 | /* Locals layout. */ | /* Locals layout. */ |
| # | Line 373 enum { | Line 403 enum { |
| 403 | /* Two local variables for possessive quantifiers (char1 cannot use them). */ | /* Two local variables for possessive quantifiers (char1 cannot use them). */ |
| 404 | #define POSSESSIVE0 (2 * sizeof(sljit_w)) | #define POSSESSIVE0 (2 * sizeof(sljit_w)) |
| 405 | #define POSSESSIVE1 (3 * sizeof(sljit_w)) | #define POSSESSIVE1 (3 * sizeof(sljit_w)) |
| /* Head of the last recursion. */ | ||
| #define RECURSIVE_HEAD (4 * sizeof(sljit_w)) | ||
| 406 | /* Max limit of recursions. */ | /* Max limit of recursions. */ |
| 407 | #define CALL_LIMIT (5 * sizeof(sljit_w)) | #define CALL_LIMIT (4 * sizeof(sljit_w)) |
| /* Last known position of the requested byte. */ | ||
| #define REQ_CHAR_PTR (6 * sizeof(sljit_w)) | ||
| /* End pointer of the first line. */ | ||
| #define FIRSTLINE_END (7 * sizeof(sljit_w)) | ||
| 408 | /* The output vector is stored on the stack, and contains pointers | /* The output vector is stored on the stack, and contains pointers |
| 409 | to characters. The vector data is divided into two groups: the first | to characters. The vector data is divided into two groups: the first |
| 410 | group contains the start / end character pointers, and the second is | group contains the start / end character pointers, and the second is |
| 411 | 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. */ |
| 412 | #define OVECTOR_START (8 * sizeof(sljit_w)) | #define OVECTOR_START (common->ovector_start) |
| 413 | #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w)) | #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w)) |
| 414 | #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w)) | #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w)) |
| 415 | #define PRIV_DATA(cc) (common->localptrs[(cc) - common->start]) | #define PRIV_DATA(cc) (common->localptrs[(cc) - common->start]) |
| # | Line 423 the start pointers when the end of the c | Line 447 the start pointers when the end of the c |
| 447 | sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label)) | sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label)) |
| 448 | #define COND_VALUE(op, dst, dstw, type) \ | #define COND_VALUE(op, dst, dstw, type) \ |
| 449 | sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type)) | sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type)) |
| 450 | #define GET_LOCAL_BASE(dst, dstw, offset) \ | |
| 451 | sljit_get_local_base(compiler, (dst), (dstw), (offset)) | |
| 452 | ||
| 453 | static pcre_uchar* bracketend(pcre_uchar* cc) | static pcre_uchar* bracketend(pcre_uchar* cc) |
| 454 | { | { |
| # | Line 441 return cc; | Line 467 return cc; |
| 467 | init_frame | init_frame |
| 468 | get_localsize | get_localsize |
| 469 | copy_locals | copy_locals |
| 470 | compile_hotpath | compile_trypath |
| 471 | compile_fallbackpath | compile_backtrackpath |
| 472 | */ | */ |
| 473 | ||
| 474 | static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc) | static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc) |
| # | Line 494 switch(*cc) | Line 520 switch(*cc) |
| 520 | case OP_BRAZERO: | case OP_BRAZERO: |
| 521 | case OP_BRAMINZERO: | case OP_BRAMINZERO: |
| 522 | case OP_BRAPOSZERO: | case OP_BRAPOSZERO: |
| 523 | case OP_COMMIT: | |
| 524 | case OP_FAIL: | case OP_FAIL: |
| 525 | case OP_ACCEPT: | case OP_ACCEPT: |
| 526 | case OP_ASSERT_ACCEPT: | case OP_ASSERT_ACCEPT: |
| # | Line 632 switch(*cc) | Line 659 switch(*cc) |
| 659 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
| 660 | return cc + 1 + LINK_SIZE + IMM2_SIZE; | return cc + 1 + LINK_SIZE + IMM2_SIZE; |
| 661 | ||
| 662 | case OP_MARK: | |
| 663 | return cc + 1 + 2 + cc[1]; | |
| 664 | ||
| 665 | default: | default: |
| 666 | return NULL; | return NULL; |
| 667 | } | } |
| # | Line 646 while (cc < ccend) | Line 676 while (cc < ccend) |
| 676 | { | { |
| 677 | switch(*cc) | switch(*cc) |
| 678 | { | { |
| 679 | case OP_SET_SOM: | |
| 680 | common->has_set_som = TRUE; | |
| 681 | cc += 1; | |
| 682 | break; | |
| 683 | ||
| 684 | case OP_ASSERT: | case OP_ASSERT: |
| 685 | case OP_ASSERT_NOT: | case OP_ASSERT_NOT: |
| 686 | case OP_ASSERTBACK: | case OP_ASSERTBACK: |
| # | Line 674 while (cc < ccend) | Line 709 while (cc < ccend) |
| 709 | cc += 1 + LINK_SIZE; | cc += 1 + LINK_SIZE; |
| 710 | break; | break; |
| 711 | ||
| 712 | case OP_RECURSE: | |
| 713 | /* Set its value only once. */ | |
| 714 | if (common->recursive_head == 0) | |
| 715 | { | |
| 716 | common->recursive_head = common->ovector_start; | |
| 717 | common->ovector_start += sizeof(sljit_w); | |
| 718 | } | |
| 719 | cc += 1 + LINK_SIZE; | |
| 720 | break; | |
| 721 | ||
| 722 | case OP_MARK: | |
| 723 | if (common->mark_ptr == 0) | |
| 724 | { | |
| 725 | common->mark_ptr = common->ovector_start; | |
| 726 | common->ovector_start += sizeof(sljit_w); | |
| 727 | } | |
| 728 | cc += 1 + 2 + cc[1]; | |
| 729 | break; | |
| 730 | ||
| 731 | default: | default: |
| 732 | cc = next_opcode(common, cc); | cc = next_opcode(common, cc); |
| 733 | if (cc == NULL) | if (cc == NULL) |
| # | Line 739 static int get_framesize(compiler_common | Line 793 static int get_framesize(compiler_common |
| 793 | pcre_uchar *ccend = bracketend(cc); | pcre_uchar *ccend = bracketend(cc); |
| 794 | int length = 0; | int length = 0; |
| 795 | BOOL possessive = FALSE; | BOOL possessive = FALSE; |
| 796 | BOOL setsom_found = FALSE; | BOOL setsom_found = recursive; |
| 797 | BOOL setmark_found = recursive; | |
| 798 | ||
| 799 | if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) | if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) |
| 800 | { | { |
| # | Line 753 while (cc < ccend) | Line 808 while (cc < ccend) |
| 808 | switch(*cc) | switch(*cc) |
| 809 | { | { |
| 810 | case OP_SET_SOM: | case OP_SET_SOM: |
| 811 | case OP_RECURSE: | SLJIT_ASSERT(common->has_set_som); |
| 812 | if (!setsom_found) | if (!setsom_found) |
| 813 | { | { |
| 814 | length += 2; | length += 2; |
| 815 | setsom_found = TRUE; | setsom_found = TRUE; |
| 816 | } | } |
| 817 | cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE; | cc += 1; |
| 818 | break; | |
| 819 | ||
| 820 | case OP_MARK: | |
| 821 | SLJIT_ASSERT(common->mark_ptr != 0); | |
| 822 | if (!setmark_found) | |
| 823 | { | |
| 824 | length += 2; | |
| 825 | setmark_found = TRUE; | |
| 826 | } | |
| 827 | cc += 1 + 2 + cc[1]; | |
| 828 | break; | |
| 829 | ||
| 830 | case OP_RECURSE: | |
| 831 | if (common->has_set_som && !setsom_found) | |
| 832 | { | |
| 833 | length += 2; | |
| 834 | setsom_found = TRUE; | |
| 835 | } | |
| 836 | if (common->mark_ptr != 0 && !setmark_found) | |
| 837 | { | |
| 838 | length += 2; | |
| 839 | setmark_found = TRUE; | |
| 840 | } | |
| 841 | cc += 1 + LINK_SIZE; | |
| 842 | break; | break; |
| 843 | ||
| 844 | case OP_CBRA: | case OP_CBRA: |
| # | Line 789 static void init_frame(compiler_common * | Line 868 static void init_frame(compiler_common * |
| 868 | { | { |
| 869 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 870 | pcre_uchar *ccend = bracketend(cc); | pcre_uchar *ccend = bracketend(cc); |
| 871 | BOOL setsom_found = FALSE; | BOOL setsom_found = recursive; |
| 872 | BOOL setmark_found = recursive; | |
| 873 | int offset; | int offset; |
| 874 | ||
| 875 | /* >= 1 + shortest item size (2) */ | /* >= 1 + shortest item size (2) */ |
| 876 | SLJIT_UNUSED_ARG(stacktop); | |
| 877 | SLJIT_ASSERT(stackpos >= stacktop + 2); | SLJIT_ASSERT(stackpos >= stacktop + 2); |
| 878 | ||
| 879 | stackpos = STACK(stackpos); | stackpos = STACK(stackpos); |
| # | Line 803 while (cc < ccend) | Line 884 while (cc < ccend) |
| 884 | switch(*cc) | switch(*cc) |
| 885 | { | { |
| 886 | case OP_SET_SOM: | case OP_SET_SOM: |
| 887 | case OP_RECURSE: | SLJIT_ASSERT(common->has_set_som); |
| 888 | if (!setsom_found) | if (!setsom_found) |
| 889 | { | { |
| 890 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
| # | Line 813 while (cc < ccend) | Line 894 while (cc < ccend) |
| 894 | stackpos += (int)sizeof(sljit_w); | stackpos += (int)sizeof(sljit_w); |
| 895 | setsom_found = TRUE; | setsom_found = TRUE; |
| 896 | } | } |
| 897 | cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE; | cc += 1; |
| 898 | break; | |
| 899 | ||
| 900 | case OP_MARK: | |
| 901 | SLJIT_ASSERT(common->mark_ptr != 0); | |
| 902 | if (!setmark_found) | |
| 903 | { | |
| 904 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | |
| 905 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark); | |
| 906 | stackpos += (int)sizeof(sljit_w); | |
| 907 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | |
| 908 | stackpos += (int)sizeof(sljit_w); | |
| 909 | setmark_found = TRUE; | |
| 910 | } | |
| 911 | cc += 1 + 2 + cc[1]; | |
| 912 | break; | |
| 913 | ||
| 914 | case OP_RECURSE: | |
| 915 | if (common->has_set_som && !setsom_found) | |
| 916 | { | |
| 917 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | |
| 918 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin); | |
| 919 | stackpos += (int)sizeof(sljit_w); | |
| 920 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | |
| 921 | stackpos += (int)sizeof(sljit_w); | |
| 922 | setsom_found = TRUE; | |
| 923 | } | |
| 924 | if (common->mark_ptr != 0 && !setmark_found) | |
| 925 | { | |
| 926 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | |
| 927 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark); | |
| 928 | stackpos += (int)sizeof(sljit_w); | |
| 929 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | |
| 930 | stackpos += (int)sizeof(sljit_w); | |
| 931 | setmark_found = TRUE; | |
| 932 | } | |
| 933 | cc += 1 + LINK_SIZE; | |
| 934 | break; | break; |
| 935 | ||
| 936 | case OP_CBRA: | case OP_CBRA: |
| # | Line 940 while (status != end) | Line 1057 while (status != end) |
| 1057 | switch(status) | switch(status) |
| 1058 | { | { |
| 1059 | case start: | case start: |
| 1060 | SLJIT_ASSERT(save); | SLJIT_ASSERT(save && common->recursive_head != 0); |
| 1061 | count = 1; | count = 1; |
| 1062 | srcw[0] = RECURSIVE_HEAD; | srcw[0] = common->recursive_head; |
| 1063 | status = loop; | status = loop; |
| 1064 | break; | break; |
| 1065 | ||
| # | Line 1201 struct sljit_label *loop; | Line 1318 struct sljit_label *loop; |
| 1318 | int i; | int i; |
| 1319 | /* At this point we can freely use all temporary registers. */ | /* At this point we can freely use all temporary registers. */ |
| 1320 | /* TMP1 returns with begin - 1. */ | /* TMP1 returns with begin - 1. */ |
| 1321 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); |
| 1322 | if (length < 8) | if (length < 8) |
| 1323 | { | { |
| 1324 | for (i = 0; i < length; i++) | for (i = 0; i < length; i++) |
| # | Line 1209 if (length < 8) | Line 1326 if (length < 8) |
| 1326 | } | } |
| 1327 | else | else |
| 1328 | { | { |
| 1329 | OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START - sizeof(sljit_w)); | GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, OVECTOR_START - sizeof(sljit_w)); |
| 1330 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length); |
| 1331 | loop = LABEL(); | loop = LABEL(); |
| 1332 | OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0); | OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0); |
| # | Line 1225 struct sljit_label *loop; | Line 1342 struct sljit_label *loop; |
| 1342 | struct sljit_jump *earlyexit; | struct sljit_jump *earlyexit; |
| 1343 | ||
| 1344 | /* At this point we can freely use all registers. */ | /* At this point we can freely use all registers. */ |
| 1345 | OP1(SLJIT_MOV, SLJIT_GENERAL_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); | OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
| 1346 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0); |
| 1347 | ||
| 1348 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0); |
| 1349 | if (common->mark_ptr != 0) | |
| 1350 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | |
| 1351 | OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount)); | OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount)); |
| 1352 | if (common->mark_ptr != 0) | |
| 1353 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_TEMPORARY_REG3, 0); | |
| 1354 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); |
| 1355 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); |
| 1356 | OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START); | GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START); |
| 1357 | /* Unlikely, but possible */ | /* Unlikely, but possible */ |
| 1358 | earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); | earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); |
| 1359 | loop = LABEL(); | loop = LABEL(); |
| 1360 | OP2(SLJIT_SUB, SLJIT_GENERAL_REG2, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), 0, SLJIT_TEMPORARY_REG1, 0); | OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_TEMPORARY_REG1, 0); |
| 1361 | OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_GENERAL_REG1, 0, SLJIT_IMM, sizeof(sljit_w)); | OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_w)); |
| 1362 | /* Copy the integer value to the output buffer */ | /* Copy the integer value to the output buffer */ |
| 1363 | #ifdef COMPILE_PCRE16 | #ifdef COMPILE_PCRE16 |
| 1364 | OP2(SLJIT_ASHR, SLJIT_GENERAL_REG2, 0, SLJIT_GENERAL_REG2, 0, SLJIT_IMM, 1); | OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1); |
| 1365 | #endif | #endif |
| 1366 | OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_GENERAL_REG2, 0); | OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_SAVED_REG2, 0); |
| 1367 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); |
| 1368 | JUMPTO(SLJIT_C_NOT_ZERO, loop); | JUMPTO(SLJIT_C_NOT_ZERO, loop); |
| 1369 | JUMPHERE(earlyexit); | JUMPHERE(earlyexit); |
| # | Line 1250 JUMPHERE(earlyexit); | Line 1371 JUMPHERE(earlyexit); |
| 1371 | /* Calculate the return value, which is the maximum ovector value. */ | /* Calculate the return value, which is the maximum ovector value. */ |
| 1372 | if (topbracket > 1) | if (topbracket > 1) |
| 1373 | { | { |
| 1374 | OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w)); | GET_LOCAL_BASE(SLJIT_TEMPORARY_REG1, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_w)); |
| 1375 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); |
| 1376 | ||
| 1377 | /* OVECTOR(0) is never equal to SLJIT_GENERAL_REG3. */ | /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ |
| 1378 | loop = LABEL(); | loop = LABEL(); |
| 1379 | OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w))); | OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w))); |
| 1380 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); |
| 1381 | CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_GENERAL_REG3, 0, loop); | CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG3, 0, loop); |
| 1382 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0); |
| 1383 | } | } |
| 1384 | else | else |
| 1385 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); |
| 1386 | } | } |
| 1387 | ||
| 1388 | static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *leave) | |
| 1389 | { | |
| 1390 | DEFINE_COMPILER; | |
| 1391 | ||
| 1392 | SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2); | |
| 1393 | SLJIT_ASSERT(common->start_used_ptr != 0 && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0)); | |
| 1394 | ||
| 1395 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); | |
| 1396 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); | |
| 1397 | OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsetcount)); | |
| 1398 | CMPTO(SLJIT_C_LESS, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 2, leave); | |
| 1399 | ||
| 1400 | /* Store match begin and end. */ | |
| 1401 | OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, begin)); | |
| 1402 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsets)); | |
| 1403 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start); | |
| 1404 | OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0); | |
| 1405 | #ifdef COMPILE_PCRE16 | |
| 1406 | OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1); | |
| 1407 | #endif | |
| 1408 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(int), SLJIT_SAVED_REG2, 0); | |
| 1409 | ||
| 1410 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG1, 0); | |
| 1411 | #ifdef COMPILE_PCRE16 | |
| 1412 | OP2(SLJIT_ASHR, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1); | |
| 1413 | #endif | |
| 1414 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), 0, SLJIT_TEMPORARY_REG3, 0); | |
| 1415 | ||
| 1416 | JUMPTO(SLJIT_JUMP, leave); | |
| 1417 | } | |
| 1418 | ||
| 1419 | static SLJIT_INLINE void check_start_used_ptr(compiler_common *common) | |
| 1420 | { | |
| 1421 | /* May destroy TMP1. */ | |
| 1422 | DEFINE_COMPILER; | |
| 1423 | struct sljit_jump *jump; | |
| 1424 | ||
| 1425 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | |
| 1426 | { | |
| 1427 | /* The value of -1 must be kept for start_used_ptr! */ | |
| 1428 | OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, 1); | |
| 1429 | /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting | |
| 1430 | is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */ | |
| 1431 | jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_PTR, 0); | |
| 1432 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | |
| 1433 | JUMPHERE(jump); | |
| 1434 | } | |
| 1435 | else if (common->mode == JIT_PARTIAL_HARD_COMPILE) | |
| 1436 | { | |
| 1437 | jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | |
| 1438 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | |
| 1439 | JUMPHERE(jump); | |
| 1440 | } | |
| 1441 | } | |
| 1442 | ||
| 1443 | 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) |
| 1444 | { | { |
| 1445 | /* Detects if the character has an othercase. */ | /* Detects if the character has an othercase. */ |
| # | Line 1385 return (bit < 256) ? ((0 << 8) | bit) : | Line 1561 return (bit < 256) ? ((0 << 8) | bit) : |
| 1561 | #endif /* COMPILE_PCRE8 */ | #endif /* COMPILE_PCRE8 */ |
| 1562 | } | } |
| 1563 | ||
| 1564 | static SLJIT_INLINE void check_input_end(compiler_common *common, jump_list **fallbacks) | static void check_partial(compiler_common *common, BOOL force) |
| 1565 | { | |
| 1566 | /* Checks whether a partial matching is occured. Does not modify registers. */ | |
| 1567 | DEFINE_COMPILER; | |
| 1568 | struct sljit_jump *jump = NULL; | |
| 1569 | ||
| 1570 | SLJIT_ASSERT(!force || common->mode != JIT_COMPILE); | |
| 1571 | ||
| 1572 | if (common->mode == JIT_COMPILE) | |
| 1573 | return; | |
| 1574 | ||
| 1575 | if (!force) | |
| 1576 | jump = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | |
| 1577 | else if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | |
| 1578 | jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); | |
| 1579 | ||
| 1580 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | |
| 1581 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); | |
| 1582 | else | |
| 1583 | { | |
| 1584 | if (common->partialmatchlabel != NULL) | |
| 1585 | JUMPTO(SLJIT_JUMP, common->partialmatchlabel); | |
| 1586 | else | |
| 1587 | add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); | |
| 1588 | } | |
| 1589 | ||
| 1590 | if (jump != NULL) | |
| 1591 | JUMPHERE(jump); | |
| 1592 | } | |
| 1593 | ||
| 1594 | static struct sljit_jump *check_str_end(compiler_common *common) | |
| 1595 | { | { |
| 1596 | /* Does not affect registers. Usually used in a tight spot. */ | |
| 1597 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 1598 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | struct sljit_jump *jump; |
| 1599 | struct sljit_jump *nohit; | |
| 1600 | struct sljit_jump *return_value; | |
| 1601 | ||
| 1602 | if (common->mode == JIT_COMPILE) | |
| 1603 | return CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | |
| 1604 | ||
| 1605 | jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | |
| 1606 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | |
| 1607 | { | |
| 1608 | nohit = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | |
| 1609 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); | |
| 1610 | JUMPHERE(nohit); | |
| 1611 | return_value = JUMP(SLJIT_JUMP); | |
| 1612 | } | |
| 1613 | else | |
| 1614 | { | |
| 1615 | return_value = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | |
| 1616 | if (common->partialmatchlabel != NULL) | |
| 1617 | JUMPTO(SLJIT_JUMP, common->partialmatchlabel); | |
| 1618 | else | |
| 1619 | add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); | |
| 1620 | } | |
| 1621 | JUMPHERE(jump); | |
| 1622 | return return_value; | |
| 1623 | } | |
| 1624 | ||
| 1625 | static void detect_partial_match(compiler_common *common, jump_list **backtracks) | |
| 1626 | { | |
| 1627 | DEFINE_COMPILER; | |
| 1628 | struct sljit_jump *jump; | |
| 1629 | ||
| 1630 | if (common->mode == JIT_COMPILE) | |
| 1631 | { | |
| 1632 | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | |
| 1633 | return; | |
| 1634 | } | |
| 1635 | ||
| 1636 | /* Partial matching mode. */ | |
| 1637 | jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | |
| 1638 | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); | |
| 1639 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | |
| 1640 | { | |
| 1641 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); | |
| 1642 | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); | |
| 1643 | } | |
| 1644 | else | |
| 1645 | { | |
| 1646 | if (common->partialmatchlabel != NULL) | |
| 1647 | JUMPTO(SLJIT_JUMP, common->partialmatchlabel); | |
| 1648 | else | |
| 1649 | add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); | |
| 1650 | } | |
| 1651 | JUMPHERE(jump); | |
| 1652 | } | } |
| 1653 | ||
| 1654 | static void read_char(compiler_common *common) | static void read_char(compiler_common *common) |
| # | Line 1529 if (common->utf) | Line 1789 if (common->utf) |
| 1789 | 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)); |
| 1790 | } | } |
| 1791 | ||
| 1792 | static void check_newlinechar(compiler_common *common, int nltype, jump_list **fallbacks, BOOL jumpiftrue) | static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpiftrue) |
| 1793 | { | { |
| 1794 | /* 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. */ |
| 1795 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| # | Line 1537 DEFINE_COMPILER; | Line 1797 DEFINE_COMPILER; |
| 1797 | if (nltype == NLTYPE_ANY) | if (nltype == NLTYPE_ANY) |
| 1798 | { | { |
| 1799 | add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); |
| 1800 | add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
| 1801 | } | } |
| 1802 | else if (nltype == NLTYPE_ANYCRLF) | else if (nltype == NLTYPE_ANYCRLF) |
| 1803 | { | { |
| # | Line 1545 else if (nltype == NLTYPE_ANYCRLF) | Line 1805 else if (nltype == NLTYPE_ANYCRLF) |
| 1805 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
| 1806 | 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); |
| 1807 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
| 1808 | add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
| 1809 | } | } |
| 1810 | else | else |
| 1811 | { | { |
| 1812 | SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); | SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); |
| 1813 | add_jump(compiler, fallbacks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); | add_jump(compiler, backtracks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); |
| 1814 | } | } |
| 1815 | } | } |
| 1816 | ||
| # | Line 1564 of the character (>= 0xc0). Return char | Line 1824 of the character (>= 0xc0). Return char |
| 1824 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 1825 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| 1826 | ||
| 1827 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
| 1828 | /* Searching for the first zero. */ | /* Searching for the first zero. */ |
| 1829 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); |
| 1830 | jump = JUMP(SLJIT_C_NOT_ZERO); | jump = JUMP(SLJIT_C_NOT_ZERO); |
| # | Line 1623 DEFINE_COMPILER; | Line 1883 DEFINE_COMPILER; |
| 1883 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| 1884 | struct sljit_jump *compare; | struct sljit_jump *compare; |
| 1885 | ||
| 1886 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
| 1887 | ||
| 1888 | 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); |
| 1889 | jump = JUMP(SLJIT_C_NOT_ZERO); | jump = JUMP(SLJIT_C_NOT_ZERO); |
| # | Line 1660 of the character (>= 0xd800). Return cha | Line 1920 of the character (>= 0xd800). Return cha |
| 1920 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 1921 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| 1922 | ||
| 1923 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
| 1924 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00); | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00); |
| 1925 | /* Do nothing, only return. */ | /* Do nothing, only return. */ |
| 1926 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
| # | Line 1697 DEFINE_COMPILER; | Line 1957 DEFINE_COMPILER; |
| 1957 | ||
| 1958 | SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8); | SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8); |
| 1959 | ||
| 1960 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
| 1961 | OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); | OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); |
| 1962 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(ucd_stage1)); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(ucd_stage1)); |
| 1963 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); |
| # | Line 1733 if (!(hascrorlf || firstline) && (common | Line 1993 if (!(hascrorlf || firstline) && (common |
| 1993 | if (firstline) | if (firstline) |
| 1994 | { | { |
| 1995 | /* Search for the end of the first line. */ | /* Search for the end of the first line. */ |
| 1996 | SLJIT_ASSERT(common->first_line_end != 0); | |
| 1997 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0); |
| 1998 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_END, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_END, 0); |
| 1999 | ||
| 2000 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
| 2001 | { | { |
| # | Line 1745 if (firstline) | Line 2006 if (firstline) |
| 2006 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
| 2007 | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); |
| 2008 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); |
| 2009 | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
| 2010 | } | } |
| 2011 | else | else |
| 2012 | { | { |
| 2013 | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
| 2014 | mainloop = LABEL(); | mainloop = LABEL(); |
| 2015 | /* Continual stores does not cause data dependency. */ | /* Continual stores does not cause data dependency. */ |
| 2016 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0); |
| 2017 | read_char(common); | read_char(common); |
| 2018 | check_newlinechar(common, common->nltype, &newline, TRUE); | check_newlinechar(common, common->nltype, &newline, TRUE); |
| 2019 | CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); | CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); |
| 2020 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0); |
| 2021 | set_jumps(newline, LABEL()); | set_jumps(newline, LABEL()); |
| 2022 | } | } |
| 2023 | ||
| # | Line 1839 pcre_uchar oc, bit; | Line 2100 pcre_uchar oc, bit; |
| 2100 | if (firstline) | if (firstline) |
| 2101 | { | { |
| 2102 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); |
| 2103 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END); | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); |
| 2104 | } | } |
| 2105 | ||
| 2106 | start = LABEL(); | start = LABEL(); |
| # | Line 1917 jump_list *newline = NULL; | Line 2178 jump_list *newline = NULL; |
| 2178 | if (firstline) | if (firstline) |
| 2179 | { | { |
| 2180 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); |
| 2181 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END); | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); |
| 2182 | } | } |
| 2183 | ||
| 2184 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
| # | Line 2001 struct sljit_jump *jump; | Line 2262 struct sljit_jump *jump; |
| 2262 | if (firstline) | if (firstline) |
| 2263 | { | { |
| 2264 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); |
| 2265 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END); | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); |
| 2266 | } | } |
| 2267 | ||
| 2268 | start = LABEL(); | start = LABEL(); |
| # | Line 2066 struct sljit_jump *foundoc = NULL; | Line 2327 struct sljit_jump *foundoc = NULL; |
| 2327 | struct sljit_jump *notfound; | struct sljit_jump *notfound; |
| 2328 | pcre_uchar oc, bit; | pcre_uchar oc, bit; |
| 2329 | ||
| 2330 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR); | SLJIT_ASSERT(common->req_char_ptr != 0); |
| 2331 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr); | |
| 2332 | 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); |
| 2333 | toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0); | toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0); |
| 2334 | alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0); | alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0); |
| # | Line 2111 JUMPTO(SLJIT_JUMP, loop); | Line 2373 JUMPTO(SLJIT_JUMP, loop); |
| 2373 | JUMPHERE(found); | JUMPHERE(found); |
| 2374 | if (foundoc) | if (foundoc) |
| 2375 | JUMPHERE(foundoc); | JUMPHERE(foundoc); |
| 2376 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, TMP1, 0); |
| 2377 | JUMPHERE(alreadyfound); | JUMPHERE(alreadyfound); |
| 2378 | JUMPHERE(toolong); | JUMPHERE(toolong); |
| 2379 | return notfound; | return notfound; |
| # | Line 2123 DEFINE_COMPILER; | Line 2385 DEFINE_COMPILER; |
| 2385 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| 2386 | struct sljit_label *mainloop; | struct sljit_label *mainloop; |
| 2387 | ||
| 2388 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
| 2389 | OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0); | OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0); |
| 2390 | GET_LOCAL_BASE(TMP3, 0, 0); | |
| 2391 | ||
| 2392 | /* Drop frames until we reach STACK_TOP. */ | /* Drop frames until we reach STACK_TOP. */ |
| 2393 | mainloop = LABEL(); | mainloop = LABEL(); |
| 2394 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); |
| 2395 | jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); | jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); |
| 2396 | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_LOCALS_REG, 0); | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); |
| 2397 | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w)); | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w)); |
| 2398 | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w)); | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w)); |
| 2399 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w)); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w)); |
| # | Line 2150 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_R | Line 2413 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_R |
| 2413 | JUMPTO(SLJIT_JUMP, mainloop); | JUMPTO(SLJIT_JUMP, mainloop); |
| 2414 | ||
| 2415 | JUMPHERE(jump); | JUMPHERE(jump); |
| 2416 | if (common->mark_ptr != 0) | |
| 2417 | { | |
| 2418 | jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setmark); | |
| 2419 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w)); | |
| 2420 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w)); | |
| 2421 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); | |
| 2422 | JUMPTO(SLJIT_JUMP, mainloop); | |
| 2423 | ||
| 2424 | JUMPHERE(jump); | |
| 2425 | } | |
| 2426 | ||
| 2427 | /* Unknown command. */ | /* Unknown command. */ |
| 2428 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w)); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w)); |
| 2429 | JUMPTO(SLJIT_JUMP, mainloop); | JUMPTO(SLJIT_JUMP, mainloop); |
| # | Line 2158 JUMPTO(SLJIT_JUMP, mainloop); | Line 2432 JUMPTO(SLJIT_JUMP, mainloop); |
| 2432 | static void check_wordboundary(compiler_common *common) | static void check_wordboundary(compiler_common *common) |
| 2433 | { | { |
| 2434 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 2435 | struct sljit_jump *beginend; | struct sljit_jump *skipread; |
| 2436 | #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF | #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF |
| 2437 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| 2438 | #endif | #endif |
| 2439 | ||
| 2440 | SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); | SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); |
| 2441 | ||
| 2442 | sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
| 2443 | /* Get type of the previous char, and put it to LOCALS1. */ | /* Get type of the previous char, and put it to LOCALS1. */ |
| 2444 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
| 2445 | 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)); |
| 2446 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0); |
| 2447 | beginend = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); | skipread = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); |
| 2448 | skip_char_back(common); | skip_char_back(common); |
| 2449 | check_start_used_ptr(common); | |
| 2450 | read_char(common); | read_char(common); |
| 2451 | ||
| 2452 | /* Testing char type. */ | /* Testing char type. */ |
| # | Line 2212 else | Line 2487 else |
| 2487 | JUMPHERE(jump); | JUMPHERE(jump); |
| 2488 | #endif /* COMPILE_PCRE8 */ | #endif /* COMPILE_PCRE8 */ |
| 2489 | } | } |
| 2490 | JUMPHERE(beginend); | JUMPHERE(skipread); |
| 2491 | ||
| 2492 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
| 2493 | beginend = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | skipread = check_str_end(common); |
| 2494 | peek_char(common); | peek_char(common); |
| 2495 | ||
| 2496 | /* Testing char type. This is a code duplication. */ | /* Testing char type. This is a code duplication. */ |
| # | Line 2256 else | Line 2531 else |
| 2531 | JUMPHERE(jump); | JUMPHERE(jump); |
| 2532 | #endif /* COMPILE_PCRE8 */ | #endif /* COMPILE_PCRE8 */ |
| 2533 | } | } |
| 2534 | JUMPHERE(beginend); | JUMPHERE(skipread); |
| 2535 | ||
| 2536 | OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); | OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); |
| 2537 | sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
| # | Line 2267 static void check_anynewline(compiler_co | Line 2542 static void check_anynewline(compiler_co |
| 2542 | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ |
| 2543 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 2544 | ||
| 2545 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
| 2546 | ||
| 2547 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); |
| 2548 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); |
| # | Line 2294 static void check_hspace(compiler_common | Line 2569 static void check_hspace(compiler_common |
| 2569 | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ |
| 2570 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 2571 | ||
| 2572 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
| 2573 | ||
| 2574 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09); |
| 2575 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
| # | Line 2333 static void check_vspace(compiler_common | Line 2608 static void check_vspace(compiler_common |
| 2608 | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ |
| 2609 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 2610 | ||
| 2611 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
| 2612 | ||
| 2613 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); |
| 2614 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); |
| # | Line 2365 DEFINE_COMPILER; | Line 2640 DEFINE_COMPILER; |
| 2640 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| 2641 | struct sljit_label *label; | struct sljit_label *label; |
| 2642 | ||
| 2643 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
| 2644 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
| 2645 | OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0); | OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0); |
| 2646 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0); |
| # | Line 2394 DEFINE_COMPILER; | Line 2669 DEFINE_COMPILER; |
| 2669 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| 2670 | struct sljit_label *label; | struct sljit_label *label; |
| 2671 | ||
| 2672 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
| 2673 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
| 2674 | ||
| 2675 | OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); | OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); |
| # | Line 2441 static const pcre_uchar *SLJIT_CALL do_u | Line 2716 static const pcre_uchar *SLJIT_CALL do_u |
| 2716 | { | { |
| 2717 | /* This function would be ineffective to do in JIT level. */ | /* This function would be ineffective to do in JIT level. */ |
| 2718 | int c1, c2; | int c1, c2; |
| 2719 | const pcre_uchar *src2 = args->ptr; | const pcre_uchar *src2 = args->uchar_ptr; |
| 2720 | const pcre_uchar *end2 = args->end; | const pcre_uchar *end2 = args->end; |
| 2721 | ||
| 2722 | while (src1 < end1) | while (src1 < end1) |
| 2723 | { | { |
| 2724 | if (src2 >= end2) | if (src2 >= end2) |
| 2725 | return 0; | return (pcre_uchar*)1; |
| 2726 | GETCHARINC(c1, src1); | GETCHARINC(c1, src1); |
| 2727 | GETCHARINC(c2, src2); | GETCHARINC(c2, src2); |
| 2728 | if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return 0; | if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return NULL; |
| 2729 | } | } |
| 2730 | return src2; | return src2; |
| 2731 | } | } |
| # | Line 2458 return src2; | Line 2733 return src2; |
| 2733 | #endif /* SUPPORT_UTF && SUPPORT_UCP */ | #endif /* SUPPORT_UTF && SUPPORT_UCP */ |
| 2734 | ||
| 2735 | static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc, | static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc, |
| 2736 | compare_context* context, jump_list **fallbacks) | compare_context* context, jump_list **backtracks) |
| 2737 | { | { |
| 2738 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 2739 | unsigned int othercasebit = 0; | unsigned int othercasebit = 0; |
| # | Line 2559 do | Line 2834 do |
| 2834 | case 4 / sizeof(pcre_uchar): | case 4 / sizeof(pcre_uchar): |
| 2835 | if (context->oc.asint != 0) | if (context->oc.asint != 0) |
| 2836 | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint); | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint); |
| 2837 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); |
| 2838 | break; | break; |
| 2839 | ||
| 2840 | case 2 / sizeof(pcre_uchar): | case 2 / sizeof(pcre_uchar): |
| 2841 | if (context->oc.asushort != 0) | if (context->oc.asushort != 0) |
| 2842 | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); |
| 2843 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort)); |
| 2844 | break; | break; |
| 2845 | ||
| 2846 | #ifdef COMPILE_PCRE8 | #ifdef COMPILE_PCRE8 |
| 2847 | case 1: | case 1: |
| 2848 | if (context->oc.asbyte != 0) | if (context->oc.asbyte != 0) |
| 2849 | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte); | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte); |
| 2850 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); |
| 2851 | break; | break; |
| 2852 | #endif | #endif |
| 2853 | ||
| # | Line 2598 do | Line 2873 do |
| 2873 | if (othercasebit != 0 && othercasechar == cc) | if (othercasebit != 0 && othercasechar == cc) |
| 2874 | { | { |
| 2875 | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); |
| 2876 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); |
| 2877 | } | } |
| 2878 | else | else |
| 2879 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc)); |
| 2880 | ||
| 2881 | #endif | #endif |
| 2882 | ||
| # | Line 2637 return cc; | Line 2912 return cc; |
| 2912 | } \ | } \ |
| 2913 | charoffset = (value); | charoffset = (value); |
| 2914 | ||
| 2915 | static void compile_xclass_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks) | static void compile_xclass_trypath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks) |
| 2916 | { | { |
| 2917 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 2918 | jump_list *found = NULL; | jump_list *found = NULL; |
| 2919 | jump_list **list = (*cc & XCL_NOT) == 0 ? &found : fallbacks; | jump_list **list = (*cc & XCL_NOT) == 0 ? &found : backtracks; |
| 2920 | unsigned int c; | unsigned int c; |
| 2921 | int compares; | int compares; |
| 2922 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
| # | Line 2656 int invertcmp, numberofcmps; | Line 2931 int invertcmp, numberofcmps; |
| 2931 | unsigned int charoffset; | unsigned int charoffset; |
| 2932 | ||
| 2933 | /* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */ | /* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */ |
| 2934 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 2935 | read_char(common); | read_char(common); |
| 2936 | ||
| 2937 | if ((*cc++ & XCL_MAP) != 0) | if ((*cc++ & XCL_MAP) != 0) |
| # | Line 2807 typeoffset = 0; | Line 3082 typeoffset = 0; |
| 3082 | while (*cc != XCL_END) | while (*cc != XCL_END) |
| 3083 | { | { |
| 3084 | compares--; | compares--; |
| 3085 | invertcmp = (compares == 0 && list != fallbacks); | invertcmp = (compares == 0 && list != backtracks); |
| 3086 | jump = NULL; | jump = NULL; |
| 3087 | ||
| 3088 | if (*cc == XCL_SINGLE) | if (*cc == XCL_SINGLE) |
| # | Line 2889 while (*cc != XCL_END) | Line 3164 while (*cc != XCL_END) |
| 3164 | switch(*cc) | switch(*cc) |
| 3165 | { | { |
| 3166 | case PT_ANY: | case PT_ANY: |
| 3167 | if (list != fallbacks) | if (list != backtracks) |
| 3168 | { | { |
| 3169 | if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0)) | if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0)) |
| 3170 | continue; | continue; |
| # | Line 2962 while (*cc != XCL_END) | Line 3237 while (*cc != XCL_END) |
| 3237 | #endif | #endif |
| 3238 | ||
| 3239 | if (jump != NULL) | if (jump != NULL) |
| 3240 | add_jump(compiler, compares > 0 ? list : fallbacks, jump); | add_jump(compiler, compares > 0 ? list : backtracks, jump); |
| 3241 | } | } |
| 3242 | ||
| 3243 | if (found != NULL) | if (found != NULL) |
| # | Line 2974 if (found != NULL) | Line 3249 if (found != NULL) |
| 3249 | ||
| 3250 | #endif | #endif |
| 3251 | ||
| 3252 | static pcre_uchar *compile_char1_hotpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **fallbacks) | static pcre_uchar *compile_char1_trypath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks) |
| 3253 | { | { |
| 3254 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 3255 | int length; | int length; |
| # | Line 2993 switch(type) | Line 3268 switch(type) |
| 3268 | case OP_SOD: | case OP_SOD: |
| 3269 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
| 3270 | 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)); |
| 3271 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); |
| 3272 | return cc; | return cc; |
| 3273 | ||
| 3274 | case OP_SOM: | case OP_SOM: |
| 3275 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
| 3276 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); |
| 3277 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); |
| 3278 | return cc; | return cc; |
| 3279 | ||
| 3280 | case OP_NOT_WORD_BOUNDARY: | case OP_NOT_WORD_BOUNDARY: |
| 3281 | case OP_WORD_BOUNDARY: | case OP_WORD_BOUNDARY: |
| 3282 | add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL)); |
| 3283 | add_jump(compiler, fallbacks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
| 3284 | return cc; | return cc; |
| 3285 | ||
| 3286 | case OP_NOT_DIGIT: | case OP_NOT_DIGIT: |
| 3287 | case OP_DIGIT: | case OP_DIGIT: |
| 3288 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3289 | read_char8_type(common); | read_char8_type(common); |
| 3290 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); |
| 3291 | add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); | add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
| 3292 | return cc; | return cc; |
| 3293 | ||
| 3294 | case OP_NOT_WHITESPACE: | case OP_NOT_WHITESPACE: |
| 3295 | case OP_WHITESPACE: | case OP_WHITESPACE: |
| 3296 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3297 | read_char8_type(common); | read_char8_type(common); |
| 3298 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); |
| 3299 | add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); | add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
| 3300 | return cc; | return cc; |
| 3301 | ||
| 3302 | case OP_NOT_WORDCHAR: | case OP_NOT_WORDCHAR: |
| 3303 | case OP_WORDCHAR: | case OP_WORDCHAR: |
| 3304 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3305 | read_char8_type(common); | read_char8_type(common); |
| 3306 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); |
| 3307 | add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); | add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
| 3308 | return cc; | return cc; |
| 3309 | ||
| 3310 | case OP_ANY: | case OP_ANY: |
| 3311 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3312 | read_char(common); | read_char(common); |
| 3313 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
| 3314 | { | { |
| 3315 | jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); | jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); |
| 3316 | jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | if (common->mode != JIT_PARTIAL_HARD_COMPILE) |
| 3317 | jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | |
| 3318 | else | |
| 3319 | jump[1] = check_str_end(common); | |
| 3320 | ||
| 3321 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
| 3322 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); |
| 3323 | JUMPHERE(jump[1]); | if (jump[1] != NULL) |
| 3324 | JUMPHERE(jump[1]); | |
| 3325 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
| 3326 | } | } |
| 3327 | else | else |
| 3328 | check_newlinechar(common, common->nltype, fallbacks, TRUE); | check_newlinechar(common, common->nltype, backtracks, TRUE); |
| 3329 | return cc; | return cc; |
| 3330 | ||
| 3331 | case OP_ALLANY: | case OP_ALLANY: |
| 3332 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3333 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
| 3334 | if (common->utf) | if (common->utf) |
| 3335 | { | { |
| # | Line 3077 switch(type) | Line 3357 switch(type) |
| 3357 | return cc; | return cc; |
| 3358 | ||
| 3359 | case OP_ANYBYTE: | case OP_ANYBYTE: |
| 3360 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3361 | 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)); |
| 3362 | return cc; | return cc; |
| 3363 | ||
| # | Line 3090 switch(type) | Line 3370 switch(type) |
| 3370 | propdata[2] = cc[0]; | propdata[2] = cc[0]; |
| 3371 | propdata[3] = cc[1]; | propdata[3] = cc[1]; |
| 3372 | propdata[4] = XCL_END; | propdata[4] = XCL_END; |
| 3373 | compile_xclass_hotpath(common, propdata, fallbacks); | compile_xclass_trypath(common, propdata, backtracks); |
| 3374 | return cc + 2; | return cc + 2; |
| 3375 | #endif | #endif |
| 3376 | #endif | #endif |
| 3377 | ||
| 3378 | case OP_ANYNL: | case OP_ANYNL: |
| 3379 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3380 | read_char(common); | read_char(common); |
| 3381 | jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); | jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); |
| 3382 | jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | /* We don't need to handle soft partial matching case. */ |
| 3383 | if (common->mode != JIT_PARTIAL_HARD_COMPILE) | |
| 3384 | jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | |
| 3385 | else | |
| 3386 | jump[1] = check_str_end(common); | |
| 3387 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
| 3388 | jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); | jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); |
| 3389 | 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)); |
| 3390 | jump[3] = JUMP(SLJIT_JUMP); | jump[3] = JUMP(SLJIT_JUMP); |
| 3391 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
| 3392 | check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE); | check_newlinechar(common, common->bsr_nltype, backtracks, FALSE); |
| 3393 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
| 3394 | JUMPHERE(jump[2]); | JUMPHERE(jump[2]); |
| 3395 | JUMPHERE(jump[3]); | JUMPHERE(jump[3]); |
| # | Line 3113 switch(type) | Line 3397 switch(type) |
| 3397 | ||
| 3398 | case OP_NOT_HSPACE: | case OP_NOT_HSPACE: |
| 3399 | case OP_HSPACE: | case OP_HSPACE: |
| 3400 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3401 | read_char(common); | read_char(common); |
| 3402 | add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); |
| 3403 | add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
| 3404 | return cc; | return cc; |
| 3405 | ||
| 3406 | case OP_NOT_VSPACE: | case OP_NOT_VSPACE: |
| 3407 | case OP_VSPACE: | case OP_VSPACE: |
| 3408 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3409 | read_char(common); | read_char(common); |
| 3410 | add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); |
| 3411 | add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
| 3412 | return cc; | return cc; |
| 3413 | ||
| 3414 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
| 3415 | case OP_EXTUNI: | case OP_EXTUNI: |
| 3416 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3417 | read_char(common); | read_char(common); |
| 3418 | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); |
| 3419 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); |
| 3420 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc)); | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc)); |
| 3421 | ||
| 3422 | label = LABEL(); | label = LABEL(); |
| 3423 | jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
| # | Line 3145 switch(type) | Line 3429 switch(type) |
| 3429 | ||
| 3430 | OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); | OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); |
| 3431 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
| 3432 | if (common->mode == JIT_PARTIAL_HARD_COMPILE) | |
| 3433 | { | |
| 3434 | jump[0] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | |
| 3435 | /* Since we successfully read a char above, partial matching must occure. */ | |
| 3436 | check_partial(common, TRUE); | |
| 3437 | JUMPHERE(jump[0]); | |
| 3438 | } | |
| 3439 | return cc; | return cc; |
| 3440 | #endif | #endif |
| 3441 | ||
| 3442 | case OP_EODN: | case OP_EODN: |
| 3443 | /* Requires rather complex checks. */ | |
| 3444 | jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
| 3445 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
| 3446 | { | { |
| 3447 | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
| 3448 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
| 3449 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); | if (common->mode == JIT_COMPILE) |
| 3450 | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); | |
| 3451 | else | |
| 3452 | { | |
| 3453 | jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0); | |
| 3454 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); | |
| 3455 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS); | |
| 3456 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); | |
| 3457 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_NOT_EQUAL); | |
| 3458 | add_jump(compiler, backtracks, JUMP(SLJIT_C_NOT_EQUAL)); | |
| 3459 | check_partial(common, TRUE); | |
| 3460 | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); | |
| 3461 | JUMPHERE(jump[1]); | |
| 3462 | } | |
| 3463 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
| 3464 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); |
| 3465 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); |
| 3466 | } | } |
| 3467 | else if (common->nltype == NLTYPE_FIXED) | else if (common->nltype == NLTYPE_FIXED) |
| 3468 | { | { |
| 3469 | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
| 3470 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
| 3471 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); |
| 3472 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); |
| 3473 | } | } |
| 3474 | else | else |
| 3475 | { | { |
| # | Line 3173 switch(type) | Line 3478 switch(type) |
| 3478 | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
| 3479 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); |
| 3480 | jump[2] = JUMP(SLJIT_C_GREATER); | jump[2] = JUMP(SLJIT_C_GREATER); |
| 3481 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_LESS)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_LESS)); |
| 3482 | /* Equal. */ | /* Equal. */ |
| 3483 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
| 3484 | jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); | jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); |
| 3485 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
| 3486 | ||
| 3487 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
| 3488 | if (common->nltype == NLTYPE_ANYCRLF) | if (common->nltype == NLTYPE_ANYCRLF) |
| 3489 | { | { |
| 3490 | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
| 3491 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0)); |
| 3492 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); |
| 3493 | } | } |
| 3494 | else | else |
| 3495 | { | { |
| 3496 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0); |
| 3497 | read_char(common); | read_char(common); |
| 3498 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); |
| 3499 | add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); |
| 3500 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); |
| 3501 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); |
| 3502 | } | } |
| 3503 | JUMPHERE(jump[2]); | JUMPHERE(jump[2]); |
| 3504 | JUMPHERE(jump[3]); | JUMPHERE(jump[3]); |
| 3505 | } | } |
| 3506 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
| 3507 | check_partial(common, FALSE); | |
| 3508 | return cc; | return cc; |
| 3509 | ||
| 3510 | case OP_EOD: | case OP_EOD: |
| 3511 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); |
| 3512 | check_partial(common, FALSE); | |
| 3513 | return cc; | return cc; |
| 3514 | ||
| 3515 | case OP_CIRC: | case OP_CIRC: |
| 3516 | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); |
| 3517 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); |
| 3518 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0)); |
| 3519 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); |
| 3520 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
| 3521 | return cc; | return cc; |
| 3522 | ||
| 3523 | case OP_CIRCM: | case OP_CIRCM: |
| # | Line 3218 switch(type) | Line 3525 switch(type) |
| 3525 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); |
| 3526 | jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0); | jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0); |
| 3527 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); |
| 3528 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
| 3529 | jump[0] = JUMP(SLJIT_JUMP); | jump[0] = JUMP(SLJIT_JUMP); |
| 3530 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
| 3531 | ||
| 3532 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
| 3533 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
| 3534 | { | { |
| 3535 | OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); | OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
| 3536 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0)); |
| 3537 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); |
| 3538 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); |
| 3539 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); |
| 3540 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); |
| 3541 | } | } |
| 3542 | else | else |
| 3543 | { | { |
| 3544 | skip_char_back(common); | skip_char_back(common); |
| 3545 | read_char(common); | read_char(common); |
| 3546 | check_newlinechar(common, common->nltype, fallbacks, FALSE); | check_newlinechar(common, common->nltype, backtracks, FALSE); |
| 3547 | } | } |
| 3548 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
| 3549 | return cc; | return cc; |
| # | Line 3244 switch(type) | Line 3551 switch(type) |
| 3551 | case OP_DOLL: | case OP_DOLL: |
| 3552 | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); |
| 3553 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); |
| 3554 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
| 3555 | ||
| 3556 | if (!common->endonly) | if (!common->endonly) |
| 3557 | compile_char1_hotpath(common, OP_EODN, cc, fallbacks); | compile_char1_trypath(common, OP_EODN, cc, backtracks); |
| 3558 | else | else |
| 3559 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); | { |
| 3560 | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); | |
| 3561 | check_partial(common, FALSE); | |
| 3562 | } | |
| 3563 | return cc; | return cc; |
| 3564 | ||
| 3565 | case OP_DOLLM: | case OP_DOLLM: |
| 3566 | jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); |
| 3567 | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); |
| 3568 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); |
| 3569 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
| 3570 | check_partial(common, FALSE); | |
| 3571 | jump[0] = JUMP(SLJIT_JUMP); | jump[0] = JUMP(SLJIT_JUMP); |
| 3572 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
| 3573 | ||
| 3574 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
| 3575 | { | { |
| 3576 | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
| add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0)); | ||
| 3577 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
| 3578 | if (common->mode == JIT_COMPILE) | |
| 3579 | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0)); | |
| 3580 | else | |
| 3581 | { | |
| 3582 | jump[1] = CMP(SLJIT_C_LESS_EQUAL, TMP2, 0, STR_END, 0); | |
| 3583 | /* STR_PTR = STR_END - IN_UCHARS(1) */ | |
| 3584 | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); | |
| 3585 | check_partial(common, TRUE); | |
| 3586 | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); | |
| 3587 | JUMPHERE(jump[1]); | |
| 3588 | } | |
| 3589 | ||
| 3590 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
| 3591 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); |
| 3592 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); |
| 3593 | } | } |
| 3594 | else | else |
| 3595 | { | { |
| 3596 | peek_char(common); | peek_char(common); |
| 3597 | check_newlinechar(common, common->nltype, fallbacks, FALSE); | check_newlinechar(common, common->nltype, backtracks, FALSE); |
| 3598 | } | } |
| 3599 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
| 3600 | return cc; | return cc; |
| # | Line 3283 switch(type) | Line 3605 switch(type) |
| 3605 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
| 3606 | if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); | if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); |
| 3607 | #endif | #endif |
| 3608 | if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0) | if (common->mode == JIT_COMPILE && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)) |
| 3609 | { | { |
| 3610 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); |
| 3611 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); |
| 3612 | ||
| 3613 | context.length = IN_UCHARS(length); | context.length = IN_UCHARS(length); |
| 3614 | context.sourcereg = -1; | context.sourcereg = -1; |
| 3615 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED |
| 3616 | context.ucharptr = 0; | context.ucharptr = 0; |
| 3617 | #endif | #endif |
| 3618 | return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks); | return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks); |
| 3619 | } | } |
| 3620 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3621 | read_char(common); | read_char(common); |
| 3622 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
| 3623 | if (common->utf) | if (common->utf) |
| # | Line 3305 switch(type) | Line 3627 switch(type) |
| 3627 | else | else |
| 3628 | #endif | #endif |
| 3629 | c = *cc; | c = *cc; |
| 3630 | if (type == OP_CHAR || !char_has_othercase(common, cc)) | |
| 3631 | { | |
| 3632 | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); | |
| 3633 | return cc + length; | |
| 3634 | } | |
| 3635 | oc = char_othercase(common, c); | |
| 3636 | bit = c ^ oc; | |
| 3637 | if (ispowerof2(bit)) | |
| 3638 | { | |
| 3639 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); | |
| 3640 | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); | |
| 3641 | return cc + length; | |
| 3642 | } | |
| 3643 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c); |
| 3644 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
| 3645 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c)); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c)); |
| 3646 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
| 3647 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); |
| 3648 | return cc + length; | return cc + length; |
| 3649 | ||
| 3650 | case OP_NOT: | case OP_NOT: |
| 3651 | case OP_NOTI: | case OP_NOTI: |
| 3652 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3653 | length = 1; | length = 1; |
| 3654 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
| 3655 | if (common->utf) | if (common->utf) |
| # | Line 3325 switch(type) | Line 3660 switch(type) |
| 3660 | { | { |
| 3661 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
| 3662 | if (type == OP_NOT || !char_has_othercase(common, cc)) | if (type == OP_NOT || !char_has_othercase(common, cc)) |
| 3663 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); |
| 3664 | else | else |
| 3665 | { | { |
| 3666 | /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */ | /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */ |
| 3667 | OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); | OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); |
| 3668 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20)); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20)); |
| 3669 | } | } |
| 3670 | /* Skip the variable-length character. */ | /* Skip the variable-length character. */ |
| 3671 | 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)); |
| # | Line 3355 switch(type) | Line 3690 switch(type) |
| 3690 | } | } |
| 3691 | ||
| 3692 | if (type == OP_NOT || !char_has_othercase(common, cc)) | if (type == OP_NOT || !char_has_othercase(common, cc)) |
| 3693 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); |
| 3694 | else | else |
| 3695 | { | { |
| 3696 | oc = char_othercase(common, c); | oc = char_othercase(common, c); |
| # | Line 3363 switch(type) | Line 3698 switch(type) |
| 3698 | if (ispowerof2(bit)) | if (ispowerof2(bit)) |
| 3699 | { | { |
| 3700 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); |
| 3701 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); |
| 3702 | } | } |
| 3703 | else | else |
| 3704 | { | { |
| 3705 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); |
| 3706 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc)); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc)); |
| 3707 | } | } |
| 3708 | } | } |
| 3709 | return cc + 1; | return cc + length; |
| 3710 | ||
| 3711 | case OP_CLASS: | case OP_CLASS: |
| 3712 | case OP_NCLASS: | case OP_NCLASS: |
| 3713 | check_input_end(common, fallbacks); | detect_partial_match(common, backtracks); |
| 3714 | read_char(common); | read_char(common); |
| 3715 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
| 3716 | jump[0] = NULL; | jump[0] = NULL; |
| # | Line 3388 switch(type) | Line 3723 switch(type) |
| 3723 | jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); |
| 3724 | if (type == OP_CLASS) | if (type == OP_CLASS) |
| 3725 | { | { |
| 3726 | add_jump(compiler, fallbacks, jump[0]); | add_jump(compiler, backtracks, jump[0]); |
| 3727 | jump[0] = NULL; | jump[0] = NULL; |
| 3728 | } | } |
| 3729 | } | } |
| # | Line 3398 switch(type) | Line 3733 switch(type) |
| 3733 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); |
| 3734 | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); |
| 3735 | 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); |
| 3736 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); |
| 3737 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
| 3738 | if (jump[0] != NULL) | if (jump[0] != NULL) |
| 3739 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
| # | Line 3407 switch(type) | Line 3742 switch(type) |
| 3742 | ||
| 3743 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 |
| 3744 | case OP_XCLASS: | case OP_XCLASS: |
| 3745 | compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks); | compile_xclass_trypath(common, cc + LINK_SIZE, backtracks); |
| 3746 | return cc + GET(cc, 0) - 1; | return cc + GET(cc, 0) - 1; |
| 3747 | #endif | #endif |
| 3748 | ||
| 3749 | case OP_REVERSE: | case OP_REVERSE: |
| 3750 | length = GET(cc, 0); | length = GET(cc, 0); |
| 3751 | SLJIT_ASSERT(length > 0); | if (length == 0) |
| 3752 | return cc + LINK_SIZE; | |
| 3753 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
| 3754 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
| 3755 | if (common->utf) | if (common->utf) |
| # | Line 3421 switch(type) | Line 3757 switch(type) |
| 3757 | OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); |
| 3758 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); |
| 3759 | label = LABEL(); | label = LABEL(); |
| 3760 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0)); |
| 3761 | skip_char_back(common); | skip_char_back(common); |
| 3762 | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); |
| 3763 | JUMPTO(SLJIT_C_NOT_ZERO, label); | JUMPTO(SLJIT_C_NOT_ZERO, label); |
| return cc + LINK_SIZE; | ||
| 3764 | } | } |
| 3765 | else | |
| 3766 | #endif | #endif |
| 3767 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); | { |
| 3768 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); |
| 3769 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); |
| 3770 | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); | |
| 3771 | } | |
| 3772 | check_start_used_ptr(common); | |
| 3773 | return cc + LINK_SIZE; | return cc + LINK_SIZE; |
| 3774 | } | } |
| 3775 | SLJIT_ASSERT_STOP(); | SLJIT_ASSERT_STOP(); |
| 3776 | return cc; | return cc; |
| 3777 | } | } |
| 3778 | ||
| 3779 | static SLJIT_INLINE pcre_uchar *compile_charn_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **fallbacks) | static SLJIT_INLINE pcre_uchar *compile_charn_trypath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **backtracks) |
| 3780 | { | { |
| 3781 | /* This function consumes at least one input character. */ | /* This function consumes at least one input character. */ |
| 3782 | /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */ | /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */ |
| # | Line 3489 if (context.length > 0) | Line 3828 if (context.length > 0) |
| 3828 | { | { |
| 3829 | /* We have a fixed-length byte sequence. */ | /* We have a fixed-length byte sequence. */ |
| 3830 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length); |
| 3831 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); |
| 3832 | ||
| 3833 | context.sourcereg = -1; | context.sourcereg = -1; |
| 3834 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED |
| 3835 | context.ucharptr = 0; | context.ucharptr = 0; |
| 3836 | #endif | #endif |
| 3837 | do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, fallbacks); while (context.length > 0); | do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0); |
| 3838 | return cc; | return cc; |
| 3839 | } | } |
| 3840 | ||
| 3841 | /* A non-fixed length character will be checked if length == 0. */ | /* A non-fixed length character will be checked if length == 0. */ |
| 3842 | return compile_char1_hotpath(common, *cc, cc + 1, fallbacks); | return compile_char1_trypath(common, *cc, cc + 1, backtracks); |
| 3843 | } | } |
| 3844 | ||
| 3845 | static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks) | static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **backtracks) |
| 3846 | { | { |
| 3847 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 3848 | int offset = GET2(cc, 1) << 1; | int offset = GET2(cc, 1) << 1; |
| # | Line 3511 int offset = GET2(cc, 1) << 1; | Line 3850 int offset = GET2(cc, 1) << 1; |
| 3850 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
| 3851 | if (!common->jscript_compat) | if (!common->jscript_compat) |
| 3852 | { | { |
| 3853 | if (fallbacks == NULL) | if (backtracks == NULL) |
| 3854 | { | { |
| 3855 | /* OVECTOR(1) contains the "string begin - 1" constant. */ | |
| 3856 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
| 3857 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
| 3858 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
| 3859 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
| 3860 | return JUMP(SLJIT_C_NOT_ZERO); | return JUMP(SLJIT_C_NOT_ZERO); |
| 3861 | } | } |
| 3862 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); |
| 3863 | } | } |
| 3864 | return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); | return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
| 3865 | } | } |
| 3866 | ||
| 3867 | /* Forward definitions. */ | /* Forward definitions. */ |
| 3868 | static void compile_hotpath(compiler_common *, pcre_uchar *, pcre_uchar *, fallback_common *); | static void compile_trypath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *); |
| 3869 | static void compile_fallbackpath(compiler_common *, struct fallback_common *); | static void compile_backtrackpath(compiler_common *, struct backtrack_common *); |
| 3870 | ||
| 3871 | #define PUSH_FALLBACK(size, ccstart, error) \ | #define PUSH_BACKTRACK(size, ccstart, error) \ |
| 3872 | do \ | do \ |
| 3873 | { \ | { \ |
| 3874 | fallback = sljit_alloc_memory(compiler, (size)); \ | backtrack = sljit_alloc_memory(compiler, (size)); \ |
| 3875 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ |
| 3876 | return error; \ | return error; \ |
| 3877 | memset(fallback, 0, size); \ | memset(backtrack, 0, size); \ |
| 3878 | fallback->prev = parent->top; \ | backtrack->prev = parent->top; \ |
| 3879 | fallback->cc = (ccstart); \ | backtrack->cc = (ccstart); \ |
| 3880 | parent->top = fallback; \ | parent->top = backtrack; \ |
| 3881 | } \ | } \ |
| 3882 | while (0) | while (0) |
| 3883 | ||
| 3884 | #define PUSH_FALLBACK_NOVALUE(size, ccstart) \ | #define PUSH_BACKTRACK_NOVALUE(size, ccstart) \ |
| 3885 | do \ | do \ |
| 3886 | { \ | { \ |
| 3887 | fallback = sljit_alloc_memory(compiler, (size)); \ | backtrack = sljit_alloc_memory(compiler, (size)); \ |
| 3888 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ |
| 3889 | return; \ | return; \ |
| 3890 | memset(fallback, 0, size); \ | memset(backtrack, 0, size); \ |
| 3891 | fallback->prev = parent->top; \ | backtrack->prev = parent->top; \ |
| 3892 | fallback->cc = (ccstart); \ | backtrack->cc = (ccstart); \ |
| 3893 | parent->top = fallback; \ | parent->top = backtrack; \ |
| 3894 | } \ | } \ |
| 3895 | while (0) | while (0) |
| 3896 | ||
| 3897 | #define FALLBACK_AS(type) ((type*)fallback) | #define BACKTRACK_AS(type) ((type *)backtrack) |
| 3898 | ||
| 3899 | static pcre_uchar *compile_ref_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail) | static pcre_uchar *compile_ref_trypath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail) |
| 3900 | { | { |
| 3901 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 3902 | int offset = GET2(cc, 1) << 1; | int offset = GET2(cc, 1) << 1; |
| 3903 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
| 3904 | struct sljit_jump *partial; | |
| 3905 | struct sljit_jump *nopartial; | |
| 3906 | ||
| 3907 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
| 3908 | /* OVECTOR(1) contains the "string begin - 1" constant. */ | |
| 3909 | if (withchecks && !common->jscript_compat) | if (withchecks && !common->jscript_compat) |
| 3910 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); |
| 3911 | ||
| 3912 | #if defined SUPPORT_UTF && defined SUPPORT_UCP | #if defined SUPPORT_UTF && defined SUPPORT_UCP |
| 3913 | if (common->utf && *cc == OP_REFI) | if (common->utf && *cc == OP_REFI) |
| # | Line 3577 if (common->utf && *cc == OP_REFI) | Line 3920 if (common->utf && *cc == OP_REFI) |
| 3920 | /* Needed to save important temporary registers. */ | /* Needed to save important temporary registers. */ |
| 3921 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
| 3922 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); |
| 3923 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, ptr), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0); |
| 3924 | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); |
| 3925 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
| 3926 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); | if (common->mode == JIT_COMPILE) |
| 3927 | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1)); | |
| 3928 | else | |
| 3929 | { | |
| 3930 | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); | |
| 3931 | nopartial = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); | |
| 3932 | check_partial(common, FALSE); | |
| 3933 | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); | |
| 3934 | JUMPHERE(nopartial); | |
| 3935 | } | |
| 3936 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); |
| 3937 | } | } |
| 3938 | else | else |
| # | Line 3589 else | Line 3941 else |
| 3941 | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); |
| 3942 | if (withchecks) | if (withchecks) |
| 3943 | jump = JUMP(SLJIT_C_ZERO); | jump = JUMP(SLJIT_C_ZERO); |
| 3944 | ||
| 3945 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
| 3946 | partial = CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0); | |
| 3947 | if (common->mode == JIT_COMPILE) | |
| 3948 | add_jump(compiler, backtracks, partial); | |
| 3949 | ||
| add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); | ||
| 3950 | add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); |
| 3951 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
| 3952 | ||
| 3953 | if (common->mode != JIT_COMPILE) | |
| 3954 | { | |
| 3955 | nopartial = JUMP(SLJIT_JUMP); | |
| 3956 | JUMPHERE(partial); | |
| 3957 | /* TMP2 -= STR_END - STR_PTR */ | |
| 3958 | OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0); | |
| 3959 | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0); | |
| 3960 | partial = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0); | |
| 3961 | OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); | |
| 3962 | add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); | |
| 3963 | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | |
| 3964 | JUMPHERE(partial); | |
| 3965 | check_partial(common, FALSE); | |
| 3966 | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); | |
| 3967 | JUMPHERE(nopartial); | |
| 3968 | } | |
| 3969 | } | } |
| 3970 | ||
| 3971 | if (jump != NULL) | if (jump != NULL) |
| 3972 | { | { |
| 3973 | if (emptyfail) | if (emptyfail) |
| 3974 | add_jump(compiler, fallbacks, jump); | add_jump(compiler, backtracks, jump); |
| 3975 | else | else |
| 3976 | JUMPHERE(jump); | JUMPHERE(jump); |
| 3977 | } | } |
| 3978 | return cc + 1 + IMM2_SIZE; | return cc + 1 + IMM2_SIZE; |
| 3979 | } | } |
| 3980 | ||
| 3981 | static SLJIT_INLINE pcre_uchar *compile_ref_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) | static SLJIT_INLINE pcre_uchar *compile_ref_iterator_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
| 3982 | { | { |
| 3983 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 3984 | fallback_common *fallback; | backtrack_common *backtrack; |
| 3985 | pcre_uchar type; | pcre_uchar type; |
| 3986 | struct sljit_label *label; | struct sljit_label *label; |
| 3987 | struct sljit_jump *zerolength; | struct sljit_jump *zerolength; |
| # | Line 3618 pcre_uchar *ccbegin = cc; | Line 3990 pcre_uchar *ccbegin = cc; |
| 3990 | int min = 0, max = 0; | int min = 0, max = 0; |
| 3991 | BOOL minimize; | BOOL minimize; |
| 3992 | ||
| 3993 | PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL); |
| 3994 | ||
| 3995 | type = cc[1 + IMM2_SIZE]; | type = cc[1 + IMM2_SIZE]; |
| 3996 | minimize = (type & 0x1) != 0; | minimize = (type & 0x1) != 0; |
| # | Line 3670 if (!minimize) | Line 4042 if (!minimize) |
| 4042 | { | { |
| 4043 | allocate_stack(common, 1); | allocate_stack(common, 1); |
| 4044 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
| 4045 | zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks); | zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks); |
| 4046 | } | } |
| 4047 | ||
| 4048 | if (min > 1 || max > 1) | if (min > 1 || max > 1) |
| 4049 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); |
| 4050 | ||
| 4051 | label = LABEL(); | label = LABEL(); |
| 4052 | compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, FALSE, FALSE); | compile_ref_trypath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE); |
| 4053 | ||
| 4054 | if (min > 1 || max > 1) | if (min > 1 || max > 1) |
| 4055 | { | { |
| # | Line 3705 if (!minimize) | Line 4077 if (!minimize) |
| 4077 | } | } |
| 4078 | ||
| 4079 | JUMPHERE(zerolength); | JUMPHERE(zerolength); |
| 4080 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); |
| 4081 | ||
| 4082 | decrease_call_count(common); | decrease_call_count(common); |
| 4083 | return cc; | return cc; |
| # | Line 3723 if (min == 0) | Line 4095 if (min == 0) |
| 4095 | jump = JUMP(SLJIT_JUMP); | jump = JUMP(SLJIT_JUMP); |
| 4096 | } | } |
| 4097 | else | else |
| 4098 | zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks); | zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks); |
| 4099 | ||
| 4100 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); |
| 4101 | if (max > 0) | if (max > 0) |
| 4102 | add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max)); | add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max)); |
| 4103 | ||
| 4104 | compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, TRUE, TRUE); | compile_ref_trypath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE); |
| 4105 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
| 4106 | ||
| 4107 | if (min > 1) | if (min > 1) |
| # | Line 3737 if (min > 1) | Line 4109 if (min > 1) |
| 4109 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
| 4110 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
| 4111 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); |
| 4112 | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, FALLBACK_AS(iterator_fallback)->hotpath); | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(iterator_backtrack)->trypath); |
| 4113 | } | } |
| 4114 | else if (max > 0) | else if (max > 0) |
| 4115 | OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); | OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); |
| # | Line 3750 decrease_call_count(common); | Line 4122 decrease_call_count(common); |
| 4122 | return cc; | return cc; |
| 4123 | } | } |
| 4124 | ||
| 4125 | static SLJIT_INLINE pcre_uchar *compile_recurse_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) | static SLJIT_INLINE pcre_uchar *compile_recurse_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
| 4126 | { | { |
| 4127 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 4128 | fallback_common *fallback; | backtrack_common *backtrack; |
| 4129 | recurse_entry *entry = common->entries; | recurse_entry *entry = common->entries; |
| 4130 | recurse_entry *prev = NULL; | recurse_entry *prev = NULL; |
| 4131 | int start = GET(cc, 1); | int start = GET(cc, 1); |
| 4132 | ||
| 4133 | PUSH_FALLBACK(sizeof(recurse_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL); |
| 4134 | while (entry != NULL) | while (entry != NULL) |
| 4135 | { | { |
| 4136 | if (entry->start == start) | if (entry->start == start) |
| # | Line 3783 if (entry == NULL) | Line 4155 if (entry == NULL) |
| 4155 | common->entries = entry; | common->entries = entry; |
| 4156 | } | } |
| 4157 | ||
| 4158 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | if (common->has_set_som && common->mark_ptr != 0) |
| 4159 | allocate_stack(common, 1); | { |
| 4160 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
| 4161 | allocate_stack(common, 2); | |
| 4162 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | |
| 4163 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); | |
| 4164 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); | |
| 4165 | } | |
| 4166 | else if (common->has_set_som || common->mark_ptr != 0) | |
| 4167 | { | |
| 4168 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr); | |
| 4169 | allocate_stack(common, 1); | |
| 4170 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); | |
| 4171 | } | |
| 4172 | ||
| 4173 | if (entry->entry == NULL) | if (entry->entry == NULL) |
| 4174 | add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL)); |
| 4175 | else | else |
| 4176 | JUMPTO(SLJIT_FAST_CALL, entry->entry); | JUMPTO(SLJIT_FAST_CALL, entry->entry); |
| 4177 | /* Leave if the match is failed. */ | /* Leave if the match is failed. */ |
| 4178 | add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0)); | add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0)); |
| 4179 | return cc + 1 + LINK_SIZE; | return cc + 1 + LINK_SIZE; |
| 4180 | } | } |
| 4181 | ||
| 4182 | static pcre_uchar *compile_assert_hotpath(compiler_common *common, pcre_uchar *cc, assert_fallback *fallback, BOOL conditional) | static pcre_uchar *compile_assert_trypath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional) |
| 4183 | { | { |
| 4184 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 4185 | int framesize; | int framesize; |
| 4186 | int localptr; | int localptr; |
| 4187 | fallback_common altfallback; | backtrack_common altbacktrack; |
| 4188 | pcre_uchar *ccbegin; | pcre_uchar *ccbegin; |
| 4189 | pcre_uchar opcode; | pcre_uchar opcode; |
| 4190 | pcre_uchar bra = OP_BRA; | pcre_uchar bra = OP_BRA; |
| 4191 | jump_list *tmp = NULL; | jump_list *tmp = NULL; |
| 4192 | jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks; | jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks; |
| 4193 | jump_list **found; | jump_list **found; |
| 4194 | /* Saving previous accept variables. */ | /* Saving previous accept variables. */ |
| 4195 | struct sljit_label *save_leavelabel = common->leavelabel; | |
| 4196 | struct sljit_label *save_acceptlabel = common->acceptlabel; | struct sljit_label *save_acceptlabel = common->acceptlabel; |
| 4197 | jump_list *save_leave = common->leave; | |
| 4198 | jump_list *save_accept = common->accept; | |
| 4199 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| 4200 | struct sljit_jump *brajump = NULL; | struct sljit_jump *brajump = NULL; |
| jump_list *save_accept = common->accept; | ||
| 4201 | ||
| 4202 | if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) | if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) |
| 4203 | { | { |
| # | Line 3823 if (*cc == OP_BRAZERO || *cc == OP_BRAMI | Line 4208 if (*cc == OP_BRAZERO || *cc == OP_BRAMI |
| 4208 | localptr = PRIV_DATA(cc); | localptr = PRIV_DATA(cc); |
| 4209 | SLJIT_ASSERT(localptr != 0); | SLJIT_ASSERT(localptr != 0); |
| 4210 | framesize = get_framesize(common, cc, FALSE); | framesize = get_framesize(common, cc, FALSE); |
| 4211 | fallback->framesize = framesize; | backtrack->framesize = framesize; |
| 4212 | fallback->localptr = localptr; | backtrack->localptr = localptr; |
| 4213 | opcode = *cc; | opcode = *cc; |
| 4214 | SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT); | SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT); |
| 4215 | found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target; | found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target; |
| # | Line 3833 cc += GET(cc, 1); | Line 4218 cc += GET(cc, 1); |
| 4218 | ||
| 4219 | if (bra == OP_BRAMINZERO) | if (bra == OP_BRAMINZERO) |
| 4220 | { | { |
| 4221 | /* This is a braminzero fallback path. */ | /* This is a braminzero backtrack path. */ |
| 4222 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 4223 | free_stack(common, 1); | free_stack(common, 1); |
| 4224 | brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); | brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); |
| # | Line 3856 else | Line 4241 else |
| 4241 | init_frame(common, ccbegin, framesize + 1, 2, FALSE); | init_frame(common, ccbegin, framesize + 1, 2, FALSE); |
| 4242 | } | } |
| 4243 | ||
| 4244 | memset(&altfallback, 0, sizeof(fallback_common)); | memset(&altbacktrack, 0, sizeof(backtrack_common)); |
| 4245 | common->leavelabel = NULL; | |
| 4246 | common->leave = NULL; | |
| 4247 | while (1) | while (1) |
| 4248 | { | { |
| 4249 | common->acceptlabel = NULL; | common->acceptlabel = NULL; |
| 4250 | common->accept = NULL; | common->accept = NULL; |
| 4251 | altfallback.top = NULL; | altbacktrack.top = NULL; |
| 4252 | altfallback.topfallbacks = NULL; | altbacktrack.topbacktracks = NULL; |
| 4253 | ||
| 4254 | if (*ccbegin == OP_ALT) | if (*ccbegin == OP_ALT) |
| 4255 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 4256 | ||
| 4257 | altfallback.cc = ccbegin; | altbacktrack.cc = ccbegin; |
| 4258 | compile_hotpath(common, ccbegin + 1 + LINK_SIZE, cc, &altfallback); | compile_trypath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); |
| 4259 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
| 4260 | { | { |
| 4261 | common->leavelabel = save_leavelabel; | |
| 4262 | common->acceptlabel = save_acceptlabel; | common->acceptlabel = save_acceptlabel; |
| 4263 | common->leave = save_leave; | |
| 4264 | common->accept = save_accept; | common->accept = save_accept; |
| 4265 | return NULL; | return NULL; |
| 4266 | } | } |
| # | Line 3921 while (1) | Line 4310 while (1) |
| 4310 | } | } |
| 4311 | add_jump(compiler, found, JUMP(SLJIT_JUMP)); | add_jump(compiler, found, JUMP(SLJIT_JUMP)); |
| 4312 | ||
| 4313 | compile_fallbackpath(common, altfallback.top); | compile_backtrackpath(common, altbacktrack.top); |
| 4314 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
| 4315 | { | { |
| 4316 | common->leavelabel = save_leavelabel; | |
| 4317 | common->acceptlabel = save_acceptlabel; | common->acceptlabel = save_acceptlabel; |
| 4318 | common->leave = save_leave; | |
| 4319 | common->accept = save_accept; | common->accept = save_accept; |
| 4320 | return NULL; | return NULL; |
| 4321 | } | } |
| 4322 | set_jumps(altfallback.topfallbacks, LABEL()); | set_jumps(altbacktrack.topbacktracks, LABEL()); |
| 4323 | ||
| 4324 | if (*cc != OP_ALT) | if (*cc != OP_ALT) |
| 4325 | break; | break; |
| # | Line 3937 while (1) | Line 4328 while (1) |
| 4328 | cc += GET(cc, 1); | cc += GET(cc, 1); |
| 4329 | } | } |
| 4330 | /* None of them matched. */ | /* None of them matched. */ |
| 4331 | if (common->leave != NULL) | |
| 4332 | set_jumps(common->leave, LABEL()); | |
| 4333 | ||
| 4334 | if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) | if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) |
| 4335 | { | { |
| # | Line 4003 if (opcode == OP_ASSERT || opcode == OP_ | Line 4396 if (opcode == OP_ASSERT || opcode == OP_ |
| 4396 | ||
| 4397 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
| 4398 | { | { |
| 4399 | fallback->hotpath = LABEL(); | backtrack->trypath = LABEL(); |
| 4400 | sljit_set_label(jump, fallback->hotpath); | sljit_set_label(jump, backtrack->trypath); |
| 4401 | } | } |
| 4402 | else if (bra == OP_BRAMINZERO) | else if (bra == OP_BRAMINZERO) |
| 4403 | { | { |
| 4404 | JUMPTO(SLJIT_JUMP, fallback->hotpath); | JUMPTO(SLJIT_JUMP, backtrack->trypath); |
| 4405 | JUMPHERE(brajump); | JUMPHERE(brajump); |
| 4406 | if (framesize >= 0) | if (framesize >= 0) |
| 4407 | { | { |
| # | Line 4016 if (opcode == OP_ASSERT || opcode == OP_ | Line 4409 if (opcode == OP_ASSERT || opcode == OP_ |
| 4409 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
| 4410 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); |
| 4411 | } | } |
| 4412 | set_jumps(fallback->common.topfallbacks, LABEL()); | set_jumps(backtrack->common.topbacktracks, LABEL()); |
| 4413 | } | } |
| 4414 | } | } |
| 4415 | else | else |
| # | Line 4046 else | Line 4439 else |
| 4439 | } | } |
| 4440 | ||
| 4441 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
| 4442 | fallback->hotpath = LABEL(); | backtrack->trypath = LABEL(); |
| 4443 | else if (bra == OP_BRAMINZERO) | else if (bra == OP_BRAMINZERO) |
| 4444 | { | { |
| 4445 | JUMPTO(SLJIT_JUMP, fallback->hotpath); | JUMPTO(SLJIT_JUMP, backtrack->trypath); |
| 4446 | JUMPHERE(brajump); | JUMPHERE(brajump); |
| 4447 | } | } |
| 4448 | ||
| 4449 | if (bra != OP_BRA) | if (bra != OP_BRA) |
| 4450 | { | { |
| 4451 | SLJIT_ASSERT(found == &fallback->common.topfallbacks); | SLJIT_ASSERT(found == &backtrack->common.topbacktracks); |
| 4452 | set_jumps(fallback->common.topfallbacks, LABEL()); | set_jumps(backtrack->common.topbacktracks, LABEL()); |
| 4453 | fallback->common.topfallbacks = NULL; | backtrack->common.topbacktracks = NULL; |
| 4454 | } | } |
| 4455 | } | } |
| 4456 | ||
| 4457 | common->leavelabel = save_leavelabel; | |
| 4458 | common->acceptlabel = save_acceptlabel; | common->acceptlabel = save_acceptlabel; |
| 4459 | common->leave = save_leave; | |
| 4460 | common->accept = save_accept; | common->accept = save_accept; |
| 4461 | return cc + 1 + LINK_SIZE; | return cc + 1 + LINK_SIZE; |
| 4462 | } | } |
| # | Line 4076 sljit_w name_entry_size = locals[LOCALS1 | Line 4471 sljit_w name_entry_size = locals[LOCALS1 |
| 4471 | sljit_w no_capture; | sljit_w no_capture; |
| 4472 | int i; | int i; |
| 4473 | ||
| 4474 | locals += OVECTOR_START / sizeof(sljit_w); | locals += refno & 0xff; |
| 4475 | refno >>= 8; | |
| 4476 | no_capture = locals[1]; | no_capture = locals[1]; |
| 4477 | ||
| 4478 | for (i = 0; i < name_count; i++) | for (i = 0; i < name_count; i++) |
| # | Line 4229 return condition; | Line 4625 return condition; |
| 4625 | Or nothing, if trace is unnecessary | Or nothing, if trace is unnecessary |
| 4626 | */ | */ |
| 4627 | ||
| 4628 | static pcre_uchar *compile_bracket_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) | static pcre_uchar *compile_bracket_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
| 4629 | { | { |
| 4630 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 4631 | fallback_common *fallback; | backtrack_common *backtrack; |
| 4632 | pcre_uchar opcode; | pcre_uchar opcode; |
| 4633 | int localptr = 0; | int localptr = 0; |
| 4634 | int offset = 0; | int offset = 0; |
| 4635 | int stacksize; | int stacksize; |
| 4636 | pcre_uchar *ccbegin; | pcre_uchar *ccbegin; |
| 4637 | pcre_uchar *hotpath; | pcre_uchar *trypath; |
| 4638 | pcre_uchar bra = OP_BRA; | pcre_uchar bra = OP_BRA; |
| 4639 | pcre_uchar ket; | pcre_uchar ket; |
| 4640 | assert_fallback *assert; | assert_backtrack *assert; |
| 4641 | BOOL has_alternatives; | BOOL has_alternatives; |
| 4642 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| 4643 | struct sljit_jump *skip; | struct sljit_jump *skip; |
| 4644 | struct sljit_label *rmaxlabel = NULL; | struct sljit_label *rmaxlabel = NULL; |
| 4645 | struct sljit_jump *braminzerojump = NULL; | struct sljit_jump *braminzerojump = NULL; |
| 4646 | ||
| 4647 | PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL); |
| 4648 | ||
| 4649 | if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) | if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) |
| 4650 | { | { |
| # | Line 4259 if (*cc == OP_BRAZERO || *cc == OP_BRAMI | Line 4655 if (*cc == OP_BRAZERO || *cc == OP_BRAMI |
| 4655 | ||
| 4656 | opcode = *cc; | opcode = *cc; |
| 4657 | ccbegin = cc; | ccbegin = cc; |
| 4658 | hotpath = ccbegin + 1 + LINK_SIZE; | trypath = ccbegin + 1 + LINK_SIZE; |
| 4659 | ||
| 4660 | if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF) | if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF) |
| 4661 | { | { |
| 4662 | /* Drop this bracket_fallback. */ | /* Drop this bracket_backtrack. */ |
| 4663 | parent->top = fallback->prev; | parent->top = backtrack->prev; |
| 4664 | return bracketend(cc); | return bracketend(cc); |
| 4665 | } | } |
| 4666 | ||
| # | Line 4276 cc += GET(cc, 1); | Line 4672 cc += GET(cc, 1); |
| 4672 | has_alternatives = *cc == OP_ALT; | has_alternatives = *cc == OP_ALT; |
| 4673 | if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) | if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) |
| 4674 | { | { |
| 4675 | has_alternatives = (*hotpath == OP_RREF) ? FALSE : TRUE; | has_alternatives = (*trypath == OP_RREF) ? FALSE : TRUE; |
| 4676 | if (*hotpath == OP_NRREF) | if (*trypath == OP_NRREF) |
| 4677 | { | { |
| 4678 | stacksize = GET2(hotpath, 1); | stacksize = GET2(trypath, 1); |
| 4679 | if (common->currententry == NULL || stacksize == RREF_ANY) | if (common->currententry == NULL || stacksize == RREF_ANY) |
| 4680 | has_alternatives = FALSE; | has_alternatives = FALSE; |
| 4681 | else if (common->currententry->start == 0) | else if (common->currententry->start == 0) |
| # | Line 4300 if (opcode == OP_CBRA || opcode == OP_SC | Line 4696 if (opcode == OP_CBRA || opcode == OP_SC |
| 4696 | offset = GET2(ccbegin, 1 + LINK_SIZE); | offset = GET2(ccbegin, 1 + LINK_SIZE); |
| 4697 | localptr = OVECTOR_PRIV(offset); | localptr = OVECTOR_PRIV(offset); |
| 4698 | offset <<= 1; | offset <<= 1; |
| 4699 | FALLBACK_AS(bracket_fallback)->localptr = localptr; | BACKTRACK_AS(bracket_backtrack)->localptr = localptr; |
| 4700 | hotpath += IMM2_SIZE; | trypath += IMM2_SIZE; |
| 4701 | } | } |
| 4702 | else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND) | else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND) |
| 4703 | { | { |
| 4704 | /* Other brackets simply allocate the next entry. */ | /* Other brackets simply allocate the next entry. */ |
| 4705 | localptr = PRIV_DATA(ccbegin); | localptr = PRIV_DATA(ccbegin); |
| 4706 | SLJIT_ASSERT(localptr != 0); | SLJIT_ASSERT(localptr != 0); |
| 4707 | FALLBACK_AS(bracket_fallback)->localptr = localptr; | BACKTRACK_AS(bracket_backtrack)->localptr = localptr; |
| 4708 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
| 4709 | FALLBACK_AS(bracket_fallback)->u.framesize = get_framesize(common, ccbegin, FALSE); | BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, FALSE); |
| 4710 | } | } |
| 4711 | ||
| 4712 | /* Instructions before the first alternative. */ | /* Instructions before the first alternative. */ |
| # | Line 4335 if (bra == OP_BRAZERO) | Line 4731 if (bra == OP_BRAZERO) |
| 4731 | ||
| 4732 | if (bra == OP_BRAMINZERO) | if (bra == OP_BRAMINZERO) |
| 4733 | { | { |
| 4734 | /* This is a fallback path! (Since the hot-path of OP_BRAMINZERO matches to the empty string) */ | /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */ |
| 4735 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 4736 | if (ket != OP_KETRMIN) | if (ket != OP_KETRMIN) |
| 4737 | { | { |
| # | Line 4352 if (bra == OP_BRAMINZERO) | Line 4748 if (bra == OP_BRAMINZERO) |
| 4748 | skip = JUMP(SLJIT_JUMP); | skip = JUMP(SLJIT_JUMP); |
| 4749 | JUMPHERE(jump); | JUMPHERE(jump); |
| 4750 | /* Checking zero-length iteration. */ | /* Checking zero-length iteration. */ |
| 4751 | if (opcode != OP_ONCE || FALLBACK_AS(bracket_fallback)->u.framesize < 0) | if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
| 4752 | { | { |
| 4753 | /* When we come from outside, localptr contains the previous STR_PTR. */ | /* When we come from outside, localptr contains the previous STR_PTR. */ |
| 4754 | braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| # | Line 4361 if (bra == OP_BRAMINZERO) | Line 4757 if (bra == OP_BRAMINZERO) |
| 4757 | { | { |
| 4758 | /* Except when the whole stack frame must be saved. */ | /* Except when the whole stack frame must be saved. */ |
| 4759 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| 4760 | braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w)); | braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_w)); |
| 4761 | } | } |
| 4762 | JUMPHERE(skip); | JUMPHERE(skip); |
| 4763 | } | } |
| # | Line 4375 if (bra == OP_BRAMINZERO) | Line 4771 if (bra == OP_BRAMINZERO) |
| 4771 | } | } |
| 4772 | ||
| 4773 | if (ket == OP_KETRMIN) | if (ket == OP_KETRMIN) |
| 4774 | FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL(); | BACKTRACK_AS(bracket_backtrack)->recursivetrypath = LABEL(); |
| 4775 | ||
| 4776 | if (ket == OP_KETRMAX) | if (ket == OP_KETRMAX) |
| 4777 | { | { |
| 4778 | rmaxlabel = LABEL(); | rmaxlabel = LABEL(); |
| 4779 | if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA) | if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA) |
| 4780 | FALLBACK_AS(bracket_fallback)->althotpath = rmaxlabel; | BACKTRACK_AS(bracket_backtrack)->alttrypath = rmaxlabel; |
| 4781 | } | } |
| 4782 | ||
| 4783 | /* Handling capturing brackets and alternatives. */ | /* Handling capturing brackets and alternatives. */ |
| 4784 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
| 4785 | { | { |
| 4786 | if (FALLBACK_AS(bracket_fallback)->u.framesize < 0) | if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
| 4787 | { | { |
| 4788 | /* Neither capturing brackets nor recursions are not found in the block. */ | /* Neither capturing brackets nor recursions are not found in the block. */ |
| 4789 | if (ket == OP_KETRMIN) | if (ket == OP_KETRMIN) |
| # | Line 4411 if (opcode == OP_ONCE) | Line 4807 if (opcode == OP_ONCE) |
| 4807 | { | { |
| 4808 | if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) | if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) |
| 4809 | { | { |
| 4810 | allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 2); | allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 2); |
| 4811 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| 4812 | OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize + 1)); | OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize + 1)); |
| 4813 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
| 4814 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); |
| 4815 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); |
| 4816 | init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize + 1, 2, FALSE); | init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1, 2, FALSE); |
| 4817 | } | } |
| 4818 | else | else |
| 4819 | { | { |
| 4820 | allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 1); | allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1); |
| 4821 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| 4822 | OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize)); | OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize)); |
| 4823 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); |
| 4824 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); |
| 4825 | init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize, 1, FALSE); | init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize, 1, FALSE); |
| 4826 | } | } |
| 4827 | } | } |
| 4828 | } | } |
| # | Line 4460 else if (has_alternatives) | Line 4856 else if (has_alternatives) |
| 4856 | /* Generating code for the first alternative. */ | /* Generating code for the first alternative. */ |
| 4857 | if (opcode == OP_COND || opcode == OP_SCOND) | if (opcode == OP_COND || opcode == OP_SCOND) |
| 4858 | { | { |
| 4859 | if (*hotpath == OP_CREF) | if (*trypath == OP_CREF) |
| 4860 | { | { |
| 4861 | SLJIT_ASSERT(has_alternatives); | SLJIT_ASSERT(has_alternatives); |
| 4862 | add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), | add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), |
| 4863 | CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(hotpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); | CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(trypath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); |
| 4864 | hotpath += 1 + IMM2_SIZE; | trypath += 1 + IMM2_SIZE; |
| 4865 | } | } |
| 4866 | else if (*hotpath == OP_NCREF) | else if (*trypath == OP_NCREF) |
| 4867 | { | { |
| 4868 | SLJIT_ASSERT(has_alternatives); | SLJIT_ASSERT(has_alternatives); |
| 4869 | stacksize = GET2(hotpath, 1); | stacksize = GET2(trypath, 1); |
| 4870 | jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); | jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
| 4871 | ||
| 4872 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); |
| 4873 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); |
| 4874 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); |
| 4875 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, (stacksize << 8) | (common->ovector_start / sizeof(sljit_w))); |
| 4876 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0); | GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0); |
| 4877 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); |
| 4878 | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector)); | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector)); |
| 4879 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); |
| 4880 | add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); | add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); |
| 4881 | ||
| 4882 | JUMPHERE(jump); | JUMPHERE(jump); |
| 4883 | hotpath += 1 + IMM2_SIZE; | trypath += 1 + IMM2_SIZE; |
| 4884 | } | } |
| 4885 | else if (*hotpath == OP_RREF || *hotpath == OP_NRREF) | else if (*trypath == OP_RREF || *trypath == OP_NRREF) |
| 4886 | { | { |
| 4887 | /* Never has other case. */ | /* Never has other case. */ |
| 4888 | FALLBACK_AS(bracket_fallback)->u.condfailed = NULL; | BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL; |
| 4889 | ||
| 4890 | stacksize = GET2(hotpath, 1); | stacksize = GET2(trypath, 1); |
| 4891 | if (common->currententry == NULL) | if (common->currententry == NULL) |
| 4892 | stacksize = 0; | stacksize = 0; |
| 4893 | else if (stacksize == RREF_ANY) | else if (stacksize == RREF_ANY) |
| # | Line 4501 if (opcode == OP_COND || opcode == OP_SC | Line 4897 if (opcode == OP_COND || opcode == OP_SC |
| 4897 | else | else |
| 4898 | stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE); | stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE); |
| 4899 | ||
| 4900 | if (*hotpath == OP_RREF || stacksize || common->currententry == NULL) | if (*trypath == OP_RREF || stacksize || common->currententry == NULL) |
| 4901 | { | { |
| 4902 | SLJIT_ASSERT(!has_alternatives); | SLJIT_ASSERT(!has_alternatives); |
| 4903 | if (stacksize != 0) | if (stacksize != 0) |
| 4904 | hotpath += 1 + IMM2_SIZE; | trypath += 1 + IMM2_SIZE; |
| 4905 | else | else |
| 4906 | { | { |
| 4907 | if (*cc == OP_ALT) | if (*cc == OP_ALT) |
| 4908 | { | { |
| 4909 | hotpath = cc + 1 + LINK_SIZE; | trypath = cc + 1 + LINK_SIZE; |
| 4910 | cc += GET(cc, 1); | cc += GET(cc, 1); |
| 4911 | } | } |
| 4912 | else | else |
| 4913 | hotpath = cc; | trypath = cc; |
| 4914 | } | } |
| 4915 | } | } |
| 4916 | else | else |
| 4917 | { | { |
| 4918 | SLJIT_ASSERT(has_alternatives); | SLJIT_ASSERT(has_alternatives); |
| 4919 | ||
| 4920 | stacksize = GET2(hotpath, 1); | stacksize = GET2(trypath, 1); |
| 4921 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); |
| 4922 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); |
| 4923 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); |
| 4924 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE)); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE)); |
| 4925 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); |
| 4926 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0); | GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0); |
| 4927 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); |
| 4928 | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups)); | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups)); |
| 4929 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); |
| 4930 | add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); | add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); |
| 4931 | hotpath += 1 + IMM2_SIZE; | trypath += 1 + IMM2_SIZE; |
| 4932 | } | } |
| 4933 | } | } |
| 4934 | else | else |
| 4935 | { | { |
| 4936 | SLJIT_ASSERT(has_alternatives && *hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT); | SLJIT_ASSERT(has_alternatives && *trypath >= OP_ASSERT && *trypath <= OP_ASSERTBACK_NOT); |
| 4937 | /* Similar code as PUSH_FALLBACK macro. */ | /* Similar code as PUSH_BACKTRACK macro. */ |
| 4938 | assert = sljit_alloc_memory(compiler, sizeof(assert_fallback)); | assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack)); |
| 4939 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
| 4940 | return NULL; | return NULL; |
| 4941 | memset(assert, 0, sizeof(assert_fallback)); | memset(assert, 0, sizeof(assert_backtrack)); |
| 4942 | assert->common.cc = hotpath; | assert->common.cc = trypath; |
| 4943 | FALLBACK_AS(bracket_fallback)->u.assert = assert; | BACKTRACK_AS(bracket_backtrack)->u.assert = assert; |
| 4944 | hotpath = compile_assert_hotpath(common, hotpath, assert, TRUE); | trypath = compile_assert_trypath(common, trypath, assert, TRUE); |
| 4945 | } | } |
| 4946 | } | } |
| 4947 | ||
| 4948 | compile_hotpath(common, hotpath, cc, fallback); | compile_trypath(common, trypath, cc, backtrack); |
| 4949 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
| 4950 | return NULL; | return NULL; |
| 4951 | ||
| 4952 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
| 4953 | { | { |
| 4954 | if (FALLBACK_AS(bracket_fallback)->u.framesize < 0) | if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
| 4955 | { | { |
| 4956 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| 4957 | /* TMP2 which is set here used by OP_KETRMAX below. */ | /* TMP2 which is set here used by OP_KETRMAX below. */ |
| # | Line 4570 if (opcode == OP_ONCE) | Line 4966 if (opcode == OP_ONCE) |
| 4966 | else | else |
| 4967 | { | { |
| 4968 | stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1; | stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1; |
| 4969 | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (FALLBACK_AS(bracket_fallback)->u.framesize + stacksize) * sizeof(sljit_w)); | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize) * sizeof(sljit_w)); |
| 4970 | if (ket == OP_KETRMAX) | if (ket == OP_KETRMAX) |
| 4971 | { | { |
| 4972 | /* TMP2 which is set here used by OP_KETRMAX below. */ | /* TMP2 which is set here used by OP_KETRMAX below. */ |
| # | Line 4605 if (has_alternatives) | Line 5001 if (has_alternatives) |
| 5001 | if (opcode != OP_ONCE) | if (opcode != OP_ONCE) |
| 5002 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); |
| 5003 | if (ket != OP_KETRMAX) | if (ket != OP_KETRMAX) |
| 5004 | FALLBACK_AS(bracket_fallback)->althotpath = LABEL(); | BACKTRACK_AS(bracket_backtrack)->alttrypath = LABEL(); |
| 5005 | } | } |
| 5006 | ||
| 5007 | /* Must be after the hotpath label. */ | /* Must be after the trypath label. */ |
| 5008 | if (offset != 0) | if (offset != 0) |
| 5009 | { | { |
| 5010 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| # | Line 4621 if (ket == OP_KETRMAX) | Line 5017 if (ket == OP_KETRMAX) |
| 5017 | if (opcode == OP_ONCE || opcode >= OP_SBRA) | if (opcode == OP_ONCE || opcode >= OP_SBRA) |
| 5018 | { | { |
| 5019 | if (has_alternatives) | if (has_alternatives) |
| 5020 | FALLBACK_AS(bracket_fallback)->althotpath = LABEL(); | BACKTRACK_AS(bracket_backtrack)->alttrypath = LABEL(); |
| 5021 | /* Checking zero-length iteration. */ | /* Checking zero-length iteration. */ |
| 5022 | if (opcode != OP_ONCE) | if (opcode != OP_ONCE) |
| 5023 | CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel); | CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel); |
| # | Line 4631 if (ket == OP_KETRMAX) | Line 5027 if (ket == OP_KETRMAX) |
| 5027 | } | } |
| 5028 | else | else |
| 5029 | JUMPTO(SLJIT_JUMP, rmaxlabel); | JUMPTO(SLJIT_JUMP, rmaxlabel); |
| 5030 | FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL(); | BACKTRACK_AS(bracket_backtrack)->recursivetrypath = LABEL(); |
| 5031 | } | } |
| 5032 | ||
| 5033 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
| 5034 | FALLBACK_AS(bracket_fallback)->zerohotpath = LABEL(); | BACKTRACK_AS(bracket_backtrack)->zerotrypath = LABEL(); |
| 5035 | ||
| 5036 | if (bra == OP_BRAMINZERO) | if (bra == OP_BRAMINZERO) |
| 5037 | { | { |
| 5038 | /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */ | /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */ |
| 5039 | JUMPTO(SLJIT_JUMP, ((braminzero_fallback*)parent)->hotpath); | JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->trypath); |
| 5040 | if (braminzerojump != NULL) | if (braminzerojump != NULL) |
| 5041 | { | { |
| 5042 | JUMPHERE(braminzerojump); | JUMPHERE(braminzerojump); |
| 5043 | /* We need to release the end pointer to perform the | /* We need to release the end pointer to perform the |
| 5044 | fallback for the zero-length iteration. When | backtrack for the zero-length iteration. When |
| 5045 | framesize is < 0, OP_ONCE will do the release itself. */ | framesize is < 0, OP_ONCE will do the release itself. */ |
| 5046 | if (opcode == OP_ONCE && FALLBACK_AS(bracket_fallback)->u.framesize >= 0) | if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0) |
| 5047 | { | { |
| 5048 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| 5049 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
| # | Line 4655 if (bra == OP_BRAMINZERO) | Line 5051 if (bra == OP_BRAMINZERO) |
| 5051 | else if (ket == OP_KETRMIN && opcode != OP_ONCE) | else if (ket == OP_KETRMIN && opcode != OP_ONCE) |
| 5052 | free_stack(common, 1); | free_stack(common, 1); |
| 5053 | } | } |
| 5054 | /* Continue to the normal fallback. */ | /* Continue to the normal backtrack. */ |
| 5055 | } | } |
| 5056 | ||
| 5057 | if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO) | if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO) |
| # | Line 4668 cc += 1 + LINK_SIZE; | Line 5064 cc += 1 + LINK_SIZE; |
| 5064 | return cc; | return cc; |
| 5065 | } | } |
| 5066 | ||
| 5067 | static pcre_uchar *compile_bracketpos_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) | static pcre_uchar *compile_bracketpos_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
| 5068 | { | { |
| 5069 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 5070 | fallback_common *fallback; | backtrack_common *backtrack; |
| 5071 | pcre_uchar opcode; | pcre_uchar opcode; |
| 5072 | int localptr; | int localptr; |
| 5073 | int cbraprivptr = 0; | int cbraprivptr = 0; |
| # | Line 4684 int stack; | Line 5080 int stack; |
| 5080 | struct sljit_label *loop = NULL; | struct sljit_label *loop = NULL; |
| 5081 | struct jump_list *emptymatch = NULL; | struct jump_list *emptymatch = NULL; |
| 5082 | ||
| 5083 | PUSH_FALLBACK(sizeof(bracketpos_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL); |
| 5084 | if (*cc == OP_BRAPOSZERO) | if (*cc == OP_BRAPOSZERO) |
| 5085 | { | { |
| 5086 | zero = TRUE; | zero = TRUE; |
| # | Line 4694 if (*cc == OP_BRAPOSZERO) | Line 5090 if (*cc == OP_BRAPOSZERO) |
| 5090 | opcode = *cc; | opcode = *cc; |
| 5091 | localptr = PRIV_DATA(cc); | localptr = PRIV_DATA(cc); |
| 5092 | SLJIT_ASSERT(localptr != 0); | SLJIT_ASSERT(localptr != 0); |
| 5093 | FALLBACK_AS(bracketpos_fallback)->localptr = localptr; | BACKTRACK_AS(bracketpos_backtrack)->localptr = localptr; |
| 5094 | switch(opcode) | switch(opcode) |
| 5095 | { | { |
| 5096 | case OP_BRAPOS: | case OP_BRAPOS: |
| # | Line 4716 switch(opcode) | Line 5112 switch(opcode) |
| 5112 | } | } |
| 5113 | ||
| 5114 | framesize = get_framesize(common, cc, FALSE); | framesize = get_framesize(common, cc, FALSE); |
| 5115 | FALLBACK_AS(bracketpos_fallback)->framesize = framesize; | BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize; |
| 5116 | if (framesize < 0) | if (framesize < 0) |
| 5117 | { | { |
| 5118 | stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1; | stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1; |
| 5119 | if (!zero) | if (!zero) |
| 5120 | stacksize++; | stacksize++; |
| 5121 | FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize; | BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; |
| 5122 | allocate_stack(common, stacksize); | allocate_stack(common, stacksize); |
| 5123 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); |
| 5124 | ||
| # | Line 4746 else | Line 5142 else |
| 5142 | stacksize++; | stacksize++; |
| 5143 | if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) | if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) |
| 5144 | stacksize++; | stacksize++; |
| 5145 | FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize; | BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; |
| 5146 | allocate_stack(common, stacksize); | allocate_stack(common, stacksize); |
| 5147 | ||
| 5148 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| # | Line 4773 if (opcode == OP_CBRAPOS || opcode == OP | Line 5169 if (opcode == OP_CBRAPOS || opcode == OP |
| 5169 | loop = LABEL(); | loop = LABEL(); |
| 5170 | while (*cc != OP_KETRPOS) | while (*cc != OP_KETRPOS) |
| 5171 | { | { |
| 5172 | fallback->top = NULL; | backtrack->top = NULL; |
| 5173 | fallback->topfallbacks = NULL; | backtrack->topbacktracks = NULL; |
| 5174 | cc += GET(cc, 1); | cc += GET(cc, 1); |
| 5175 | ||
| 5176 | compile_hotpath(common, ccbegin, cc, fallback); | compile_trypath(common, ccbegin, cc, backtrack); |
| 5177 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
| 5178 | return NULL; | return NULL; |
| 5179 | ||
| # | Line 4838 while (*cc != OP_KETRPOS) | Line 5234 while (*cc != OP_KETRPOS) |
| 5234 | JUMPTO(SLJIT_JUMP, loop); | JUMPTO(SLJIT_JUMP, loop); |
| 5235 | flush_stubs(common); | flush_stubs(common); |
| 5236 | ||
| 5237 | compile_fallbackpath(common, fallback->top); | compile_backtrackpath(common, backtrack->top); |
| 5238 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
| 5239 | return NULL; | return NULL; |
| 5240 | set_jumps(fallback->topfallbacks, LABEL()); | set_jumps(backtrack->topbacktracks, LABEL()); |
| 5241 | ||
| 5242 | if (framesize < 0) | if (framesize < 0) |
| 5243 | { | { |
| # | Line 4871 while (*cc != OP_KETRPOS) | Line 5267 while (*cc != OP_KETRPOS) |
| 5267 | ccbegin = cc + 1 + LINK_SIZE; | ccbegin = cc + 1 + LINK_SIZE; |
| 5268 | } | } |
| 5269 | ||
| 5270 | fallback->topfallbacks = NULL; | backtrack->topbacktracks = NULL; |
| 5271 | if (!zero) | if (!zero) |
| 5272 | { | { |
| 5273 | if (framesize < 0) | if (framesize < 0) |
| 5274 | add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0)); | add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0)); |
| 5275 | else /* TMP2 is set to [localptr] above. */ | else /* TMP2 is set to [localptr] above. */ |
| 5276 | add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0)); | add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0)); |
| 5277 | } | } |
| 5278 | ||
| 5279 | /* None of them matched. */ | /* None of them matched. */ |
| # | Line 4925 else | Line 5321 else |
| 5321 | SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS); | SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS); |
| 5322 | *type = *opcode; | *type = *opcode; |
| 5323 | cc++; | cc++; |
| 5324 | class_len = (*type < OP_XCLASS) ? (1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0); | class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0); |
| 5325 | *opcode = cc[class_len - 1]; | *opcode = cc[class_len - 1]; |
| 5326 | if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) | if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) |
| 5327 | { | { |
| # | Line 4978 if (end != NULL) | Line 5374 if (end != NULL) |
| 5374 | return cc; | return cc; |
| 5375 | } | } |
| 5376 | ||
| 5377 | static pcre_uchar *compile_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) | static pcre_uchar *compile_iterator_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
| 5378 | { | { |
| 5379 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 5380 | fallback_common *fallback; | backtrack_common *backtrack; |
| 5381 | pcre_uchar opcode; | pcre_uchar opcode; |
| 5382 | pcre_uchar type; | pcre_uchar type; |
| 5383 | int arg1 = -1, arg2 = -1; | int arg1 = -1, arg2 = -1; |
| # | Line 4990 jump_list *nomatch = NULL; | Line 5386 jump_list *nomatch = NULL; |
| 5386 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
| 5387 | struct sljit_label *label; | struct sljit_label *label; |
| 5388 | ||
| 5389 | PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL); |
| 5390 | ||
| 5391 | cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end); | cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end); |
| 5392 | ||
| # | Line 5017 switch(opcode) | Line 5413 switch(opcode) |
| 5413 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); |
| 5414 | ||
| 5415 | label = LABEL(); | label = LABEL(); |
| 5416 | compile_char1_hotpath(common, type, cc, &fallback->topfallbacks); | compile_char1_trypath(common, type, cc, &backtrack->topbacktracks); |
| 5417 | if (opcode == OP_UPTO || opcode == OP_CRRANGE) | if (opcode == OP_UPTO || opcode == OP_CRRANGE) |
| 5418 | { | { |
| 5419 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); |
| # | Line 5041 switch(opcode) | Line 5437 switch(opcode) |
| 5437 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
| 5438 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); |
| 5439 | label = LABEL(); | label = LABEL(); |
| 5440 | compile_char1_hotpath(common, type, cc, &nomatch); | compile_char1_trypath(common, type, cc, &nomatch); |
| 5441 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
| 5442 | if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0)) | if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0)) |
| 5443 | { | { |
| # | Line 5057 switch(opcode) | Line 5453 switch(opcode) |
| 5453 | } | } |
| 5454 | set_jumps(nomatch, LABEL()); | set_jumps(nomatch, LABEL()); |
| 5455 | if (opcode == OP_PLUS || opcode == OP_CRRANGE) | if (opcode == OP_PLUS || opcode == OP_CRRANGE) |
| 5456 | add_jump(compiler, &fallback->topfallbacks, | add_jump(compiler, &backtrack->topbacktracks, |
| 5457 | CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, opcode == OP_PLUS ? 2 : arg2 + 1)); | CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, opcode == OP_PLUS ? 2 : arg2 + 1)); |
| 5458 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 5459 | } | } |
| 5460 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); |
| 5461 | break; | break; |
| 5462 | ||
| 5463 | case OP_MINSTAR: | case OP_MINSTAR: |
| # | Line 5069 switch(opcode) | Line 5465 switch(opcode) |
| 5465 | allocate_stack(common, 1); | allocate_stack(common, 1); |
| 5466 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
| 5467 | if (opcode == OP_MINPLUS) | if (opcode == OP_MINPLUS) |
| 5468 | add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); |
| 5469 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); |
| 5470 | break; | break; |
| 5471 | ||
| 5472 | case OP_MINUPTO: | case OP_MINUPTO: |
| # | Line 5079 switch(opcode) | Line 5475 switch(opcode) |
| 5475 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
| 5476 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); |
| 5477 | if (opcode == OP_CRMINRANGE) | if (opcode == OP_CRMINRANGE) |
| 5478 | add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); |
| 5479 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); |
| 5480 | break; | break; |
| 5481 | ||
| 5482 | case OP_QUERY: | case OP_QUERY: |
| # | Line 5088 switch(opcode) | Line 5484 switch(opcode) |
| 5484 | allocate_stack(common, 1); | allocate_stack(common, 1); |
| 5485 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
| 5486 | if (opcode == OP_QUERY) | if (opcode == OP_QUERY) |
| 5487 | compile_char1_hotpath(common, type, cc, &fallback->topfallbacks); | compile_char1_trypath(common, type, cc, &backtrack->topbacktracks); |
| 5488 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); |
| 5489 | break; | break; |
| 5490 | ||
| 5491 | case OP_EXACT: | case OP_EXACT: |
| 5492 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1); |
| 5493 | label = LABEL(); | label = LABEL(); |
| 5494 | compile_char1_hotpath(common, type, cc, &fallback->topfallbacks); | compile_char1_trypath(common, type, cc, &backtrack->topbacktracks); |
| 5495 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); |
| 5496 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
| 5497 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); |
| # | Line 5109 switch(opcode) | Line 5505 switch(opcode) |
| 5505 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1); |
| 5506 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); |
| 5507 | label = LABEL(); | label = LABEL(); |
| 5508 | compile_char1_hotpath(common, type, cc, &nomatch); | compile_char1_trypath(common, type, cc, &nomatch); |
| 5509 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); |
| 5510 | if (opcode != OP_POSUPTO) | if (opcode != OP_POSUPTO) |
| 5511 | { | { |
| # | Line 5126 switch(opcode) | Line 5522 switch(opcode) |
| 5522 | } | } |
| 5523 | set_jumps(nomatch, LABEL()); | set_jumps(nomatch, LABEL()); |
| 5524 | if (opcode == OP_POSPLUS) | if (opcode == OP_POSPLUS) |
| 5525 | add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2)); | add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2)); |
| 5526 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); |
| 5527 | break; | break; |
| 5528 | ||
| 5529 | case OP_POSQUERY: | case OP_POSQUERY: |
| 5530 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); |
| 5531 | compile_char1_hotpath(common, type, cc, &nomatch); | compile_char1_trypath(common, type, cc, &nomatch); |
| 5532 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); |
| 5533 | set_jumps(nomatch, LABEL()); | set_jumps(nomatch, LABEL()); |
| 5534 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); |
| # | Line 5147 decrease_call_count(common); | Line 5543 decrease_call_count(common); |
| 5543 | return end; | return end; |
| 5544 | } | } |
| 5545 | ||
| 5546 | static SLJIT_INLINE pcre_uchar *compile_fail_accept_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) | static SLJIT_INLINE pcre_uchar *compile_fail_accept_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
| 5547 | { | { |
| 5548 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 5549 | fallback_common *fallback; | backtrack_common *backtrack; |
| 5550 | ||
| 5551 | PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL); |
| 5552 | ||
| 5553 | if (*cc == OP_FAIL) | if (*cc == OP_FAIL) |
| 5554 | { | { |
| 5555 | add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); |
| 5556 | return cc + 1; | return cc + 1; |
| 5557 | } | } |
| 5558 | ||
| # | Line 5176 else | Line 5572 else |
| 5572 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel); |
| 5573 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
| 5574 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); |
| 5575 | add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
| 5576 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); |
| 5577 | if (common->acceptlabel == NULL) | if (common->acceptlabel == NULL) |
| 5578 | add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
| # | Line 5187 if (common->acceptlabel == NULL) | Line 5583 if (common->acceptlabel == NULL) |
| 5583 | add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0)); | add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0)); |
| 5584 | else | else |
| 5585 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel); | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel); |
| 5586 | add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); |
| 5587 | return cc + 1; | return cc + 1; |
| 5588 | } | } |
| 5589 | ||
| 5590 | static SLJIT_INLINE pcre_uchar *compile_close_hotpath(compiler_common *common, pcre_uchar *cc) | static SLJIT_INLINE pcre_uchar *compile_close_trypath(compiler_common *common, pcre_uchar *cc) |
| 5591 | { | { |
| 5592 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 5593 | int offset = GET2(cc, 1); | int offset = GET2(cc, 1); |
| # | Line 5207 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_R | Line 5603 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_R |
| 5603 | return cc + 1 + IMM2_SIZE; | return cc + 1 + IMM2_SIZE; |
| 5604 | } | } |
| 5605 | ||
| 5606 | static void compile_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, fallback_common *parent) | static void compile_trypath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) |
| 5607 | { | { |
| 5608 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 5609 | fallback_common *fallback; | backtrack_common *backtrack; |
| 5610 | ||
| 5611 | while (cc < ccend) | while (cc < ccend) |
| 5612 | { | { |
| # | Line 5246 while (cc < ccend) | Line 5642 while (cc < ccend) |
| 5642 | case OP_NOT: | case OP_NOT: |
| 5643 | case OP_NOTI: | case OP_NOTI: |
| 5644 | case OP_REVERSE: | case OP_REVERSE: |
| 5645 | cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); |
| 5646 | break; | break; |
| 5647 | ||
| 5648 | case OP_SET_SOM: | case OP_SET_SOM: |
| 5649 | PUSH_FALLBACK_NOVALUE(sizeof(fallback_common), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); |
| 5650 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | |
| 5651 | allocate_stack(common, 1); | allocate_stack(common, 1); |
| OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | ||
| 5652 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); |
| 5653 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); |
| 5654 | cc++; | cc++; |
| 5655 | break; | break; |
| 5656 | ||
| 5657 | case OP_CHAR: | case OP_CHAR: |
| 5658 | case OP_CHARI: | case OP_CHARI: |
| 5659 | cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | if (common->mode == JIT_COMPILE) |
| 5660 | cc = compile_charn_trypath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); | |
| 5661 | else | |
| 5662 | cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); | |
| 5663 | break; | break; |
| 5664 | ||
| 5665 | case OP_STAR: | case OP_STAR: |
| # | Line 5328 while (cc < ccend) | Line 5727 while (cc < ccend) |
| 5727 | case OP_TYPEPOSPLUS: | case OP_TYPEPOSPLUS: |
| 5728 | case OP_TYPEPOSQUERY: | case OP_TYPEPOSQUERY: |
| 5729 | case OP_TYPEPOSUPTO: | case OP_TYPEPOSUPTO: |
| 5730 | cc = compile_iterator_hotpath(common, cc, parent); | cc = compile_iterator_trypath(common, cc, parent); |
| 5731 | break; | break; |
| 5732 | ||
| 5733 | case OP_CLASS: | case OP_CLASS: |
| 5734 | case OP_NCLASS: | case OP_NCLASS: |
| 5735 | if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRMINRANGE) | if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRMINRANGE) |
| 5736 | cc = compile_iterator_hotpath(common, cc, parent); | cc = compile_iterator_trypath(common, cc, parent); |
| 5737 | else | else |
| 5738 | cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); |
| 5739 | break; | break; |
| 5740 | ||
| 5741 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 |
| 5742 | case OP_XCLASS: | case OP_XCLASS: |
| 5743 | if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE) | if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE) |
| 5744 | cc = compile_iterator_hotpath(common, cc, parent); | cc = compile_iterator_trypath(common, cc, parent); |
| 5745 | else | else |
| 5746 | cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); |
| 5747 | break; | break; |
| 5748 | #endif | #endif |
| 5749 | ||
| 5750 | case OP_REF: | case OP_REF: |
| 5751 | case OP_REFI: | case OP_REFI: |
| 5752 | if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE) | if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE) |
| 5753 | cc = compile_ref_iterator_hotpath(common, cc, parent); | cc = compile_ref_iterator_trypath(common, cc, parent); |
| 5754 | else | else |
| 5755 | cc = compile_ref_hotpath(common, cc, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks, TRUE, FALSE); | cc = compile_ref_trypath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE); |
| 5756 | break; | break; |
| 5757 | ||
| 5758 | case OP_RECURSE: | case OP_RECURSE: |
| 5759 | cc = compile_recurse_hotpath(common, cc, parent); | cc = compile_recurse_trypath(common, cc, parent); |
| 5760 | break; | break; |
| 5761 | ||
| 5762 | case OP_ASSERT: | case OP_ASSERT: |
| 5763 | case OP_ASSERT_NOT: | case OP_ASSERT_NOT: |
| 5764 | case OP_ASSERTBACK: | case OP_ASSERTBACK: |
| 5765 | case OP_ASSERTBACK_NOT: | case OP_ASSERTBACK_NOT: |
| 5766 | PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc); |
| 5767 | cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE); | cc = compile_assert_trypath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE); |
| 5768 | break; | break; |
| 5769 | ||
| 5770 | case OP_BRAMINZERO: | case OP_BRAMINZERO: |
| 5771 | PUSH_FALLBACK_NOVALUE(sizeof(braminzero_fallback), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc); |
| 5772 | cc = bracketend(cc + 1); | cc = bracketend(cc + 1); |
| 5773 | if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN) | if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN) |
| 5774 | { | { |
| # | Line 5382 while (cc < ccend) | Line 5781 while (cc < ccend) |
| 5781 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
| 5782 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0); |
| 5783 | } | } |
| 5784 | FALLBACK_AS(braminzero_fallback)->hotpath = LABEL(); | BACKTRACK_AS(braminzero_backtrack)->trypath = LABEL(); |
| 5785 | if (cc[1] > OP_ASSERTBACK_NOT) | if (cc[1] > OP_ASSERTBACK_NOT) |
| 5786 | decrease_call_count(common); | decrease_call_count(common); |
| 5787 | break; | break; |
| # | Line 5395 while (cc < ccend) | Line 5794 while (cc < ccend) |
| 5794 | case OP_SBRA: | case OP_SBRA: |
| 5795 | case OP_SCBRA: | case OP_SCBRA: |
| 5796 | case OP_SCOND: | case OP_SCOND: |
| 5797 | cc = compile_bracket_hotpath(common, cc, parent); | cc = compile_bracket_trypath(common, cc, parent); |
| 5798 | break; | break; |
| 5799 | ||
| 5800 | case OP_BRAZERO: | case OP_BRAZERO: |
| 5801 | if (cc[1] > OP_ASSERTBACK_NOT) | if (cc[1] > OP_ASSERTBACK_NOT) |
| 5802 | cc = compile_bracket_hotpath(common, cc, parent); | cc = compile_bracket_trypath(common, cc, parent); |
| 5803 | else | else |
| 5804 | { | { |
| 5805 | PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc); |
| 5806 | cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE); | cc = compile_assert_trypath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE); |
| 5807 | } | } |
| 5808 | break; | break; |
| 5809 | ||
| # | Line 5413 while (cc < ccend) | Line 5812 while (cc < ccend) |
| 5812 | case OP_SBRAPOS: | case OP_SBRAPOS: |
| 5813 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
| 5814 | case OP_BRAPOSZERO: | case OP_BRAPOSZERO: |
| 5815 | cc = compile_bracketpos_hotpath(common, cc, parent); | cc = compile_bracketpos_trypath(common, cc, parent); |
| 5816 | break; | |
| 5817 | ||
| 5818 | case OP_MARK: | |
| 5819 | PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); | |
| 5820 | SLJIT_ASSERT(common->mark_ptr != 0); | |
| 5821 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | |
| 5822 | allocate_stack(common, 1); | |
| 5823 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | |
| 5824 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); | |
| 5825 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)(cc + 2)); | |
| 5826 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); | |
| 5827 | OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); | |
| 5828 | cc += 1 + 2 + cc[1]; | |
| 5829 | break; | |
| 5830 | ||
| 5831 | case OP_COMMIT: | |
| 5832 | PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); | |
| 5833 | cc += 1; | |
| 5834 | break; | break; |
| 5835 | ||
| 5836 | case OP_FAIL: | case OP_FAIL: |
| 5837 | case OP_ACCEPT: | case OP_ACCEPT: |
| 5838 | case OP_ASSERT_ACCEPT: | case OP_ASSERT_ACCEPT: |
| 5839 | cc = compile_fail_accept_hotpath(common, cc, parent); | cc = compile_fail_accept_trypath(common, cc, parent); |
| 5840 | break; | break; |
| 5841 | ||
| 5842 | case OP_CLOSE: | case OP_CLOSE: |
| 5843 | cc = compile_close_hotpath(common, cc); | cc = compile_close_trypath(common, cc); |
| 5844 | break; | break; |
| 5845 | ||
| 5846 | case OP_SKIPZERO: | case OP_SKIPZERO: |
| # | Line 5440 while (cc < ccend) | Line 5857 while (cc < ccend) |
| 5857 | SLJIT_ASSERT(cc == ccend); | SLJIT_ASSERT(cc == ccend); |
| 5858 | } | } |
| 5859 | ||
| 5860 | #undef PUSH_FALLBACK | #undef PUSH_BACKTRACK |
| 5861 | #undef PUSH_FALLBACK_NOVALUE | #undef PUSH_BACKTRACK_NOVALUE |
| 5862 | #undef FALLBACK_AS | #undef BACKTRACK_AS |
| 5863 | ||
| 5864 | #define COMPILE_FALLBACKPATH(current) \ | #define COMPILE_BACKTRACKPATH(current) \ |
| 5865 | do \ | do \ |
| 5866 | { \ | { \ |
| 5867 | compile_fallbackpath(common, (current)); \ | compile_backtrackpath(common, (current)); \ |
| 5868 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ |
| 5869 | return; \ | return; \ |
| 5870 | } \ | } \ |
| 5871 | while (0) | while (0) |
| 5872 | ||
| 5873 | #define CURRENT_AS(type) ((type*)current) | #define CURRENT_AS(type) ((type *)current) |
| 5874 | ||
| 5875 | static void compile_iterator_fallbackpath(compiler_common *common, struct fallback_common *current) | static void compile_iterator_backtrackpath(compiler_common *common, struct backtrack_common *current) |
| 5876 | { | { |
| 5877 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 5878 | pcre_uchar *cc = current->cc; | pcre_uchar *cc = current->cc; |
| # | Line 5475 switch(opcode) | Line 5892 switch(opcode) |
| 5892 | case OP_CRRANGE: | case OP_CRRANGE: |
| 5893 | if (type == OP_ANYNL || type == OP_EXTUNI) | if (type == OP_ANYNL || type == OP_EXTUNI) |
| 5894 | { | { |
| 5895 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 5896 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 5897 | free_stack(common, 1); | free_stack(common, 1); |
| 5898 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath); |
| 5899 | } | } |
| 5900 | else | else |
| 5901 | { | { |
| # | Line 5491 switch(opcode) | Line 5908 switch(opcode) |
| 5908 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 5909 | skip_char_back(common); | skip_char_back(common); |
| 5910 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
| 5911 | JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath); |
| 5912 | if (opcode == OP_PLUS || opcode == OP_CRRANGE) | if (opcode == OP_PLUS || opcode == OP_CRRANGE) |
| 5913 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 5914 | JUMPHERE(jump); | JUMPHERE(jump); |
| 5915 | free_stack(common, 2); | free_stack(common, 2); |
| 5916 | } | } |
| # | Line 5504 switch(opcode) | Line 5921 switch(opcode) |
| 5921 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 5922 | if (opcode == OP_MINPLUS) | if (opcode == OP_MINPLUS) |
| 5923 | { | { |
| 5924 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 5925 | current->topfallbacks = NULL; | current->topbacktracks = NULL; |
| 5926 | } | } |
| 5927 | compile_char1_hotpath(common, type, cc, ¤t->topfallbacks); | compile_char1_trypath(common, type, cc, ¤t->topbacktracks); |
| 5928 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
| 5929 | JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath); |
| 5930 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 5931 | free_stack(common, 1); | free_stack(common, 1); |
| 5932 | break; | break; |
| 5933 | ||
| # | Line 5518 switch(opcode) | Line 5935 switch(opcode) |
| 5935 | case OP_CRMINRANGE: | case OP_CRMINRANGE: |
| 5936 | if (opcode == OP_CRMINRANGE) | if (opcode == OP_CRMINRANGE) |
| 5937 | { | { |
| 5938 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 5939 | current->topfallbacks = NULL; | current->topbacktracks = NULL; |
| 5940 | label = LABEL(); | label = LABEL(); |
| 5941 | } | } |
| 5942 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 5943 | compile_char1_hotpath(common, type, cc, ¤t->topfallbacks); | compile_char1_trypath(common, type, cc, ¤t->topbacktracks); |
| 5944 | ||
| 5945 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
| 5946 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
| # | Line 5534 switch(opcode) | Line 5951 switch(opcode) |
| 5951 | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label); | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label); |
| 5952 | ||
| 5953 | if (opcode == OP_CRMINRANGE && arg1 == 0) | if (opcode == OP_CRMINRANGE && arg1 == 0) |
| 5954 | JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath); |
| 5955 | else | else |
| 5956 | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_fallback)->hotpath); | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_backtrack)->trypath); |
| 5957 | ||
| 5958 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 5959 | free_stack(common, 2); | free_stack(common, 2); |
| 5960 | break; | break; |
| 5961 | ||
| 5962 | case OP_QUERY: | case OP_QUERY: |
| 5963 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 5964 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
| 5965 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath); |
| 5966 | jump = JUMP(SLJIT_JUMP); | jump = JUMP(SLJIT_JUMP); |
| 5967 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 5968 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 5969 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
| 5970 | JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath); |
| 5971 | JUMPHERE(jump); | JUMPHERE(jump); |
| 5972 | free_stack(common, 1); | free_stack(common, 1); |
| 5973 | break; | break; |
| # | Line 5559 switch(opcode) | Line 5976 switch(opcode) |
| 5976 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 5977 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
| 5978 | jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); | jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); |
| 5979 | compile_char1_hotpath(common, type, cc, ¤t->topfallbacks); | compile_char1_trypath(common, type, cc, ¤t->topbacktracks); |
| 5980 | JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath); |
| 5981 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 5982 | JUMPHERE(jump); | JUMPHERE(jump); |
| 5983 | free_stack(common, 1); | free_stack(common, 1); |
| 5984 | break; | break; |
| 5985 | ||
| 5986 | case OP_EXACT: | case OP_EXACT: |
| 5987 | case OP_POSPLUS: | case OP_POSPLUS: |
| 5988 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 5989 | break; | break; |
| 5990 | ||
| 5991 | case OP_POSSTAR: | case OP_POSSTAR: |
| # | Line 5582 switch(opcode) | Line 5999 switch(opcode) |
| 5999 | } | } |
| 6000 | } | } |
| 6001 | ||
| 6002 | static void compile_ref_iterator_fallbackpath(compiler_common *common, struct fallback_common *current) | static void compile_ref_iterator_backtrackpath(compiler_common *common, struct backtrack_common *current) |
| 6003 | { | { |
| 6004 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 6005 | pcre_uchar *cc = current->cc; | pcre_uchar *cc = current->cc; |
| # | Line 5591 pcre_uchar type; | Line 6008 pcre_uchar type; |
| 6008 | type = cc[1 + IMM2_SIZE]; | type = cc[1 + IMM2_SIZE]; |
| 6009 | if ((type & 0x1) == 0) | if ((type & 0x1) == 0) |
| 6010 | { | { |
| 6011 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 6012 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 6013 | free_stack(common, 1); | free_stack(common, 1); |
| 6014 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath); |
| 6015 | return; | return; |
| 6016 | } | } |
| 6017 | ||
| 6018 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 6019 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath); |
| 6020 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 6021 | free_stack(common, 2); | free_stack(common, 2); |
| 6022 | } | } |
| 6023 | ||
| 6024 | static void compile_recurse_fallbackpath(compiler_common *common, struct fallback_common *current) | static void compile_recurse_backtrackpath(compiler_common *common, struct backtrack_common *current) |
| 6025 | { | { |
| 6026 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 6027 | ||
| 6028 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 6029 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | |
| 6030 | free_stack(common, 1); | if (common->has_set_som && common->mark_ptr != 0) |
| 6031 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0); | { |
| 6032 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | |
| 6033 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | |
| 6034 | free_stack(common, 2); | |
| 6035 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0); | |
| 6036 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0); | |
| 6037 | } | |
| 6038 | else if (common->has_set_som || common->mark_ptr != 0) | |
| 6039 | { | |
| 6040 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | |
| 6041 | free_stack(common, 1); | |
| 6042 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0); | |
| 6043 | } | |
| 6044 | } | } |
| 6045 | ||
| 6046 | static void compile_assert_fallbackpath(compiler_common *common, struct fallback_common *current) | static void compile_assert_backtrackpath(compiler_common *common, struct backtrack_common *current) |
| 6047 | { | { |
| 6048 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 6049 | pcre_uchar *cc = current->cc; | pcre_uchar *cc = current->cc; |
| # | Line 5630 if (*cc == OP_BRAZERO) | Line 6059 if (*cc == OP_BRAZERO) |
| 6059 | ||
| 6060 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
| 6061 | { | { |
| 6062 | SLJIT_ASSERT(current->topfallbacks == NULL); | SLJIT_ASSERT(current->topbacktracks == NULL); |
| 6063 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 6064 | } | } |
| 6065 | ||
| 6066 | if (CURRENT_AS(assert_fallback)->framesize < 0) | if (CURRENT_AS(assert_backtrack)->framesize < 0) |
| 6067 | { | { |
| 6068 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 6069 | ||
| 6070 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
| 6071 | { | { |
| 6072 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
| 6073 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_fallback)->hotpath); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->trypath); |
| 6074 | free_stack(common, 1); | free_stack(common, 1); |
| 6075 | } | } |
| 6076 | return; | return; |
| # | Line 5652 if (bra == OP_BRAZERO) | Line 6081 if (bra == OP_BRAZERO) |
| 6081 | if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT) | if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT) |
| 6082 | { | { |
| 6083 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
| 6084 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_fallback)->hotpath); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->trypath); |
| 6085 | free_stack(common, 1); | free_stack(common, 1); |
| 6086 | return; | return; |
| 6087 | } | } |
| # | Line 5662 if (bra == OP_BRAZERO) | Line 6091 if (bra == OP_BRAZERO) |
| 6091 | ||
| 6092 | if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK) | if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK) |
| 6093 | { | { |
| 6094 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->localptr); |
| 6095 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
| 6096 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_fallback)->framesize * sizeof(sljit_w)); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_w)); |
| 6097 | ||
| 6098 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 6099 | } | } |
| 6100 | else | else |
| 6101 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 6102 | ||
| 6103 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
| 6104 | { | { |
| 6105 | /* We know there is enough place on the stack. */ | /* We know there is enough place on the stack. */ |
| 6106 | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); |
| 6107 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
| 6108 | JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_fallback)->hotpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->trypath); |
| 6109 | JUMPHERE(brajump); | JUMPHERE(brajump); |
| 6110 | } | } |
| 6111 | } | } |
| 6112 | ||
| 6113 | static void compile_bracket_fallbackpath(compiler_common *common, struct fallback_common *current) | static void compile_bracket_backtrackpath(compiler_common *common, struct backtrack_common *current) |
| 6114 | { | { |
| 6115 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 6116 | int opcode; | int opcode; |
| 6117 | int offset = 0; | int offset = 0; |
| 6118 | int localptr = CURRENT_AS(bracket_fallback)->localptr; | int localptr = CURRENT_AS(bracket_backtrack)->localptr; |
| 6119 | int stacksize; | int stacksize; |
| 6120 | int count; | int count; |
| 6121 | pcre_uchar *cc = current->cc; | pcre_uchar *cc = current->cc; |
| # | Line 5696 jump_list *jumplist = NULL; | Line 6125 jump_list *jumplist = NULL; |
| 6125 | jump_list *jumplistitem = NULL; | jump_list *jumplistitem = NULL; |
| 6126 | pcre_uchar bra = OP_BRA; | pcre_uchar bra = OP_BRA; |
| 6127 | pcre_uchar ket; | pcre_uchar ket; |
| 6128 | assert_fallback *assert; | assert_backtrack *assert; |
| 6129 | BOOL has_alternatives; | BOOL has_alternatives; |
| 6130 | struct sljit_jump *brazero = NULL; | struct sljit_jump *brazero = NULL; |
| 6131 | struct sljit_jump *once = NULL; | struct sljit_jump *once = NULL; |
| # | Line 5715 ket = *(bracketend(ccbegin) - 1 - LINK_S | Line 6144 ket = *(bracketend(ccbegin) - 1 - LINK_S |
| 6144 | cc += GET(cc, 1); | cc += GET(cc, 1); |
| 6145 | has_alternatives = *cc == OP_ALT; | has_alternatives = *cc == OP_ALT; |
| 6146 | if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) | if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) |
| 6147 | has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_fallback)->u.condfailed != NULL; | has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL; |
| 6148 | if (opcode == OP_CBRA || opcode == OP_SCBRA) | if (opcode == OP_CBRA || opcode == OP_SCBRA) |
| 6149 | offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1; | offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1; |
| 6150 | if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) | if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) |
| # | Line 5742 else if (ket == OP_KETRMIN) | Line 6171 else if (ket == OP_KETRMIN) |
| 6171 | if (opcode >= OP_SBRA || opcode == OP_ONCE) | if (opcode >= OP_SBRA || opcode == OP_ONCE) |
| 6172 | { | { |
| 6173 | /* Checking zero-length iteration. */ | /* Checking zero-length iteration. */ |
| 6174 | if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize < 0) | if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0) |
| 6175 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_fallback)->recursivehotpath); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_backtrack)->recursivetrypath); |
| 6176 | else | else |
| 6177 | { | { |
| 6178 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| 6179 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_fallback)->recursivehotpath); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_backtrack)->recursivetrypath); |
| 6180 | } | } |
| 6181 | if (opcode != OP_ONCE) | if (opcode != OP_ONCE) |
| 6182 | free_stack(common, 1); | free_stack(common, 1); |
| 6183 | } | } |
| 6184 | else | else |
| 6185 | JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->recursivehotpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursivetrypath); |
| 6186 | } | } |
| 6187 | rminlabel = LABEL(); | rminlabel = LABEL(); |
| 6188 | } | } |
| # | Line 5766 else if (bra == OP_BRAZERO) | Line 6195 else if (bra == OP_BRAZERO) |
| 6195 | ||
| 6196 | if (SLJIT_UNLIKELY(opcode == OP_ONCE)) | if (SLJIT_UNLIKELY(opcode == OP_ONCE)) |
| 6197 | { | { |
| 6198 | if (CURRENT_AS(bracket_fallback)->u.framesize >= 0) | if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
| 6199 | { | { |
| 6200 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| 6201 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
| # | Line 5821 else if (*cc == OP_ALT) | Line 6250 else if (*cc == OP_ALT) |
| 6250 | cc = ccbegin + GET(ccbegin, 1); | cc = ccbegin + GET(ccbegin, 1); |
| 6251 | } | } |
| 6252 | ||
| 6253 | COMPILE_FALLBACKPATH(current->top); | COMPILE_BACKTRACKPATH(current->top); |
| 6254 | if (current->topfallbacks) | if (current->topbacktracks) |
| 6255 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 6256 | ||
| 6257 | if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) | if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) |
| 6258 | { | { |
| # | Line 5831 if (SLJIT_UNLIKELY(opcode == OP_COND) || | Line 6260 if (SLJIT_UNLIKELY(opcode == OP_COND) || |
| 6260 | if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) | if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) |
| 6261 | { | { |
| 6262 | SLJIT_ASSERT(has_alternatives); | SLJIT_ASSERT(has_alternatives); |
| 6263 | assert = CURRENT_AS(bracket_fallback)->u.assert; | assert = CURRENT_AS(bracket_backtrack)->u.assert; |
| 6264 | if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK)) | if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK)) |
| 6265 | { | { |
| 6266 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr); |
| # | Line 5839 if (SLJIT_UNLIKELY(opcode == OP_COND) || | Line 6268 if (SLJIT_UNLIKELY(opcode == OP_COND) || |
| 6268 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w)); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w)); |
| 6269 | } | } |
| 6270 | cond = JUMP(SLJIT_JUMP); | cond = JUMP(SLJIT_JUMP); |
| 6271 | set_jumps(CURRENT_AS(bracket_fallback)->u.assert->condfailed, LABEL()); | set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL()); |
| 6272 | } | } |
| 6273 | else if (CURRENT_AS(bracket_fallback)->u.condfailed != NULL) | else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL) |
| 6274 | { | { |
| 6275 | SLJIT_ASSERT(has_alternatives); | SLJIT_ASSERT(has_alternatives); |
| 6276 | cond = JUMP(SLJIT_JUMP); | cond = JUMP(SLJIT_JUMP); |
| 6277 | set_jumps(CURRENT_AS(bracket_fallback)->u.condfailed, LABEL()); | set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL()); |
| 6278 | } | } |
| 6279 | else | else |
| 6280 | SLJIT_ASSERT(!has_alternatives); | SLJIT_ASSERT(!has_alternatives); |
| # | Line 5857 if (has_alternatives) | Line 6286 if (has_alternatives) |
| 6286 | do | do |
| 6287 | { | { |
| 6288 | current->top = NULL; | current->top = NULL; |
| 6289 | current->topfallbacks = NULL; | current->topbacktracks = NULL; |
| 6290 | current->nextfallbacks = NULL; | current->nextbacktracks = NULL; |
| 6291 | if (*cc == OP_ALT) | if (*cc == OP_ALT) |
| 6292 | { | { |
| 6293 | ccprev = cc + 1 + LINK_SIZE; | ccprev = cc + 1 + LINK_SIZE; |
| # | Line 5870 if (has_alternatives) | Line 6299 if (has_alternatives) |
| 6299 | else | else |
| 6300 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 6301 | } | } |
| 6302 | compile_hotpath(common, ccprev, cc, current); | compile_trypath(common, ccprev, cc, current); |
| 6303 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
| 6304 | return; | return; |
| 6305 | } | } |
| 6306 | ||
| 6307 | /* Instructions after the current alternative is succesfully matched. */ | /* Instructions after the current alternative is succesfully matched. */ |
| 6308 | /* There is a similar code in compile_bracket_hotpath. */ | /* There is a similar code in compile_bracket_trypath. */ |
| 6309 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
| 6310 | { | { |
| 6311 | if (CURRENT_AS(bracket_fallback)->u.framesize < 0) | if (CURRENT_AS(bracket_backtrack)->u.framesize < 0) |
| 6312 | { | { |
| 6313 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
| 6314 | /* TMP2 which is set here used by OP_KETRMAX below. */ | /* TMP2 which is set here used by OP_KETRMAX below. */ |
| # | Line 5893 if (has_alternatives) | Line 6322 if (has_alternatives) |
| 6322 | } | } |
| 6323 | else | else |
| 6324 | { | { |
| 6325 | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (CURRENT_AS(bracket_fallback)->u.framesize + 2) * sizeof(sljit_w)); | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (CURRENT_AS(bracket_backtrack)->u.framesize + 2) * sizeof(sljit_w)); |
| 6326 | if (ket == OP_KETRMAX) | if (ket == OP_KETRMAX) |
| 6327 | { | { |
| 6328 | /* TMP2 which is set here used by OP_KETRMAX below. */ | /* TMP2 which is set here used by OP_KETRMAX below. */ |
| # | Line 5909 if (has_alternatives) | Line 6338 if (has_alternatives) |
| 6338 | stacksize++; | stacksize++; |
| 6339 | ||
| 6340 | if (stacksize > 0) { | if (stacksize > 0) { |
| 6341 | if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize >= 0) | if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
| 6342 | allocate_stack(common, stacksize); | allocate_stack(common, stacksize); |
| 6343 | else | else |
| 6344 | { | { |
| # | Line 5939 if (has_alternatives) | Line 6368 if (has_alternatives) |
| 6368 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0); |
| 6369 | } | } |
| 6370 | ||
| 6371 | JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->althotpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alttrypath); |
| 6372 | ||
| 6373 | if (opcode != OP_ONCE) | if (opcode != OP_ONCE) |
| 6374 | { | { |
| # | Line 5948 if (has_alternatives) | Line 6377 if (has_alternatives) |
| 6377 | jumplist = jumplist->next; | jumplist = jumplist->next; |
| 6378 | } | } |
| 6379 | ||
| 6380 | COMPILE_FALLBACKPATH(current->top); | COMPILE_BACKTRACKPATH(current->top); |
| 6381 | if (current->topfallbacks) | if (current->topbacktracks) |
| 6382 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 6383 | SLJIT_ASSERT(!current->nextfallbacks); | SLJIT_ASSERT(!current->nextbacktracks); |
| 6384 | } | } |
| 6385 | while (*cc == OP_ALT); | while (*cc == OP_ALT); |
| 6386 | SLJIT_ASSERT(!jumplist); | SLJIT_ASSERT(!jumplist); |
| # | Line 5959 if (has_alternatives) | Line 6388 if (has_alternatives) |
| 6388 | if (cond != NULL) | if (cond != NULL) |
| 6389 | { | { |
| 6390 | SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND); | SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND); |
| 6391 | assert = CURRENT_AS(bracket_fallback)->u.assert; | assert = CURRENT_AS(bracket_backtrack)->u.assert; |
| 6392 | if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) | if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) |
| 6393 | ||
| 6394 | { | { |
| # | Line 5993 else if (opcode == OP_SBRA || opcode == | Line 6422 else if (opcode == OP_SBRA || opcode == |
| 6422 | else if (opcode == OP_ONCE) | else if (opcode == OP_ONCE) |
| 6423 | { | { |
| 6424 | cc = ccbegin + GET(ccbegin, 1); | cc = ccbegin + GET(ccbegin, 1); |
| 6425 | if (CURRENT_AS(bracket_fallback)->u.framesize >= 0) | if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
| 6426 | { | { |
| 6427 | /* Reset head and drop saved frame. */ | /* Reset head and drop saved frame. */ |
| 6428 | stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1; | stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1; |
| 6429 | free_stack(common, CURRENT_AS(bracket_fallback)->u.framesize + stacksize); | free_stack(common, CURRENT_AS(bracket_backtrack)->u.framesize + stacksize); |
| 6430 | } | } |
| 6431 | else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN)) | else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN)) |
| 6432 | { | { |
| # | Line 6007 else if (opcode == OP_ONCE) | Line 6436 else if (opcode == OP_ONCE) |
| 6436 | ||
| 6437 | JUMPHERE(once); | JUMPHERE(once); |
| 6438 | /* Restore previous localptr */ | /* Restore previous localptr */ |
| 6439 | if (CURRENT_AS(bracket_fallback)->u.framesize >= 0) | if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
| 6440 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_fallback)->u.framesize * sizeof(sljit_w)); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_w)); |
| 6441 | else if (ket == OP_KETRMIN) | else if (ket == OP_KETRMIN) |
| 6442 | { | { |
| 6443 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
| # | Line 6021 else if (opcode == OP_ONCE) | Line 6450 else if (opcode == OP_ONCE) |
| 6450 | if (ket == OP_KETRMAX) | if (ket == OP_KETRMAX) |
| 6451 | { | { |
| 6452 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 6453 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_fallback)->recursivehotpath); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursivetrypath); |
| 6454 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
| 6455 | { | { |
| 6456 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
| 6457 | JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zerotrypath); |
| 6458 | JUMPHERE(brazero); | JUMPHERE(brazero); |
| 6459 | } | } |
| 6460 | free_stack(common, 1); | free_stack(common, 1); |
| # | Line 6034 else if (ket == OP_KETRMIN) | Line 6463 else if (ket == OP_KETRMIN) |
| 6463 | { | { |
| 6464 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 6465 | ||
| 6466 | /* OP_ONCE removes everything in case of a fallback, so we don't | /* OP_ONCE removes everything in case of a backtrack, so we don't |
| 6467 | need to explicitly release the STR_PTR. The extra release would | need to explicitly release the STR_PTR. The extra release would |
| 6468 | affect badly the free_stack(2) above. */ | affect badly the free_stack(2) above. */ |
| 6469 | if (opcode != OP_ONCE) | if (opcode != OP_ONCE) |
| # | Line 6048 else if (ket == OP_KETRMIN) | Line 6477 else if (ket == OP_KETRMIN) |
| 6477 | else if (bra == OP_BRAZERO) | else if (bra == OP_BRAZERO) |
| 6478 | { | { |
| 6479 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
| 6480 | JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zerotrypath); |
| 6481 | JUMPHERE(brazero); | JUMPHERE(brazero); |
| 6482 | } | } |
| 6483 | } | } |
| 6484 | ||
| 6485 | static void compile_bracketpos_fallbackpath(compiler_common *common, struct fallback_common *current) | static void compile_bracketpos_backtrackpath(compiler_common *common, struct backtrack_common *current) |
| 6486 | { | { |
| 6487 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 6488 | int offset; | int offset; |
| 6489 | struct sljit_jump *jump; | struct sljit_jump *jump; |
| 6490 | ||
| 6491 | if (CURRENT_AS(bracketpos_fallback)->framesize < 0) | if (CURRENT_AS(bracketpos_backtrack)->framesize < 0) |
| 6492 | { | { |
| 6493 | if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS) | if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS) |
| 6494 | { | { |
| # | Line 6069 if (CURRENT_AS(bracketpos_fallback)->fra | Line 6498 if (CURRENT_AS(bracketpos_fallback)->fra |
| 6498 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); |
| 6499 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); |
| 6500 | } | } |
| 6501 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 6502 | free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize); | free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); |
| 6503 | return; | return; |
| 6504 | } | } |
| 6505 | ||
| 6506 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->localptr); |
| 6507 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
| 6508 | ||
| 6509 | if (current->topfallbacks) | if (current->topbacktracks) |
| 6510 | { | { |
| 6511 | jump = JUMP(SLJIT_JUMP); | jump = JUMP(SLJIT_JUMP); |
| 6512 | set_jumps(current->topfallbacks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
| 6513 | /* Drop the stack frame. */ | /* Drop the stack frame. */ |
| 6514 | free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize); | free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); |
| 6515 | JUMPHERE(jump); | JUMPHERE(jump); |
| 6516 | } | } |
| 6517 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_fallback)->framesize * sizeof(sljit_w)); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_w)); |
| 6518 | } | } |
| 6519 | ||
| 6520 | static void compile_braminzero_fallbackpath(compiler_common *common, struct fallback_common *current) | static void compile_braminzero_backtrackpath(compiler_common *common, struct backtrack_common *current) |
| 6521 | { | { |
| 6522 | assert_fallback fallback; | assert_backtrack backtrack; |
| 6523 | ||
| 6524 | current->top = NULL; | current->top = NULL; |
| 6525 | current->topfallbacks = NULL; | current->topbacktracks = NULL; |
| 6526 | current->nextfallbacks = NULL; | current->nextbacktracks = NULL; |
| 6527 | if (current->cc[1] > OP_ASSERTBACK_NOT) | if (current->cc[1] > OP_ASSERTBACK_NOT) |
| 6528 | { | { |
| 6529 | /* Manual call of compile_bracket_hotpath and compile_bracket_fallbackpath. */ | /* Manual call of compile_bracket_trypath and compile_bracket_backtrackpath. */ |
| 6530 | compile_bracket_hotpath(common, current->cc, current); | compile_bracket_trypath(common, current->cc, current); |
| 6531 | compile_bracket_fallbackpath(common, current->top); | compile_bracket_backtrackpath(common, current->top); |
| 6532 | } | } |
| 6533 | else | else |
| 6534 | { | { |
| 6535 | memset(&fallback, 0, sizeof(fallback)); | memset(&backtrack, 0, sizeof(backtrack)); |
| 6536 | fallback.common.cc = current->cc; | backtrack.common.cc = current->cc; |
| 6537 | fallback.hotpath = CURRENT_AS(braminzero_fallback)->hotpath; | backtrack.trypath = CURRENT_AS(braminzero_backtrack)->trypath; |
| 6538 | /* Manual call of compile_assert_hotpath. */ | /* Manual call of compile_assert_trypath. */ |
| 6539 | compile_assert_hotpath(common, current->cc, &fallback, FALSE); | compile_assert_trypath(common, current->cc, &backtrack, FALSE); |
| 6540 | } | } |
| 6541 | SLJIT_ASSERT(!current->nextfallbacks && !current->topfallbacks); | SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks); |
| 6542 | } | } |
| 6543 | ||
| 6544 | static void compile_fallbackpath(compiler_common *common, struct fallback_common *current) | static void compile_backtrackpath(compiler_common *common, struct backtrack_common *current) |
| 6545 | { | { |
| 6546 | DEFINE_COMPILER; | DEFINE_COMPILER; |
| 6547 | ||
| 6548 | while (current) | while (current) |
| 6549 | { | { |
| 6550 | if (current->nextfallbacks != NULL) | if (current->nextbacktracks != NULL) |
| 6551 | set_jumps(current->nextfallbacks, LABEL()); | set_jumps(current->nextbacktracks, LABEL()); |
| 6552 | switch(*current->cc) | switch(*current->cc) |
| 6553 | { | { |
| 6554 | case OP_SET_SOM: | case OP_SET_SOM: |
| # | Line 6198 while (current) | Line 6627 while (current) |
| 6627 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
| 6628 | case OP_XCLASS: | case OP_XCLASS: |
| 6629 | #endif | #endif |
| 6630 | compile_iterator_fallbackpath(common, current); | compile_iterator_backtrackpath(common, current); |
| 6631 | break; | break; |
| 6632 | ||
| 6633 | case OP_REF: | case OP_REF: |
| 6634 | case OP_REFI: | case OP_REFI: |