Parent Directory
|
Revision Log
|
Patch
revision 941 by zherczeg, Tue Feb 28 11:33:34 2012 UTC | revision 999 by zherczeg, Mon Aug 6 07:36:49 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 matching 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 matching path. |
95 | ||
96 | Greedy star operator (*) : | Greedy star operator (*) : |
97 | Hot path: match happens. | Matching 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. | Matching 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 matching path |
112 | '(' hot path (pushing arguments to the stack) | '(' matching path (pushing arguments to the stack) |
113 | B hot path | B matching path |
114 | ')' hot path (pushing arguments to the stack) | ')' matching path (pushing arguments to the stack) |
115 | D hot path | D matching 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 matching 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 matching 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 181 typedef struct stub_list { | Line 181 typedef struct stub_list { |
181 | enum stub_types type; | enum stub_types type; |
182 | int data; | int data; |
183 | struct sljit_jump *start; | struct sljit_jump *start; |
184 | struct sljit_label *leave; | struct sljit_label *quit; |
185 | struct stub_list *next; | struct stub_list *next; |
186 | } stub_list; | } stub_list; |
187 | ||
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_matchingpath, and contains |
192 | the aguments for compile_fallbackpath. Must be the first member | the aguments for compile_backtrackingpath. 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 *matchingpath; |
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 *alternative_matchingpath; |
220 | /* For rmin and rmax iterators. */ | /* For rmin and rmax iterators. */ |
221 | struct sljit_label *recursivehotpath; | struct sljit_label *recursive_matchingpath; |
222 | /* For greedy ? operator. */ | /* For greedy ? operator. */ |
223 | struct sljit_label *zerohotpath; | struct sljit_label *zero_matchingpath; |
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 *matchingpath; |
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 *matchingpath; |
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 264 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 | #define MAX_RANGE_SIZE 6 | |
272 | ||
273 | typedef struct compiler_common { | typedef struct compiler_common { |
274 | struct sljit_compiler *compiler; | struct sljit_compiler *compiler; |
275 | pcre_uchar *start; | pcre_uchar *start; |
276 | ||
277 | /* Local stack area size and variable pointers. */ | /* Opcode local area direct map. */ |
int localsize; | ||
278 | int *localptrs; | int *localptrs; |
279 | int cbraptr; | int cbraptr; |
280 | /* OVector starting point. Must be divisible by 2. */ | /* OVector starting point. Must be divisible by 2. */ |
# | Line 291 typedef struct compiler_common { | Line 292 typedef struct compiler_common { |
292 | /* Points to the marked string. */ | /* Points to the marked string. */ |
293 | int mark_ptr; | int mark_ptr; |
294 | ||
295 | /* Other */ | /* Flipped and lower case tables. */ |
296 | const pcre_uint8 *fcc; | const pcre_uint8 *fcc; |
297 | sljit_w lcc; | sljit_w lcc; |
298 | /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */ | |
299 | int mode; | int mode; |
300 | /* Newline control. */ | |
301 | int nltype; | int nltype; |
302 | int newline; | int newline; |
303 | int bsr_nltype; | int bsr_nltype; |
304 | /* Dollar endonly. */ | |
305 | int endonly; | int endonly; |
306 | BOOL has_set_som; | BOOL has_set_som; |
307 | /* Tables. */ | |
308 | sljit_w ctypes; | sljit_w ctypes; |
309 | int digits[2 + MAX_RANGE_SIZE]; | |
310 | /* Named capturing brackets. */ | |
311 | sljit_uw name_table; | sljit_uw name_table; |
312 | sljit_w name_count; | sljit_w name_count; |
313 | sljit_w name_entry_size; | sljit_w name_entry_size; |
314 | ||
315 | /* Labels and jump lists. */ | /* Labels and jump lists. */ |
316 | struct sljit_label *partialmatchlabel; | struct sljit_label *partialmatchlabel; |
317 | struct sljit_label *leavelabel; | struct sljit_label *quitlabel; |
318 | struct sljit_label *acceptlabel; | struct sljit_label *acceptlabel; |
319 | stub_list *stubs; | stub_list *stubs; |
320 | recurse_entry *entries; | recurse_entry *entries; |
321 | recurse_entry *currententry; | recurse_entry *currententry; |
322 | jump_list *partialmatch; | jump_list *partialmatch; |
323 | jump_list *leave; | jump_list *quit; |
324 | jump_list *accept; | jump_list *accept; |
325 | jump_list *calllimit; | jump_list *calllimit; |
326 | jump_list *stackalloc; | jump_list *stackalloc; |
# | Line 448 the start pointers when the end of the c | Line 455 the start pointers when the end of the c |
455 | 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)) |
456 | #define COND_VALUE(op, dst, dstw, type) \ | #define COND_VALUE(op, dst, dstw, type) \ |
457 | sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type)) | sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type)) |
458 | #define GET_LOCAL_BASE(dst, dstw, offset) \ | |
459 | sljit_get_local_base(compiler, (dst), (dstw), (offset)) | |
460 | ||
461 | static pcre_uchar* bracketend(pcre_uchar* cc) | static pcre_uchar* bracketend(pcre_uchar* cc) |
462 | { | { |
# | Line 466 return cc; | Line 475 return cc; |
475 | init_frame | init_frame |
476 | get_localsize | get_localsize |
477 | copy_locals | copy_locals |
478 | compile_hotpath | compile_matchingpath |
479 | compile_fallbackpath | compile_backtrackingpath |
480 | */ | */ |
481 | ||
482 | static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc) | static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc) |
# | Line 666 switch(*cc) | Line 675 switch(*cc) |
675 | } | } |
676 | } | } |
677 | ||
678 | #define CASE_ITERATOR_LOCAL1 \ | |
679 | case OP_MINSTAR: \ | |
680 | case OP_MINPLUS: \ | |
681 | case OP_QUERY: \ | |
682 | case OP_MINQUERY: \ | |
683 | case OP_MINSTARI: \ | |
684 | case OP_MINPLUSI: \ | |
685 | case OP_QUERYI: \ | |
686 | case OP_MINQUERYI: \ | |
687 | case OP_NOTMINSTAR: \ | |
688 | case OP_NOTMINPLUS: \ | |
689 | case OP_NOTQUERY: \ | |
690 | case OP_NOTMINQUERY: \ | |
691 | case OP_NOTMINSTARI: \ | |
692 | case OP_NOTMINPLUSI: \ | |
693 | case OP_NOTQUERYI: \ | |
694 | case OP_NOTMINQUERYI: | |
695 | ||
696 | #define CASE_ITERATOR_LOCAL2A \ | |
697 | case OP_STAR: \ | |
698 | case OP_PLUS: \ | |
699 | case OP_STARI: \ | |
700 | case OP_PLUSI: \ | |
701 | case OP_NOTSTAR: \ | |
702 | case OP_NOTPLUS: \ | |
703 | case OP_NOTSTARI: \ | |
704 | case OP_NOTPLUSI: | |
705 | ||
706 | #define CASE_ITERATOR_LOCAL2B \ | |
707 | case OP_UPTO: \ | |
708 | case OP_MINUPTO: \ | |
709 | case OP_UPTOI: \ | |
710 | case OP_MINUPTOI: \ | |
711 | case OP_NOTUPTO: \ | |
712 | case OP_NOTMINUPTO: \ | |
713 | case OP_NOTUPTOI: \ | |
714 | case OP_NOTMINUPTOI: | |
715 | ||
716 | #define CASE_ITERATOR_TYPE_LOCAL1 \ | |
717 | case OP_TYPEMINSTAR: \ | |
718 | case OP_TYPEMINPLUS: \ | |
719 | case OP_TYPEQUERY: \ | |
720 | case OP_TYPEMINQUERY: | |
721 | ||
722 | #define CASE_ITERATOR_TYPE_LOCAL2A \ | |
723 | case OP_TYPESTAR: \ | |
724 | case OP_TYPEPLUS: | |
725 | ||
726 | #define CASE_ITERATOR_TYPE_LOCAL2B \ | |
727 | case OP_TYPEUPTO: \ | |
728 | case OP_TYPEMINUPTO: | |
729 | ||
730 | static int get_class_iterator_size(pcre_uchar *cc) | |
731 | { | |
732 | switch(*cc) | |
733 | { | |
734 | case OP_CRSTAR: | |
735 | case OP_CRPLUS: | |
736 | return 2; | |
737 | ||
738 | case OP_CRMINSTAR: | |
739 | case OP_CRMINPLUS: | |
740 | case OP_CRQUERY: | |
741 | case OP_CRMINQUERY: | |
742 | return 1; | |
743 | ||
744 | case OP_CRRANGE: | |
745 | case OP_CRMINRANGE: | |
746 | if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE)) | |
747 | return 0; | |
748 | return 2; | |
749 | ||
750 | default: | |
751 | return 0; | |
752 | } | |
753 | } | |
754 | ||
755 | static int get_localspace(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) | static int get_localspace(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) |
756 | { | { |
757 | int localspace = 0; | int localspace = 0; |
758 | pcre_uchar *alternative; | pcre_uchar *alternative; |
759 | pcre_uchar *end = NULL; | |
760 | int space, size, bracketlen; | |
761 | ||
762 | /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ | /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ |
763 | while (cc < ccend) | while (cc < ccend) |
764 | { | { |
765 | space = 0; | |
766 | size = 0; | |
767 | bracketlen = 0; | |
768 | switch(*cc) | switch(*cc) |
769 | { | { |
770 | case OP_SET_SOM: | case OP_SET_SOM: |
# | Line 691 while (cc < ccend) | Line 783 while (cc < ccend) |
783 | case OP_SBRAPOS: | case OP_SBRAPOS: |
784 | case OP_SCOND: | case OP_SCOND: |
785 | localspace += sizeof(sljit_w); | localspace += sizeof(sljit_w); |
786 | cc += 1 + LINK_SIZE; | bracketlen = 1 + LINK_SIZE; |
787 | break; | break; |
788 | ||
789 | case OP_CBRAPOS: | case OP_CBRAPOS: |
790 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
791 | localspace += sizeof(sljit_w); | localspace += sizeof(sljit_w); |
792 | cc += 1 + LINK_SIZE + IMM2_SIZE; | bracketlen = 1 + LINK_SIZE + IMM2_SIZE; |
793 | break; | break; |
794 | ||
795 | case OP_COND: | case OP_COND: |
# | Line 705 while (cc < ccend) | Line 797 while (cc < ccend) |
797 | alternative = cc + GET(cc, 1); | alternative = cc + GET(cc, 1); |
798 | if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) | if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) |
799 | localspace += sizeof(sljit_w); | localspace += sizeof(sljit_w); |
800 | cc += 1 + LINK_SIZE; | bracketlen = 1 + LINK_SIZE; |
801 | break; | |
802 | ||
803 | case OP_BRA: | |
804 | bracketlen = 1 + LINK_SIZE; | |
805 | break; | |
806 | ||
807 | case OP_CBRA: | |
808 | case OP_SCBRA: | |
809 | bracketlen = 1 + LINK_SIZE + IMM2_SIZE; | |
810 | break; | |
811 | ||
812 | CASE_ITERATOR_LOCAL1 | |
813 | space = 1; | |
814 | size = -2; | |
815 | break; | |
816 | ||
817 | CASE_ITERATOR_LOCAL2A | |
818 | space = 2; | |
819 | size = -2; | |
820 | break; | |
821 | ||
822 | CASE_ITERATOR_LOCAL2B | |
823 | space = 2; | |
824 | size = -(2 + IMM2_SIZE); | |
825 | break; | |
826 | ||
827 | CASE_ITERATOR_TYPE_LOCAL1 | |
828 | space = 1; | |
829 | size = 1; | |
830 | break; | |
831 | ||
832 | CASE_ITERATOR_TYPE_LOCAL2A | |
833 | if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI) | |
834 | space = 2; | |
835 | size = 1; | |
836 | break; | break; |
837 | ||
838 | CASE_ITERATOR_TYPE_LOCAL2B | |
839 | if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) | |
840 | space = 2; | |
841 | size = 1 + IMM2_SIZE; | |
842 | break; | |
843 | ||
844 | case OP_CLASS: | |
845 | case OP_NCLASS: | |
846 | size += 1 + 32 / sizeof(pcre_uchar); | |
847 | space = get_class_iterator_size(cc + size); | |
848 | break; | |
849 | ||
850 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | |
851 | case OP_XCLASS: | |
852 | size = GET(cc, 1); | |
853 | space = get_class_iterator_size(cc + size); | |
854 | break; | |
855 | #endif | |
856 | ||
857 | case OP_RECURSE: | case OP_RECURSE: |
858 | /* Set its value only once. */ | /* Set its value only once. */ |
859 | if (common->recursive_head == 0) | if (common->recursive_head == 0) |
# | Line 733 while (cc < ccend) | Line 879 while (cc < ccend) |
879 | return -1; | return -1; |
880 | break; | break; |
881 | } | } |
882 | ||
883 | if (space > 0 && cc >= end) | |
884 | localspace += sizeof(sljit_w) * space; | |
885 | ||
886 | if (size != 0) | |
887 | { | |
888 | if (size < 0) | |
889 | { | |
890 | cc += -size; | |
891 | #ifdef SUPPORT_UTF | |
892 | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); | |
893 | #endif | |
894 | } | |
895 | else | |
896 | cc += size; | |
897 | } | |
898 | ||
899 | if (bracketlen > 0) | |
900 | { | |
901 | if (cc >= end) | |
902 | { | |
903 | end = bracketend(cc); | |
904 | if (end[-1 - LINK_SIZE] == OP_KET) | |
905 | end = NULL; | |
906 | } | |
907 | cc += bracketlen; | |
908 | } | |
909 | } | } |
910 | return localspace; | return localspace; |
911 | } | } |
# | Line 741 static void set_localptrs(compiler_commo | Line 914 static void set_localptrs(compiler_commo |
914 | { | { |
915 | pcre_uchar *cc = common->start; | pcre_uchar *cc = common->start; |
916 | pcre_uchar *alternative; | pcre_uchar *alternative; |
917 | pcre_uchar *end = NULL; | |
918 | int space, size, bracketlen; | |
919 | ||
920 | while (cc < ccend) | while (cc < ccend) |
921 | { | { |
922 | space = 0; | |
923 | size = 0; | |
924 | bracketlen = 0; | |
925 | switch(*cc) | switch(*cc) |
926 | { | { |
927 | case OP_ASSERT: | case OP_ASSERT: |
# | Line 757 while (cc < ccend) | Line 936 while (cc < ccend) |
936 | case OP_SCOND: | case OP_SCOND: |
937 | common->localptrs[cc - common->start] = localptr; | common->localptrs[cc - common->start] = localptr; |
938 | localptr += sizeof(sljit_w); | localptr += sizeof(sljit_w); |
939 | cc += 1 + LINK_SIZE; | bracketlen = 1 + LINK_SIZE; |
940 | break; | break; |
941 | ||
942 | case OP_CBRAPOS: | case OP_CBRAPOS: |
943 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
944 | common->localptrs[cc - common->start] = localptr; | common->localptrs[cc - common->start] = localptr; |
945 | localptr += sizeof(sljit_w); | localptr += sizeof(sljit_w); |
946 | cc += 1 + LINK_SIZE + IMM2_SIZE; | bracketlen = 1 + LINK_SIZE + IMM2_SIZE; |
947 | break; | break; |
948 | ||
949 | case OP_COND: | case OP_COND: |
# | Line 775 while (cc < ccend) | Line 954 while (cc < ccend) |
954 | common->localptrs[cc - common->start] = localptr; | common->localptrs[cc - common->start] = localptr; |
955 | localptr += sizeof(sljit_w); | localptr += sizeof(sljit_w); |
956 | } | } |
957 | cc += 1 + LINK_SIZE; | bracketlen = 1 + LINK_SIZE; |
958 | break; | break; |
959 | ||
960 | case OP_BRA: | |
961 | bracketlen = 1 + LINK_SIZE; | |
962 | break; | |
963 | ||
964 | case OP_CBRA: | |
965 | case OP_SCBRA: | |
966 | bracketlen = 1 + LINK_SIZE + IMM2_SIZE; | |
967 | break; | |
968 | ||
969 | CASE_ITERATOR_LOCAL1 | |
970 | space = 1; | |
971 | size = -2; | |
972 | break; | |
973 | ||
974 | CASE_ITERATOR_LOCAL2A | |
975 | space = 2; | |
976 | size = -2; | |
977 | break; | |
978 | ||
979 | CASE_ITERATOR_LOCAL2B | |
980 | space = 2; | |
981 | size = -(2 + IMM2_SIZE); | |
982 | break; | |
983 | ||
984 | CASE_ITERATOR_TYPE_LOCAL1 | |
985 | space = 1; | |
986 | size = 1; | |
987 | break; | |
988 | ||
989 | CASE_ITERATOR_TYPE_LOCAL2A | |
990 | if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI) | |
991 | space = 2; | |
992 | size = 1; | |
993 | break; | |
994 | ||
995 | CASE_ITERATOR_TYPE_LOCAL2B | |
996 | if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) | |
997 | space = 2; | |
998 | size = 1 + IMM2_SIZE; | |
999 | break; | |
1000 | ||
1001 | case OP_CLASS: | |
1002 | case OP_NCLASS: | |
1003 | size += 1 + 32 / sizeof(pcre_uchar); | |
1004 | space = get_class_iterator_size(cc + size); | |
1005 | break; | |
1006 | ||
1007 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | |
1008 | case OP_XCLASS: | |
1009 | size = GET(cc, 1); | |
1010 | space = get_class_iterator_size(cc + size); | |
1011 | break; | |
1012 | #endif | |
1013 | ||
1014 | default: | default: |
1015 | cc = next_opcode(common, cc); | cc = next_opcode(common, cc); |
1016 | SLJIT_ASSERT(cc != NULL); | SLJIT_ASSERT(cc != NULL); |
1017 | break; | break; |
1018 | } | } |
1019 | ||
1020 | if (space > 0 && cc >= end) | |
1021 | { | |
1022 | common->localptrs[cc - common->start] = localptr; | |
1023 | localptr += sizeof(sljit_w) * space; | |
1024 | } | |
1025 | ||
1026 | if (size != 0) | |
1027 | { | |
1028 | if (size < 0) | |
1029 | { | |
1030 | cc += -size; | |
1031 | #ifdef SUPPORT_UTF | |
1032 | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); | |
1033 | #endif | |
1034 | } | |
1035 | else | |
1036 | cc += size; | |
1037 | } | |
1038 | ||
1039 | if (bracketlen > 0) | |
1040 | { | |
1041 | if (cc >= end) | |
1042 | { | |
1043 | end = bracketend(cc); | |
1044 | if (end[-1 - LINK_SIZE] == OP_KET) | |
1045 | end = NULL; | |
1046 | } | |
1047 | cc += bracketlen; | |
1048 | } | |
1049 | } | } |
1050 | } | } |
1051 | ||
# | Line 962 SLJIT_ASSERT(stackpos == STACK(stacktop) | Line 1225 SLJIT_ASSERT(stackpos == STACK(stacktop) |
1225 | static SLJIT_INLINE int get_localsize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) | static SLJIT_INLINE int get_localsize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) |
1226 | { | { |
1227 | int localsize = 2; | int localsize = 2; |
1228 | int size; | |
1229 | pcre_uchar *alternative; | pcre_uchar *alternative; |
1230 | /* Calculate the sum of the local variables. */ | /* Calculate the sum of the local variables. */ |
1231 | while (cc < ccend) | while (cc < ccend) |
1232 | { | { |
1233 | size = 0; | |
1234 | switch(*cc) | switch(*cc) |
1235 | { | { |
1236 | case OP_ASSERT: | case OP_ASSERT: |
# | Line 1002 while (cc < ccend) | Line 1267 while (cc < ccend) |
1267 | cc += 1 + LINK_SIZE; | cc += 1 + LINK_SIZE; |
1268 | break; | break; |
1269 | ||
1270 | CASE_ITERATOR_LOCAL1 | |
1271 | if (PRIV_DATA(cc)) | |
1272 | localsize++; | |
1273 | cc += 2; | |
1274 | #ifdef SUPPORT_UTF | |
1275 | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); | |
1276 | #endif | |
1277 | break; | |
1278 | ||
1279 | CASE_ITERATOR_LOCAL2A | |
1280 | if (PRIV_DATA(cc)) | |
1281 | localsize += 2; | |
1282 | cc += 2; | |
1283 | #ifdef SUPPORT_UTF | |
1284 | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); | |
1285 | #endif | |
1286 | break; | |
1287 | ||
1288 | CASE_ITERATOR_LOCAL2B | |
1289 | if (PRIV_DATA(cc)) | |
1290 | localsize += 2; | |
1291 | cc += 2 + IMM2_SIZE; | |
1292 | #ifdef SUPPORT_UTF | |
1293 | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); | |
1294 | #endif | |
1295 | break; | |
1296 | ||
1297 | CASE_ITERATOR_TYPE_LOCAL1 | |
1298 | if (PRIV_DATA(cc)) | |
1299 | localsize++; | |
1300 | cc += 1; | |
1301 | break; | |
1302 | ||
1303 | CASE_ITERATOR_TYPE_LOCAL2A | |
1304 | if (PRIV_DATA(cc)) | |
1305 | localsize += 2; | |
1306 | cc += 1; | |
1307 | break; | |
1308 | ||
1309 | CASE_ITERATOR_TYPE_LOCAL2B | |
1310 | if (PRIV_DATA(cc)) | |
1311 | localsize += 2; | |
1312 | cc += 1 + IMM2_SIZE; | |
1313 | break; | |
1314 | ||
1315 | case OP_CLASS: | |
1316 | case OP_NCLASS: | |
1317 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | |
1318 | case OP_XCLASS: | |
1319 | size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar); | |
1320 | #else | |
1321 | size = 1 + 32 / (int)sizeof(pcre_uchar); | |
1322 | #endif | |
1323 | if (PRIV_DATA(cc)) | |
1324 | localsize += get_class_iterator_size(cc + size); | |
1325 | cc += size; | |
1326 | break; | |
1327 | ||
1328 | default: | default: |
1329 | cc = next_opcode(common, cc); | cc = next_opcode(common, cc); |
1330 | SLJIT_ASSERT(cc != NULL); | SLJIT_ASSERT(cc != NULL); |
# | Line 1017 static void copy_locals(compiler_common | Line 1340 static void copy_locals(compiler_common |
1340 | { | { |
1341 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1342 | int srcw[2]; | int srcw[2]; |
1343 | int count; | int count, size; |
1344 | BOOL tmp1next = TRUE; | BOOL tmp1next = TRUE; |
1345 | BOOL tmp1empty = TRUE; | BOOL tmp1empty = TRUE; |
1346 | BOOL tmp2empty = TRUE; | BOOL tmp2empty = TRUE; |
# | Line 1097 while (status != end) | Line 1420 while (status != end) |
1420 | case OP_CBRAPOS: | case OP_CBRAPOS: |
1421 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
1422 | count = 2; | count = 2; |
1423 | srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); | srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); |
1424 | srcw[0] = PRIV_DATA(cc); | srcw[1] = PRIV_DATA(cc); |
1425 | SLJIT_ASSERT(srcw[0] != 0); | SLJIT_ASSERT(srcw[0] != 0); |
1426 | cc += 1 + LINK_SIZE + IMM2_SIZE; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
1427 | break; | break; |
# | Line 1115 while (status != end) | Line 1438 while (status != end) |
1438 | cc += 1 + LINK_SIZE; | cc += 1 + LINK_SIZE; |
1439 | break; | break; |
1440 | ||
1441 | CASE_ITERATOR_LOCAL1 | |
1442 | if (PRIV_DATA(cc)) | |
1443 | { | |
1444 | count = 1; | |
1445 | srcw[0] = PRIV_DATA(cc); | |
1446 | } | |
1447 | cc += 2; | |
1448 | #ifdef SUPPORT_UTF | |
1449 | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); | |
1450 | #endif | |
1451 | break; | |
1452 | ||
1453 | CASE_ITERATOR_LOCAL2A | |
1454 | if (PRIV_DATA(cc)) | |
1455 | { | |
1456 | count = 2; | |
1457 | srcw[0] = PRIV_DATA(cc); | |
1458 | srcw[1] = PRIV_DATA(cc) + sizeof(sljit_w); | |
1459 | } | |
1460 | cc += 2; | |
1461 | #ifdef SUPPORT_UTF | |
1462 | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); | |
1463 | #endif | |
1464 | break; | |
1465 | ||
1466 | CASE_ITERATOR_LOCAL2B | |
1467 | if (PRIV_DATA(cc)) | |
1468 | { | |
1469 | count = 2; | |
1470 | srcw[0] = PRIV_DATA(cc); | |
1471 | srcw[1] = PRIV_DATA(cc) + sizeof(sljit_w); | |
1472 | } | |
1473 | cc += 2 + IMM2_SIZE; | |
1474 | #ifdef SUPPORT_UTF | |
1475 | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); | |
1476 | #endif | |
1477 | break; | |
1478 | ||
1479 | CASE_ITERATOR_TYPE_LOCAL1 | |
1480 | if (PRIV_DATA(cc)) | |
1481 | { | |
1482 | count = 1; | |
1483 | srcw[0] = PRIV_DATA(cc); | |
1484 | } | |
1485 | cc += 1; | |
1486 | break; | |
1487 | ||
1488 | CASE_ITERATOR_TYPE_LOCAL2A | |
1489 | if (PRIV_DATA(cc)) | |
1490 | { | |
1491 | count = 2; | |
1492 | srcw[0] = PRIV_DATA(cc); | |
1493 | srcw[1] = srcw[0] + sizeof(sljit_w); | |
1494 | } | |
1495 | cc += 1; | |
1496 | break; | |
1497 | ||
1498 | CASE_ITERATOR_TYPE_LOCAL2B | |
1499 | if (PRIV_DATA(cc)) | |
1500 | { | |
1501 | count = 2; | |
1502 | srcw[0] = PRIV_DATA(cc); | |
1503 | srcw[1] = srcw[0] + sizeof(sljit_w); | |
1504 | } | |
1505 | cc += 1 + IMM2_SIZE; | |
1506 | break; | |
1507 | ||
1508 | case OP_CLASS: | |
1509 | case OP_NCLASS: | |
1510 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | |
1511 | case OP_XCLASS: | |
1512 | size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar); | |
1513 | #else | |
1514 | size = 1 + 32 / (int)sizeof(pcre_uchar); | |
1515 | #endif | |
1516 | if (PRIV_DATA(cc)) | |
1517 | switch(get_class_iterator_size(cc + size)) | |
1518 | { | |
1519 | case 1: | |
1520 | count = 1; | |
1521 | srcw[0] = PRIV_DATA(cc); | |
1522 | break; | |
1523 | ||
1524 | case 2: | |
1525 | count = 2; | |
1526 | srcw[0] = PRIV_DATA(cc); | |
1527 | srcw[1] = srcw[0] + sizeof(sljit_w); | |
1528 | break; | |
1529 | ||
1530 | default: | |
1531 | SLJIT_ASSERT_STOP(); | |
1532 | break; | |
1533 | } | |
1534 | cc += size; | |
1535 | break; | |
1536 | ||
1537 | default: | default: |
1538 | cc = next_opcode(common, cc); | cc = next_opcode(common, cc); |
1539 | SLJIT_ASSERT(cc != NULL); | SLJIT_ASSERT(cc != NULL); |
# | Line 1217 if (save) | Line 1636 if (save) |
1636 | SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); | SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); |
1637 | } | } |
1638 | ||
1639 | #undef CASE_ITERATOR_LOCAL1 | |
1640 | #undef CASE_ITERATOR_LOCAL2A | |
1641 | #undef CASE_ITERATOR_LOCAL2B | |
1642 | #undef CASE_ITERATOR_TYPE_LOCAL1 | |
1643 | #undef CASE_ITERATOR_TYPE_LOCAL2A | |
1644 | #undef CASE_ITERATOR_TYPE_LOCAL2B | |
1645 | ||
1646 | static SLJIT_INLINE BOOL ispowerof2(unsigned int value) | static SLJIT_INLINE BOOL ispowerof2(unsigned int value) |
1647 | { | { |
1648 | return (value & (value - 1)) == 0; | return (value & (value - 1)) == 0; |
# | Line 1227 static SLJIT_INLINE void set_jumps(jump_ | Line 1653 static SLJIT_INLINE void set_jumps(jump_ |
1653 | while (list) | while (list) |
1654 | { | { |
1655 | /* sljit_set_label is clever enough to do nothing | /* sljit_set_label is clever enough to do nothing |
1656 | if either the jump or the label is NULL */ | if either the jump or the label is NULL. */ |
1657 | sljit_set_label(list->jump, label); | sljit_set_label(list->jump, label); |
1658 | list = list->next; | list = list->next; |
1659 | } | } |
# | Line 1254 if (list_item) | Line 1680 if (list_item) |
1680 | list_item->type = type; | list_item->type = type; |
1681 | list_item->data = data; | list_item->data = data; |
1682 | list_item->start = start; | list_item->start = start; |
1683 | list_item->leave = LABEL(); | list_item->quit = LABEL(); |
1684 | list_item->next = common->stubs; | list_item->next = common->stubs; |
1685 | common->stubs = list_item; | common->stubs = list_item; |
1686 | } | } |
# | Line 1274 while (list_item) | Line 1700 while (list_item) |
1700 | add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL)); |
1701 | break; | break; |
1702 | } | } |
1703 | JUMPTO(SLJIT_JUMP, list_item->leave); | JUMPTO(SLJIT_JUMP, list_item->quit); |
1704 | list_item = list_item->next; | list_item = list_item->next; |
1705 | } | } |
1706 | common->stubs = NULL; | common->stubs = NULL; |
# | Line 1325 if (length < 8) | Line 1751 if (length < 8) |
1751 | } | } |
1752 | else | else |
1753 | { | { |
1754 | 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)); |
1755 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length); |
1756 | loop = LABEL(); | loop = LABEL(); |
1757 | 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 1352 if (common->mark_ptr != 0) | Line 1778 if (common->mark_ptr != 0) |
1778 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_TEMPORARY_REG3, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_TEMPORARY_REG3, 0); |
1779 | 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)); |
1780 | 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)); |
1781 | OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START); | GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START); |
1782 | /* Unlikely, but possible */ | /* Unlikely, but possible */ |
1783 | earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); | earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); |
1784 | loop = LABEL(); | loop = LABEL(); |
# | Line 1370 JUMPHERE(earlyexit); | Line 1796 JUMPHERE(earlyexit); |
1796 | /* Calculate the return value, which is the maximum ovector value. */ | /* Calculate the return value, which is the maximum ovector value. */ |
1797 | if (topbracket > 1) | if (topbracket > 1) |
1798 | { | { |
1799 | 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)); |
1800 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); |
1801 | ||
1802 | /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ | /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ |
# | Line 1384 else | Line 1810 else |
1810 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); |
1811 | } | } |
1812 | ||
1813 | static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *leave) | static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *quit) |
1814 | { | { |
1815 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1816 | ||
# | Line 1394 SLJIT_ASSERT(common->start_used_ptr != 0 | Line 1820 SLJIT_ASSERT(common->start_used_ptr != 0 |
1820 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); |
1821 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); |
1822 | OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsetcount)); | OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsetcount)); |
1823 | CMPTO(SLJIT_C_LESS, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 2, leave); | CMPTO(SLJIT_C_LESS, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 2, quit); |
1824 | ||
1825 | /* Store match begin and end. */ | /* Store match begin and end. */ |
1826 | OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, begin)); |
# | Line 1412 OP2(SLJIT_ASHR, SLJIT_TEMPORARY_REG3, 0, | Line 1838 OP2(SLJIT_ASHR, SLJIT_TEMPORARY_REG3, 0, |
1838 | #endif | #endif |
1839 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), 0, SLJIT_TEMPORARY_REG3, 0); | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), 0, SLJIT_TEMPORARY_REG3, 0); |
1840 | ||
1841 | JUMPTO(SLJIT_JUMP, leave); | JUMPTO(SLJIT_JUMP, quit); |
1842 | } | } |
1843 | ||
1844 | static SLJIT_INLINE void check_start_used_ptr(compiler_common *common) | static SLJIT_INLINE void check_start_used_ptr(compiler_common *common) |
# | Line 1621 JUMPHERE(jump); | Line 2047 JUMPHERE(jump); |
2047 | return return_value; | return return_value; |
2048 | } | } |
2049 | ||
2050 | static void fallback_at_str_end(compiler_common *common, jump_list **fallbacks) | static void detect_partial_match(compiler_common *common, jump_list **backtracks) |
2051 | { | { |
2052 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2053 | struct sljit_jump *jump; | struct sljit_jump *jump; |
2054 | ||
2055 | if (common->mode == JIT_COMPILE) | if (common->mode == JIT_COMPILE) |
2056 | { | { |
2057 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
2058 | return; | return; |
2059 | } | } |
2060 | ||
2061 | /* Partial matching mode. */ | /* Partial matching mode. */ |
2062 | jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); |
2063 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); |
2064 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2065 | { | { |
2066 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); |
2067 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
2068 | } | } |
2069 | else | else |
2070 | { | { |
# | Line 1788 if (common->utf) | Line 2214 if (common->utf) |
2214 | 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)); |
2215 | } | } |
2216 | ||
2217 | 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) |
2218 | { | { |
2219 | /* 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. */ |
2220 | DEFINE_COMPILER; | DEFINE_COMPILER; |
# | Line 1796 DEFINE_COMPILER; | Line 2222 DEFINE_COMPILER; |
2222 | if (nltype == NLTYPE_ANY) | if (nltype == NLTYPE_ANY) |
2223 | { | { |
2224 | add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); |
2225 | 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)); |
2226 | } | } |
2227 | else if (nltype == NLTYPE_ANYCRLF) | else if (nltype == NLTYPE_ANYCRLF) |
2228 | { | { |
# | Line 1804 else if (nltype == NLTYPE_ANYCRLF) | Line 2230 else if (nltype == NLTYPE_ANYCRLF) |
2230 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
2231 | 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); |
2232 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
2233 | 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)); |
2234 | } | } |
2235 | else | else |
2236 | { | { |
2237 | SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); | SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); |
2238 | 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)); |
2239 | } | } |
2240 | } | } |
2241 | ||
# | Line 1823 of the character (>= 0xc0). Return char | Line 2249 of the character (>= 0xc0). Return char |
2249 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2250 | struct sljit_jump *jump; | struct sljit_jump *jump; |
2251 | ||
2252 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
2253 | /* Searching for the first zero. */ | /* Searching for the first zero. */ |
2254 | 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); |
2255 | jump = JUMP(SLJIT_C_NOT_ZERO); | jump = JUMP(SLJIT_C_NOT_ZERO); |
# | Line 1882 DEFINE_COMPILER; | Line 2308 DEFINE_COMPILER; |
2308 | struct sljit_jump *jump; | struct sljit_jump *jump; |
2309 | struct sljit_jump *compare; | struct sljit_jump *compare; |
2310 | ||
2311 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
2312 | ||
2313 | 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); |
2314 | jump = JUMP(SLJIT_C_NOT_ZERO); | jump = JUMP(SLJIT_C_NOT_ZERO); |
# | Line 1919 of the character (>= 0xd800). Return cha | Line 2345 of the character (>= 0xd800). Return cha |
2345 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2346 | struct sljit_jump *jump; | struct sljit_jump *jump; |
2347 | ||
2348 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
2349 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00); | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00); |
2350 | /* Do nothing, only return. */ | /* Do nothing, only return. */ |
2351 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
# | Line 1956 DEFINE_COMPILER; | Line 2382 DEFINE_COMPILER; |
2382 | ||
2383 | SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8); | SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8); |
2384 | ||
2385 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
2386 | OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); | OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); |
2387 | 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)); |
2388 | 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 1993 if (firstline) | Line 2419 if (firstline) |
2419 | { | { |
2420 | /* Search for the end of the first line. */ | /* Search for the end of the first line. */ |
2421 | SLJIT_ASSERT(common->first_line_end != 0); | SLJIT_ASSERT(common->first_line_end != 0); |
2422 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0); | OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_END, 0); | ||
2423 | ||
2424 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
2425 | { | { |
# | Line 2005 if (firstline) | Line 2430 if (firstline) |
2430 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
2431 | 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); |
2432 | 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); |
2433 | JUMPHERE(end); | |
2434 | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
2435 | } | } |
2436 | else | else |
# | Line 2016 if (firstline) | Line 2442 if (firstline) |
2442 | read_char(common); | read_char(common); |
2443 | check_newlinechar(common, common->nltype, &newline, TRUE); | check_newlinechar(common, common->nltype, &newline, TRUE); |
2444 | CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); | CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); |
2445 | JUMPHERE(end); | |
2446 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0); |
2447 | set_jumps(newline, LABEL()); | set_jumps(newline, LABEL()); |
2448 | } | } |
2449 | ||
2450 | JUMPHERE(end); | OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | ||
2451 | } | } |
2452 | ||
2453 | start = JUMP(SLJIT_JUMP); | start = JUMP(SLJIT_JUMP); |
# | Line 2043 if (newlinecheck) | Line 2469 if (newlinecheck) |
2469 | ||
2470 | mainloop = LABEL(); | mainloop = LABEL(); |
2471 | ||
2472 | /* Increasing the STR_PTR here requires one less jump in the most common case. */ | /* Increasing the STR_PTR here requires one less jump in the most common case. */ |
2473 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
2474 | if (common->utf) readuchar = TRUE; | if (common->utf) readuchar = TRUE; |
2475 | #endif | |
2476 | if (newlinecheck) readuchar = TRUE; | |
2477 | ||
2478 | if (readuchar) | |
2479 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | |
2480 | ||
2481 | if (newlinecheck) | |
2482 | CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); | |
2483 | ||
2484 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
2485 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | |
2486 | if (common->utf) | |
2487 | { | |
2488 | singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); | |
2489 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); | |
2490 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
2491 | JUMPHERE(singlechar); | |
2492 | } | |
2493 | #endif | |
2494 | #if defined SUPPORT_UTF && defined COMPILE_PCRE16 | |
2495 | if (common->utf) | |
2496 | { | |
2497 | singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | |
2498 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | |
2499 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | |
2500 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | |
2501 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | |
2502 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
2503 | JUMPHERE(singlechar); | |
2504 | } | |
2505 | #endif | |
2506 | JUMPHERE(start); | |
2507 | ||
2508 | if (newlinecheck) | |
2509 | { | |
2510 | JUMPHERE(end); | |
2511 | JUMPHERE(nl); | |
2512 | } | |
2513 | ||
2514 | return mainloop; | |
2515 | } | |
2516 | ||
2517 | static SLJIT_INLINE BOOL fast_forward_first_two_chars(compiler_common *common, BOOL firstline) | |
2518 | { | |
2519 | DEFINE_COMPILER; | |
2520 | struct sljit_label *start; | |
2521 | struct sljit_jump *quit; | |
2522 | struct sljit_jump *found; | |
2523 | pcre_int32 chars[4]; | |
2524 | pcre_uchar *cc = common->start + 1 + IMM2_SIZE; | |
2525 | int location = 0; | |
2526 | pcre_int32 len, c, bit, caseless; | |
2527 | BOOL must_end; | |
2528 | ||
2529 | #ifdef COMPILE_PCRE8 | |
2530 | union { | |
2531 | sljit_uh ascombined; | |
2532 | sljit_ub asuchars[2]; | |
2533 | } pair; | |
2534 | #else | |
2535 | union { | |
2536 | sljit_ui ascombined; | |
2537 | sljit_uh asuchars[2]; | |
2538 | } pair; | |
2539 | #endif | |
2540 | ||
2541 | if (*(common->start + GET(common->start, 1)) == OP_ALT) | |
2542 | return FALSE; | |
2543 | ||
2544 | while (TRUE) | |
2545 | { | |
2546 | caseless = 0; | |
2547 | must_end = TRUE; | |
2548 | switch(*cc) | |
2549 | { | |
2550 | case OP_CHAR: | |
2551 | must_end = FALSE; | |
2552 | cc++; | |
2553 | break; | |
2554 | ||
2555 | case OP_CHARI: | |
2556 | caseless = 1; | |
2557 | must_end = FALSE; | |
2558 | cc++; | |
2559 | break; | |
2560 | ||
2561 | case OP_SOD: | |
2562 | case OP_SOM: | |
2563 | case OP_SET_SOM: | |
2564 | case OP_NOT_WORD_BOUNDARY: | |
2565 | case OP_WORD_BOUNDARY: | |
2566 | case OP_EODN: | |
2567 | case OP_EOD: | |
2568 | case OP_CIRC: | |
2569 | case OP_CIRCM: | |
2570 | case OP_DOLL: | |
2571 | case OP_DOLLM: | |
2572 | /* Zero width assertions. */ | |
2573 | cc++; | |
2574 | continue; | |
2575 | ||
2576 | case OP_PLUS: | |
2577 | case OP_MINPLUS: | |
2578 | case OP_POSPLUS: | |
2579 | cc++; | |
2580 | break; | |
2581 | ||
2582 | case OP_EXACT: | |
2583 | cc += 1 + IMM2_SIZE; | |
2584 | break; | |
2585 | ||
2586 | case OP_PLUSI: | |
2587 | case OP_MINPLUSI: | |
2588 | case OP_POSPLUSI: | |
2589 | caseless = 1; | |
2590 | cc++; | |
2591 | break; | |
2592 | ||
2593 | case OP_EXACTI: | |
2594 | caseless = 1; | |
2595 | cc += 1 + IMM2_SIZE; | |
2596 | break; | |
2597 | ||
2598 | default: | |
2599 | return FALSE; | |
2600 | } | |
2601 | ||
2602 | len = 1; | |
2603 | #ifdef SUPPORT_UTF | |
2604 | if (common->utf && HAS_EXTRALEN(cc[0])) len += GET_EXTRALEN(cc[0]); | |
2605 | #endif | |
2606 | ||
2607 | if (caseless && char_has_othercase(common, cc)) | |
2608 | { | |
2609 | caseless = char_get_othercase_bit(common, cc); | |
2610 | if (caseless == 0) | |
2611 | return FALSE; | |
2612 | #ifdef COMPILE_PCRE8 | |
2613 | caseless = ((caseless & 0xff) << 8) | (len - (caseless >> 8)); | |
2614 | #else | |
2615 | if ((caseless & 0x100) != 0) | |
2616 | caseless = ((caseless & 0xff) << 16) | (len - (caseless >> 9)); | |
2617 | else | |
2618 | caseless = ((caseless & 0xff) << 8) | (len - (caseless >> 9)); | |
2619 | #endif | |
2620 | } | |
2621 | else | |
2622 | caseless = 0; | |
2623 | ||
2624 | while (len > 0 && location < 2 * 2) | |
2625 | { | |
2626 | c = *cc; | |
2627 | bit = 0; | |
2628 | if (len == (caseless & 0xff)) | |
2629 | { | |
2630 | bit = caseless >> 8; | |
2631 | c |= bit; | |
2632 | } | |
2633 | ||
2634 | chars[location] = c; | |
2635 | chars[location + 1] = bit; | |
2636 | ||
2637 | len--; | |
2638 | location += 2; | |
2639 | cc++; | |
2640 | } | |
2641 | ||
2642 | if (location == 2 * 2) | |
2643 | break; | |
2644 | else if (must_end) | |
2645 | return FALSE; | |
2646 | } | |
2647 | ||
2648 | if (firstline) | |
2649 | { | |
2650 | SLJIT_ASSERT(common->first_line_end != 0); | |
2651 | OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); | |
2652 | OP2(SLJIT_SUB, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, SLJIT_IMM, 1); | |
2653 | } | |
2654 | else | |
2655 | OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, 1); | |
2656 | ||
2657 | start = LABEL(); | |
2658 | quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | |
2659 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | |
2660 | #ifdef COMPILE_PCRE8 | |
2661 | OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | |
2662 | #else /* COMPILE_PCRE8 */ | |
2663 | OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | |
2664 | #endif | #endif |
if (newlinecheck) readuchar = TRUE; | ||
2665 | ||
2666 | if (readuchar) | #else /* SLJIT_UNALIGNED */ |
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | ||
2667 | ||
2668 | if (newlinecheck) | #if defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN |
2669 | CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); |
2670 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | |
2671 | #else /* SLJIT_BIG_ENDIAN */ | |
2672 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | |
2673 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | |
2674 | #endif /* SLJIT_BIG_ENDIAN */ | |
2675 | ||
2676 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | #ifdef COMPILE_PCRE8 |
2677 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 8); |
2678 | if (common->utf) | #else /* COMPILE_PCRE8 */ |
2679 | { | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 16); |
singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); | ||
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | ||
JUMPHERE(singlechar); | ||
} | ||
2680 | #endif | #endif |
2681 | #if defined SUPPORT_UTF && defined COMPILE_PCRE16 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
2682 | if (common->utf) | |
{ | ||
singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | ||
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | ||
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | ||
COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | ||
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | ||
JUMPHERE(singlechar); | ||
} | ||
2683 | #endif | #endif |
JUMPHERE(start); | ||
2684 | ||
2685 | if (newlinecheck) | if (chars[1] != 0 || chars[3] != 0) |
2686 | { | { |
2687 | JUMPHERE(end); | pair.asuchars[0] = chars[1]; |
2688 | JUMPHERE(nl); | pair.asuchars[1] = chars[3]; |
2689 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, pair.ascombined); | |
2690 | } | } |
2691 | ||
2692 | return mainloop; | pair.asuchars[0] = chars[0]; |
2693 | pair.asuchars[1] = chars[2]; | |
2694 | found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, pair.ascombined); | |
2695 | ||
2696 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
2697 | JUMPTO(SLJIT_JUMP, start); | |
2698 | JUMPHERE(found); | |
2699 | JUMPHERE(quit); | |
2700 | ||
2701 | if (firstline) | |
2702 | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); | |
2703 | else | |
2704 | OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, 1); | |
2705 | return TRUE; | |
2706 | } | } |
2707 | ||
2708 | static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline) | static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline) |
2709 | { | { |
2710 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2711 | struct sljit_label *start; | struct sljit_label *start; |
2712 | struct sljit_jump *leave; | struct sljit_jump *quit; |
2713 | struct sljit_jump *found; | struct sljit_jump *found; |
2714 | pcre_uchar oc, bit; | pcre_uchar oc, bit; |
2715 | ||
2716 | if (firstline) | if (firstline) |
2717 | { | { |
2718 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); | SLJIT_ASSERT(common->first_line_end != 0); |
2719 | OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); | |
2720 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); |
2721 | } | } |
2722 | ||
2723 | start = LABEL(); | start = LABEL(); |
2724 | leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
2725 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
2726 | ||
2727 | oc = first_char; | oc = first_char; |
# | Line 2136 else | Line 2754 else |
2754 | } | } |
2755 | ||
2756 | 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)); |
#if defined SUPPORT_UTF && defined COMPILE_PCRE8 | ||
if (common->utf) | ||
{ | ||
CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); | ||
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | ||
} | ||
#endif | ||
#if defined SUPPORT_UTF && defined COMPILE_PCRE16 | ||
if (common->utf) | ||
{ | ||
CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); | ||
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | ||
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | ||
COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | ||
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | ||
} | ||
#endif | ||
2757 | JUMPTO(SLJIT_JUMP, start); | JUMPTO(SLJIT_JUMP, start); |
2758 | JUMPHERE(found); | JUMPHERE(found); |
2759 | JUMPHERE(leave); | JUMPHERE(quit); |
2760 | ||
2761 | if (firstline) | if (firstline) |
2762 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); |
2763 | } | } |
2764 | ||
2765 | static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline) | static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline) |
# | Line 2169 DEFINE_COMPILER; | Line 2768 DEFINE_COMPILER; |
2768 | struct sljit_label *loop; | struct sljit_label *loop; |
2769 | struct sljit_jump *lastchar; | struct sljit_jump *lastchar; |
2770 | struct sljit_jump *firstchar; | struct sljit_jump *firstchar; |
2771 | struct sljit_jump *leave; | struct sljit_jump *quit; |
2772 | struct sljit_jump *foundcr = NULL; | struct sljit_jump *foundcr = NULL; |
2773 | struct sljit_jump *notfoundnl; | struct sljit_jump *notfoundnl; |
2774 | jump_list *newline = NULL; | jump_list *newline = NULL; |
2775 | ||
2776 | if (firstline) | if (firstline) |
2777 | { | { |
2778 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); | SLJIT_ASSERT(common->first_line_end != 0); |
2779 | OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); | |
2780 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); |
2781 | } | } |
2782 | ||
# | Line 2198 if (common->nltype == NLTYPE_FIXED && co | Line 2798 if (common->nltype == NLTYPE_FIXED && co |
2798 | ||
2799 | loop = LABEL(); | loop = LABEL(); |
2800 | 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)); |
2801 | leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
2802 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); |
2803 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); |
2804 | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); |
2805 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); |
2806 | ||
2807 | JUMPHERE(leave); | JUMPHERE(quit); |
2808 | JUMPHERE(firstchar); | JUMPHERE(firstchar); |
2809 | JUMPHERE(lastchar); | JUMPHERE(lastchar); |
2810 | ||
# | Line 2228 set_jumps(newline, loop); | Line 2828 set_jumps(newline, loop); |
2828 | ||
2829 | if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) | if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) |
2830 | { | { |
2831 | leave = JUMP(SLJIT_JUMP); | quit = JUMP(SLJIT_JUMP); |
2832 | JUMPHERE(foundcr); | JUMPHERE(foundcr); |
2833 | notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
2834 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
# | Line 2239 if (common->nltype == NLTYPE_ANY || comm | Line 2839 if (common->nltype == NLTYPE_ANY || comm |
2839 | #endif | #endif |
2840 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
2841 | JUMPHERE(notfoundnl); | JUMPHERE(notfoundnl); |
2842 | JUMPHERE(leave); | JUMPHERE(quit); |
2843 | } | } |
2844 | JUMPHERE(lastchar); | JUMPHERE(lastchar); |
2845 | JUMPHERE(firstchar); | JUMPHERE(firstchar); |
2846 | ||
2847 | if (firstline) | if (firstline) |
2848 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); |
2849 | } | } |
2850 | ||
2851 | static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline) | static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline) |
2852 | { | { |
2853 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2854 | struct sljit_label *start; | struct sljit_label *start; |
2855 | struct sljit_jump *leave; | struct sljit_jump *quit; |
2856 | struct sljit_jump *found; | struct sljit_jump *found; |
2857 | #ifndef COMPILE_PCRE8 | #ifndef COMPILE_PCRE8 |
2858 | struct sljit_jump *jump; | struct sljit_jump *jump; |
# | Line 2260 struct sljit_jump *jump; | Line 2860 struct sljit_jump *jump; |
2860 | ||
2861 | if (firstline) | if (firstline) |
2862 | { | { |
2863 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); | SLJIT_ASSERT(common->first_line_end != 0); |
2864 | OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0); | |
2865 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); |
2866 | } | } |
2867 | ||
2868 | start = LABEL(); | start = LABEL(); |
2869 | leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
2870 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
2871 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
2872 | if (common->utf) | if (common->utf) |
# | Line 2309 if (common->utf) | Line 2910 if (common->utf) |
2910 | #endif | #endif |
2911 | JUMPTO(SLJIT_JUMP, start); | JUMPTO(SLJIT_JUMP, start); |
2912 | JUMPHERE(found); | JUMPHERE(found); |
2913 | JUMPHERE(leave); | JUMPHERE(quit); |
2914 | ||
2915 | if (firstline) | if (firstline) |
2916 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); | OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0); |
2917 | } | } |
2918 | ||
2919 | static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar) | static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar) |
# | Line 2384 DEFINE_COMPILER; | Line 2985 DEFINE_COMPILER; |
2985 | struct sljit_jump *jump; | struct sljit_jump *jump; |
2986 | struct sljit_label *mainloop; | struct sljit_label *mainloop; |
2987 | ||
2988 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
2989 | OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0); | OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0); |
2990 | GET_LOCAL_BASE(TMP3, 0, 0); | |
2991 | ||
2992 | /* Drop frames until we reach STACK_TOP. */ | /* Drop frames until we reach STACK_TOP. */ |
2993 | mainloop = LABEL(); | mainloop = LABEL(); |
2994 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); |
2995 | 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); |
2996 | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_LOCALS_REG, 0); | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); |
2997 | 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)); |
2998 | 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)); |
2999 | 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 2437 struct sljit_jump *jump; | Line 3039 struct sljit_jump *jump; |
3039 | ||
3040 | SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); | SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); |
3041 | ||
3042 | 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); |
3043 | /* Get type of the previous char, and put it to LOCALS1. */ | /* Get type of the previous char, and put it to LOCALS1. */ |
3044 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
3045 | 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)); |
# | Line 2535 OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSE | Line 3137 OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSE |
3137 | sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
3138 | } | } |
3139 | ||
3140 | /* | |
3141 | range format: | |
3142 | ||
3143 | ranges[0] = length of the range (max MAX_RANGE_SIZE, -1 means invalid range). | |
3144 | ranges[1] = first bit (0 or 1) | |
3145 | ranges[2-length] = position of the bit change (when the current bit is not equal to the previous) | |
3146 | */ | |
3147 | ||
3148 | static BOOL check_ranges(compiler_common *common, int *ranges, jump_list **backtracks, BOOL readch) | |
3149 | { | |
3150 | DEFINE_COMPILER; | |
3151 | struct sljit_jump *jump; | |
3152 | ||
3153 | if (ranges[0] < 0) | |
3154 | return FALSE; | |
3155 | ||
3156 | switch(ranges[0]) | |
3157 | { | |
3158 | case 1: | |
3159 | if (readch) | |
3160 | read_char(common); | |
3161 | add_jump(compiler, backtracks, CMP(ranges[1] == 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2])); | |
3162 | return TRUE; | |
3163 | ||
3164 | case 2: | |
3165 | if (readch) | |
3166 | read_char(common); | |
3167 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]); | |
3168 | add_jump(compiler, backtracks, CMP(ranges[1] != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2])); | |
3169 | return TRUE; | |
3170 | ||
3171 | case 4: | |
3172 | if (ranges[2] + 1 == ranges[3] && ranges[4] + 1 == ranges[5]) | |
3173 | { | |
3174 | if (readch) | |
3175 | read_char(common); | |
3176 | if (ranges[1] != 0) | |
3177 | { | |
3178 | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2])); | |
3179 | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[4])); | |
3180 | } | |
3181 | else | |
3182 | { | |
3183 | jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]); | |
3184 | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[4])); | |
3185 | JUMPHERE(jump); | |
3186 | } | |
3187 | return TRUE; | |
3188 | } | |
3189 | if ((ranges[3] - ranges[2]) == (ranges[5] - ranges[4]) && ispowerof2(ranges[4] - ranges[2])) | |
3190 | { | |
3191 | if (readch) | |
3192 | read_char(common); | |
3193 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[4] - ranges[2]); | |
3194 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[4]); | |
3195 | add_jump(compiler, backtracks, CMP(ranges[1] != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[5] - ranges[4])); | |
3196 | return TRUE; | |
3197 | } | |
3198 | return FALSE; | |
3199 | ||
3200 | default: | |
3201 | return FALSE; | |
3202 | } | |
3203 | } | |
3204 | ||
3205 | static void get_ctype_ranges(compiler_common *common, int flag, int *ranges) | |
3206 | { | |
3207 | int i, bit, length; | |
3208 | const pcre_uint8 *ctypes = (const pcre_uint8*)common->ctypes; | |
3209 | ||
3210 | bit = ctypes[0] & flag; | |
3211 | ranges[0] = -1; | |
3212 | ranges[1] = bit != 0 ? 1 : 0; | |
3213 | length = 0; | |
3214 | ||
3215 | for (i = 1; i < 256; i++) | |
3216 | if ((ctypes[i] & flag) != bit) | |
3217 | { | |
3218 | if (length >= MAX_RANGE_SIZE) | |
3219 | return; | |
3220 | ranges[2 + length] = i; | |
3221 | length++; | |
3222 | bit ^= flag; | |
3223 | } | |
3224 | ||
3225 | if (bit != 0) | |
3226 | { | |
3227 | if (length >= MAX_RANGE_SIZE) | |
3228 | return; | |
3229 | ranges[2 + length] = 256; | |
3230 | length++; | |
3231 | } | |
3232 | ranges[0] = length; | |
3233 | } | |
3234 | ||
3235 | static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, jump_list **backtracks) | |
3236 | { | |
3237 | int ranges[2 + MAX_RANGE_SIZE]; | |
3238 | pcre_uint8 bit, cbit, all; | |
3239 | int i, byte, length = 0; | |
3240 | ||
3241 | bit = bits[0] & 0x1; | |
3242 | ranges[1] = bit; | |
3243 | /* Can be 0 or 255. */ | |
3244 | all = -bit; | |
3245 | ||
3246 | for (i = 0; i < 256; ) | |
3247 | { | |
3248 | byte = i >> 3; | |
3249 | if ((i & 0x7) == 0 && bits[byte] == all) | |
3250 | i += 8; | |
3251 | else | |
3252 | { | |
3253 | cbit = (bits[byte] >> (i & 0x7)) & 0x1; | |
3254 | if (cbit != bit) | |
3255 | { | |
3256 | if (length >= MAX_RANGE_SIZE) | |
3257 | return FALSE; | |
3258 | ranges[2 + length] = i; | |
3259 | length++; | |
3260 | bit = cbit; | |
3261 | all = -cbit; | |
3262 | } | |
3263 | i++; | |
3264 | } | |
3265 | } | |
3266 | ||
3267 | if (((bit == 0) && nclass) || ((bit == 1) && !nclass)) | |
3268 | { | |
3269 | if (length >= MAX_RANGE_SIZE) | |
3270 | return FALSE; | |
3271 | ranges[2 + length] = 256; | |
3272 | length++; | |
3273 | } | |
3274 | ranges[0] = length; | |
3275 | ||
3276 | return check_ranges(common, ranges, backtracks, FALSE); | |
3277 | } | |
3278 | ||
3279 | static void check_anynewline(compiler_common *common) | static void check_anynewline(compiler_common *common) |
3280 | { | { |
3281 | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ |
3282 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3283 | ||
3284 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
3285 | ||
3286 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); |
3287 | 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 2567 static void check_hspace(compiler_common | Line 3308 static void check_hspace(compiler_common |
3308 | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ |
3309 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3310 | ||
3311 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
3312 | ||
3313 | 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); |
3314 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
# | Line 2606 static void check_vspace(compiler_common | Line 3347 static void check_vspace(compiler_common |
3347 | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ | /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ |
3348 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3349 | ||
3350 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
3351 | ||
3352 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); |
3353 | 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 2638 DEFINE_COMPILER; | Line 3379 DEFINE_COMPILER; |
3379 | struct sljit_jump *jump; | struct sljit_jump *jump; |
3380 | struct sljit_label *label; | struct sljit_label *label; |
3381 | ||
3382 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
3383 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
3384 | OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0); | OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0); |
3385 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0); |
# | Line 2667 DEFINE_COMPILER; | Line 3408 DEFINE_COMPILER; |
3408 | struct sljit_jump *jump; | struct sljit_jump *jump; |
3409 | struct sljit_label *label; | struct sljit_label *label; |
3410 | ||
3411 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
3412 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
3413 | ||
3414 | OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); | OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); |
# | Line 2731 return src2; | Line 3472 return src2; |
3472 | #endif /* SUPPORT_UTF && SUPPORT_UCP */ | #endif /* SUPPORT_UTF && SUPPORT_UCP */ |
3473 | ||
3474 | 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, |
3475 | compare_context* context, jump_list **fallbacks) | compare_context* context, jump_list **backtracks) |
3476 | { | { |
3477 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3478 | unsigned int othercasebit = 0; | unsigned int othercasebit = 0; |
# | Line 2832 do | Line 3573 do |
3573 | case 4 / sizeof(pcre_uchar): | case 4 / sizeof(pcre_uchar): |
3574 | if (context->oc.asint != 0) | if (context->oc.asint != 0) |
3575 | 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); |
3576 | 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)); |
3577 | break; | break; |
3578 | ||
3579 | case 2 / sizeof(pcre_uchar): | case 2 / sizeof(pcre_uchar): |
3580 | if (context->oc.asushort != 0) | if (context->oc.asushort != 0) |
3581 | 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); |
3582 | 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)); |
3583 | break; | break; |
3584 | ||
3585 | #ifdef COMPILE_PCRE8 | #ifdef COMPILE_PCRE8 |
3586 | case 1: | case 1: |
3587 | if (context->oc.asbyte != 0) | if (context->oc.asbyte != 0) |
3588 | 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); |
3589 | 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)); |
3590 | break; | break; |
3591 | #endif | #endif |
3592 | ||
# | Line 2871 do | Line 3612 do |
3612 | if (othercasebit != 0 && othercasechar == cc) | if (othercasebit != 0 && othercasechar == cc) |
3613 | { | { |
3614 | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); |
3615 | 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)); |
3616 | } | } |
3617 | else | else |
3618 | 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)); |
3619 | ||
3620 | #endif | #endif |
3621 | ||
# | Line 2910 return cc; | Line 3651 return cc; |
3651 | } \ | } \ |
3652 | charoffset = (value); | charoffset = (value); |
3653 | ||
3654 | static void compile_xclass_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks) | static void compile_xclass_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks) |
3655 | { | { |
3656 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3657 | jump_list *found = NULL; | jump_list *found = NULL; |
3658 | jump_list **list = (*cc & XCL_NOT) == 0 ? &found : fallbacks; | jump_list **list = (*cc & XCL_NOT) == 0 ? &found : backtracks; |
3659 | unsigned int c; | unsigned int c; |
3660 | int compares; | int compares; |
3661 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
# | Line 2928 unsigned int typeoffset; | Line 3669 unsigned int typeoffset; |
3669 | int invertcmp, numberofcmps; | int invertcmp, numberofcmps; |
3670 | unsigned int charoffset; | unsigned int charoffset; |
3671 | ||
3672 | /* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */ | /* Although SUPPORT_UTF must be defined, we are |
3673 | fallback_at_str_end(common, fallbacks); | not necessary in utf mode even in 8 bit mode. */ |
3674 | detect_partial_match(common, backtracks); | |
3675 | read_char(common); | read_char(common); |
3676 | ||
3677 | if ((*cc++ & XCL_MAP) != 0) | if ((*cc++ & XCL_MAP) != 0) |
# | Line 2942 if ((*cc++ & XCL_MAP) != 0) | Line 3684 if ((*cc++ & XCL_MAP) != 0) |
3684 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); |
3685 | #endif | #endif |
3686 | ||
3687 | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); | if (!check_class_ranges(common, (const pcre_uint8 *)cc, TRUE, list)) |
3688 | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); | { |
3689 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); |
3690 | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); |
3691 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); |
3692 | add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO)); | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); |
3693 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); | |
3694 | add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO)); | |
3695 | } | |
3696 | ||
3697 | #ifndef COMPILE_PCRE8 | #ifndef COMPILE_PCRE8 |
3698 | JUMPHERE(jump); | JUMPHERE(jump); |
# | Line 3080 typeoffset = 0; | Line 3825 typeoffset = 0; |
3825 | while (*cc != XCL_END) | while (*cc != XCL_END) |
3826 | { | { |
3827 | compares--; | compares--; |
3828 | invertcmp = (compares == 0 && list != fallbacks); | invertcmp = (compares == 0 && list != backtracks); |
3829 | jump = NULL; | jump = NULL; |
3830 | ||
3831 | if (*cc == XCL_SINGLE) | if (*cc == XCL_SINGLE) |
# | Line 3162 while (*cc != XCL_END) | Line 3907 while (*cc != XCL_END) |
3907 | switch(*cc) | switch(*cc) |
3908 | { | { |
3909 | case PT_ANY: | case PT_ANY: |
3910 | if (list != fallbacks) | if (list != backtracks) |
3911 | { | { |
3912 | 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)) |
3913 | continue; | continue; |
# | Line 3235 while (*cc != XCL_END) | Line 3980 while (*cc != XCL_END) |
3980 | #endif | #endif |
3981 | ||
3982 | if (jump != NULL) | if (jump != NULL) |
3983 | add_jump(compiler, compares > 0 ? list : fallbacks, jump); | add_jump(compiler, compares > 0 ? list : backtracks, jump); |
3984 | } | } |
3985 | ||
3986 | if (found != NULL) | if (found != NULL) |
# | Line 3247 if (found != NULL) | Line 3992 if (found != NULL) |
3992 | ||
3993 | #endif | #endif |
3994 | ||
3995 | static pcre_uchar *compile_char1_hotpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **fallbacks) | static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks) |
3996 | { | { |
3997 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3998 | int length; | int length; |
# | Line 3266 switch(type) | Line 4011 switch(type) |
4011 | case OP_SOD: | case OP_SOD: |
4012 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
4013 | 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)); |
4014 | 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)); |
4015 | return cc; | return cc; |
4016 | ||
4017 | case OP_SOM: | case OP_SOM: |
4018 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
4019 | 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)); |
4020 | 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)); |
4021 | return cc; | return cc; |
4022 | ||
4023 | case OP_NOT_WORD_BOUNDARY: | case OP_NOT_WORD_BOUNDARY: |
4024 | case OP_WORD_BOUNDARY: | case OP_WORD_BOUNDARY: |
4025 | add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL)); |
4026 | 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)); |
4027 | return cc; | return cc; |
4028 | ||
4029 | case OP_NOT_DIGIT: | case OP_NOT_DIGIT: |
4030 | case OP_DIGIT: | case OP_DIGIT: |
4031 | fallback_at_str_end(common, fallbacks); | /* Digits are usually 0-9, so it is worth to optimize them. */ |
4032 | read_char8_type(common); | if (common->digits[0] == -2) |
4033 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); | get_ctype_ranges(common, ctype_digit, common->digits); |
4034 | add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); | detect_partial_match(common, backtracks); |
4035 | /* Flip the starting bit in the negative case. */ | |
4036 | if (type == OP_NOT_DIGIT) | |
4037 | common->digits[1] ^= 1; | |
4038 | if (!check_ranges(common, common->digits, backtracks, TRUE)) | |
4039 | { | |
4040 | read_char8_type(common); | |
4041 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); | |
4042 | add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); | |
4043 | } | |
4044 | if (type == OP_NOT_DIGIT) | |
4045 | common->digits[1] ^= 1; | |
4046 | return cc; | return cc; |
4047 | ||
4048 | case OP_NOT_WHITESPACE: | case OP_NOT_WHITESPACE: |
4049 | case OP_WHITESPACE: | case OP_WHITESPACE: |
4050 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4051 | read_char8_type(common); | read_char8_type(common); |
4052 | 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); |
4053 | 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)); |
4054 | return cc; | return cc; |
4055 | ||
4056 | case OP_NOT_WORDCHAR: | case OP_NOT_WORDCHAR: |
4057 | case OP_WORDCHAR: | case OP_WORDCHAR: |
4058 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4059 | read_char8_type(common); | read_char8_type(common); |
4060 | 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); |
4061 | 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)); |
4062 | return cc; | return cc; |
4063 | ||
4064 | case OP_ANY: | case OP_ANY: |
4065 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4066 | read_char(common); | read_char(common); |
4067 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
4068 | { | { |
# | Line 3317 switch(type) | Line 4073 switch(type) |
4073 | jump[1] = check_str_end(common); | jump[1] = check_str_end(common); |
4074 | ||
4075 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
4076 | 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)); |
4077 | if (jump[1] != NULL) | if (jump[1] != NULL) |
4078 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
4079 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
4080 | } | } |
4081 | else | else |
4082 | check_newlinechar(common, common->nltype, fallbacks, TRUE); | check_newlinechar(common, common->nltype, backtracks, TRUE); |
4083 | return cc; | return cc; |
4084 | ||
4085 | case OP_ALLANY: | case OP_ALLANY: |
4086 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4087 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
4088 | if (common->utf) | if (common->utf) |
4089 | { | { |
# | Line 3355 switch(type) | Line 4111 switch(type) |
4111 | return cc; | return cc; |
4112 | ||
4113 | case OP_ANYBYTE: | case OP_ANYBYTE: |
4114 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4115 | 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)); |
4116 | return cc; | return cc; |
4117 | ||
# | Line 3368 switch(type) | Line 4124 switch(type) |
4124 | propdata[2] = cc[0]; | propdata[2] = cc[0]; |
4125 | propdata[3] = cc[1]; | propdata[3] = cc[1]; |
4126 | propdata[4] = XCL_END; | propdata[4] = XCL_END; |
4127 | compile_xclass_hotpath(common, propdata, fallbacks); | compile_xclass_matchingpath(common, propdata, backtracks); |
4128 | return cc + 2; | return cc + 2; |
4129 | #endif | #endif |
4130 | #endif | #endif |
4131 | ||
4132 | case OP_ANYNL: | case OP_ANYNL: |
4133 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4134 | read_char(common); | read_char(common); |
4135 | 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); |
4136 | /* We don't need to handle soft partial matching case. */ | /* We don't need to handle soft partial matching case. */ |
# | Line 3387 switch(type) | Line 4143 switch(type) |
4143 | 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)); |
4144 | jump[3] = JUMP(SLJIT_JUMP); | jump[3] = JUMP(SLJIT_JUMP); |
4145 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
4146 | check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE); | check_newlinechar(common, common->bsr_nltype, backtracks, FALSE); |
4147 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
4148 | JUMPHERE(jump[2]); | JUMPHERE(jump[2]); |
4149 | JUMPHERE(jump[3]); | JUMPHERE(jump[3]); |
# | Line 3395 switch(type) | Line 4151 switch(type) |
4151 | ||
4152 | case OP_NOT_HSPACE: | case OP_NOT_HSPACE: |
4153 | case OP_HSPACE: | case OP_HSPACE: |
4154 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4155 | read_char(common); | read_char(common); |
4156 | add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); |
4157 | 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)); |
4158 | return cc; | return cc; |
4159 | ||
4160 | case OP_NOT_VSPACE: | case OP_NOT_VSPACE: |
4161 | case OP_VSPACE: | case OP_VSPACE: |
4162 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4163 | read_char(common); | read_char(common); |
4164 | add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); |
4165 | 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)); |
4166 | return cc; | return cc; |
4167 | ||
4168 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
4169 | case OP_EXTUNI: | case OP_EXTUNI: |
4170 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4171 | read_char(common); | read_char(common); |
4172 | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); |
4173 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); |
4174 | 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)); |
4175 | ||
4176 | label = LABEL(); | label = LABEL(); |
4177 | 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 3445 switch(type) | Line 4201 switch(type) |
4201 | 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)); |
4202 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
4203 | if (common->mode == JIT_COMPILE) | if (common->mode == JIT_COMPILE) |
4204 | 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)); |
4205 | else | else |
4206 | { | { |
4207 | jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0); | jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0); |
# | Line 3453 switch(type) | Line 4209 switch(type) |
4209 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS); |
4210 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); |
4211 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_NOT_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_NOT_EQUAL); |
4212 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_NOT_EQUAL)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_NOT_EQUAL)); |
4213 | check_partial(common, TRUE); | check_partial(common, TRUE); |
4214 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
4215 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
4216 | } | } |
4217 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
4218 | 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)); |
4219 | 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)); |
4220 | } | } |
4221 | else if (common->nltype == NLTYPE_FIXED) | else if (common->nltype == NLTYPE_FIXED) |
4222 | { | { |
4223 | 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)); |
4224 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
4225 | 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)); |
4226 | 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)); |
4227 | } | } |
4228 | else | else |
4229 | { | { |
# | Line 3476 switch(type) | Line 4232 switch(type) |
4232 | 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)); |
4233 | 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); |
4234 | jump[2] = JUMP(SLJIT_C_GREATER); | jump[2] = JUMP(SLJIT_C_GREATER); |
4235 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_LESS)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_LESS)); |
4236 | /* Equal. */ | /* Equal. */ |
4237 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
4238 | jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); | jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); |
4239 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
4240 | ||
4241 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
4242 | if (common->nltype == NLTYPE_ANYCRLF) | if (common->nltype == NLTYPE_ANYCRLF) |
4243 | { | { |
4244 | 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)); |
4245 | 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)); |
4246 | 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)); |
4247 | } | } |
4248 | else | else |
4249 | { | { |
4250 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0); |
4251 | read_char(common); | read_char(common); |
4252 | 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)); |
4253 | add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); |
4254 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); |
4255 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); |
4256 | } | } |
4257 | JUMPHERE(jump[2]); | JUMPHERE(jump[2]); |
# | Line 3506 switch(type) | Line 4262 switch(type) |
4262 | return cc; | return cc; |
4263 | ||
4264 | case OP_EOD: | case OP_EOD: |
4265 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); |
4266 | check_partial(common, FALSE); | check_partial(common, FALSE); |
4267 | return cc; | return cc; |
4268 | ||
4269 | case OP_CIRC: | case OP_CIRC: |
4270 | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); |
4271 | 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)); |
4272 | 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)); |
4273 | 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)); |
4274 | 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)); |
4275 | return cc; | return cc; |
4276 | ||
4277 | case OP_CIRCM: | case OP_CIRCM: |
# | Line 3523 switch(type) | Line 4279 switch(type) |
4279 | 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)); |
4280 | jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0); | jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0); |
4281 | 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)); |
4282 | 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)); |
4283 | jump[0] = JUMP(SLJIT_JUMP); | jump[0] = JUMP(SLJIT_JUMP); |
4284 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
4285 | ||
4286 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
4287 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
4288 | { | { |
4289 | 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)); |
4290 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0)); |
4291 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); |
4292 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); |
4293 | 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)); |
4294 | 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)); |
4295 | } | } |
4296 | else | else |
4297 | { | { |
4298 | skip_char_back(common); | skip_char_back(common); |
4299 | read_char(common); | read_char(common); |
4300 | check_newlinechar(common, common->nltype, fallbacks, FALSE); | check_newlinechar(common, common->nltype, backtracks, FALSE); |
4301 | } | } |
4302 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
4303 | return cc; | return cc; |
# | Line 3549 switch(type) | Line 4305 switch(type) |
4305 | case OP_DOLL: | case OP_DOLL: |
4306 | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); |
4307 | 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)); |
4308 | 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)); |
4309 | ||
4310 | if (!common->endonly) | if (!common->endonly) |
4311 | compile_char1_hotpath(common, OP_EODN, cc, fallbacks); | compile_char1_matchingpath(common, OP_EODN, cc, backtracks); |
4312 | else | else |
4313 | { | { |
4314 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); |
4315 | check_partial(common, FALSE); | check_partial(common, FALSE); |
4316 | } | } |
4317 | return cc; | return cc; |
# | Line 3564 switch(type) | Line 4320 switch(type) |
4320 | jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); |
4321 | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); |
4322 | 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)); |
4323 | 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)); |
4324 | check_partial(common, FALSE); | check_partial(common, FALSE); |
4325 | jump[0] = JUMP(SLJIT_JUMP); | jump[0] = JUMP(SLJIT_JUMP); |
4326 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
# | Line 3574 switch(type) | Line 4330 switch(type) |
4330 | 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)); |
4331 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
4332 | if (common->mode == JIT_COMPILE) | if (common->mode == JIT_COMPILE) |
4333 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0)); |
4334 | else | else |
4335 | { | { |
4336 | jump[1] = CMP(SLJIT_C_LESS_EQUAL, TMP2, 0, STR_END, 0); | jump[1] = CMP(SLJIT_C_LESS_EQUAL, TMP2, 0, STR_END, 0); |
4337 | /* STR_PTR = STR_END - IN_UCHARS(1) */ | /* STR_PTR = STR_END - IN_UCHARS(1) */ |
4338 | 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)); |
4339 | check_partial(common, TRUE); | check_partial(common, TRUE); |
4340 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
4341 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
4342 | } | } |
4343 | ||
4344 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
4345 | 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)); |
4346 | 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)); |
4347 | } | } |
4348 | else | else |
4349 | { | { |
4350 | peek_char(common); | peek_char(common); |
4351 | check_newlinechar(common, common->nltype, fallbacks, FALSE); | check_newlinechar(common, common->nltype, backtracks, FALSE); |
4352 | } | } |
4353 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
4354 | return cc; | return cc; |
# | Line 3606 switch(type) | Line 4362 switch(type) |
4362 | if (common->mode == JIT_COMPILE && (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)) |
4363 | { | { |
4364 | 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)); |
4365 | 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)); |
4366 | ||
4367 | context.length = IN_UCHARS(length); | context.length = IN_UCHARS(length); |
4368 | context.sourcereg = -1; | context.sourcereg = -1; |
4369 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED |
4370 | context.ucharptr = 0; | context.ucharptr = 0; |
4371 | #endif | #endif |
4372 | return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks); | return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks); |
4373 | } | } |
4374 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4375 | read_char(common); | read_char(common); |
4376 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
4377 | if (common->utf) | if (common->utf) |
# | Line 3627 switch(type) | Line 4383 switch(type) |
4383 | c = *cc; | c = *cc; |
4384 | if (type == OP_CHAR || !char_has_othercase(common, cc)) | if (type == OP_CHAR || !char_has_othercase(common, cc)) |
4385 | { | { |
4386 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); |
4387 | return cc + length; | return cc + length; |
4388 | } | } |
4389 | oc = char_othercase(common, c); | oc = char_othercase(common, c); |
# | Line 3635 switch(type) | Line 4391 switch(type) |
4391 | if (ispowerof2(bit)) | if (ispowerof2(bit)) |
4392 | { | { |
4393 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); |
4394 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); |
4395 | return cc + length; | return cc + length; |
4396 | } | } |
4397 | 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); |
4398 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
4399 | 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, oc); |
4400 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
4401 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); |
4402 | return cc + length; | return cc + length; |
4403 | ||
4404 | case OP_NOT: | case OP_NOT: |
4405 | case OP_NOTI: | case OP_NOTI: |
4406 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4407 | length = 1; | length = 1; |
4408 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
4409 | if (common->utf) | if (common->utf) |
# | Line 3658 switch(type) | Line 4414 switch(type) |
4414 | { | { |
4415 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
4416 | if (type == OP_NOT || !char_has_othercase(common, cc)) | if (type == OP_NOT || !char_has_othercase(common, cc)) |
4417 | 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)); |
4418 | else | else |
4419 | { | { |
4420 | /* 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. */ |
4421 | OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); | OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); |
4422 | 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)); |
4423 | } | } |
4424 | /* Skip the variable-length character. */ | /* Skip the variable-length character. */ |
4425 | 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 3688 switch(type) | Line 4444 switch(type) |
4444 | } | } |
4445 | ||
4446 | if (type == OP_NOT || !char_has_othercase(common, cc)) | if (type == OP_NOT || !char_has_othercase(common, cc)) |
4447 | 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)); |
4448 | else | else |
4449 | { | { |
4450 | oc = char_othercase(common, c); | oc = char_othercase(common, c); |
# | Line 3696 switch(type) | Line 4452 switch(type) |
4452 | if (ispowerof2(bit)) | if (ispowerof2(bit)) |
4453 | { | { |
4454 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); |
4455 | 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)); |
4456 | } | } |
4457 | else | else |
4458 | { | { |
4459 | 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)); |
4460 | 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)); |
4461 | } | } |
4462 | } | } |
4463 | return cc + length; | return cc + length; |
4464 | ||
4465 | case OP_CLASS: | case OP_CLASS: |
4466 | case OP_NCLASS: | case OP_NCLASS: |
4467 | fallback_at_str_end(common, fallbacks); | detect_partial_match(common, backtracks); |
4468 | read_char(common); | read_char(common); |
4469 | if (check_class_ranges(common, (const pcre_uint8 *)cc, type == OP_NCLASS, backtracks)) | |
4470 | return cc + 32 / sizeof(pcre_uchar); | |
4471 | ||
4472 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
4473 | jump[0] = NULL; | jump[0] = NULL; |
4474 | #ifdef COMPILE_PCRE8 | #ifdef COMPILE_PCRE8 |
# | Line 3721 switch(type) | Line 4480 switch(type) |
4480 | jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); |
4481 | if (type == OP_CLASS) | if (type == OP_CLASS) |
4482 | { | { |
4483 | add_jump(compiler, fallbacks, jump[0]); | add_jump(compiler, backtracks, jump[0]); |
4484 | jump[0] = NULL; | jump[0] = NULL; |
4485 | } | } |
4486 | } | } |
# | Line 3731 switch(type) | Line 4490 switch(type) |
4490 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); |
4491 | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); |
4492 | 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); |
4493 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); |
4494 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
4495 | if (jump[0] != NULL) | if (jump[0] != NULL) |
4496 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
# | Line 3740 switch(type) | Line 4499 switch(type) |
4499 | ||
4500 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 |
4501 | case OP_XCLASS: | case OP_XCLASS: |
4502 | compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks); | compile_xclass_matchingpath(common, cc + LINK_SIZE, backtracks); |
4503 | return cc + GET(cc, 0) - 1; | return cc + GET(cc, 0) - 1; |
4504 | #endif | #endif |
4505 | ||
4506 | case OP_REVERSE: | case OP_REVERSE: |
4507 | length = GET(cc, 0); | length = GET(cc, 0); |
4508 | SLJIT_ASSERT(length > 0); | if (length == 0) |
4509 | return cc + LINK_SIZE; | |
4510 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
4511 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
4512 | if (common->utf) | if (common->utf) |
# | Line 3754 switch(type) | Line 4514 switch(type) |
4514 | 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)); |
4515 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); |
4516 | label = LABEL(); | label = LABEL(); |
4517 | 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)); |
4518 | skip_char_back(common); | skip_char_back(common); |
4519 | 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); |
4520 | JUMPTO(SLJIT_C_NOT_ZERO, label); | JUMPTO(SLJIT_C_NOT_ZERO, label); |
# | Line 3764 switch(type) | Line 4524 switch(type) |
4524 | { | { |
4525 | 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)); |
4526 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); |
4527 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); |
4528 | } | } |
4529 | check_start_used_ptr(common); | check_start_used_ptr(common); |
4530 | return cc + LINK_SIZE; | return cc + LINK_SIZE; |
# | Line 3773 SLJIT_ASSERT_STOP(); | Line 4533 SLJIT_ASSERT_STOP(); |
4533 | return cc; | return cc; |
4534 | } | } |
4535 | ||
4536 | 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_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **backtracks) |
4537 | { | { |
4538 | /* This function consumes at least one input character. */ | /* This function consumes at least one input character. */ |
4539 | /* 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 3825 if (context.length > 0) | Line 4585 if (context.length > 0) |
4585 | { | { |
4586 | /* We have a fixed-length byte sequence. */ | /* We have a fixed-length byte sequence. */ |
4587 | 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); |
4588 | 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)); |
4589 | ||
4590 | context.sourcereg = -1; | context.sourcereg = -1; |
4591 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED |
4592 | context.ucharptr = 0; | context.ucharptr = 0; |
4593 | #endif | #endif |
4594 | 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); |
4595 | return cc; | return cc; |
4596 | } | } |
4597 | ||
4598 | /* A non-fixed length character will be checked if length == 0. */ | /* A non-fixed length character will be checked if length == 0. */ |
4599 | return compile_char1_hotpath(common, *cc, cc + 1, fallbacks); | return compile_char1_matchingpath(common, *cc, cc + 1, backtracks); |
4600 | } | } |
4601 | ||
4602 | 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) |
4603 | { | { |
4604 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4605 | int offset = GET2(cc, 1) << 1; | int offset = GET2(cc, 1) << 1; |
# | Line 3847 int offset = GET2(cc, 1) << 1; | Line 4607 int offset = GET2(cc, 1) << 1; |
4607 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
4608 | if (!common->jscript_compat) | if (!common->jscript_compat) |
4609 | { | { |
4610 | if (fallbacks == NULL) | if (backtracks == NULL) |
4611 | { | { |
4612 | /* OVECTOR(1) contains the "string begin - 1" constant. */ | /* OVECTOR(1) contains the "string begin - 1" constant. */ |
4613 | 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)); |
# | Line 3856 if (!common->jscript_compat) | Line 4616 if (!common->jscript_compat) |
4616 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
4617 | return JUMP(SLJIT_C_NOT_ZERO); | return JUMP(SLJIT_C_NOT_ZERO); |
4618 | } | } |
4619 | 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))); |
4620 | } | } |
4621 | 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)); |
4622 | } | } |
4623 | ||
4624 | /* Forward definitions. */ | /* Forward definitions. */ |
4625 | static void compile_hotpath(compiler_common *, pcre_uchar *, pcre_uchar *, fallback_common *); | static void compile_matchingpath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *); |
4626 | static void compile_fallbackpath(compiler_common *, struct fallback_common *); | static void compile_backtrackingpath(compiler_common *, struct backtrack_common *); |
4627 | ||
4628 | #define PUSH_FALLBACK(size, ccstart, error) \ | #define PUSH_BACKTRACK(size, ccstart, error) \ |
4629 | do \ | do \ |
4630 | { \ | { \ |
4631 | fallback = sljit_alloc_memory(compiler, (size)); \ | backtrack = sljit_alloc_memory(compiler, (size)); \ |
4632 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ |
4633 | return error; \ | return error; \ |
4634 | memset(fallback, 0, size); \ | memset(backtrack, 0, size); \ |
4635 | fallback->prev = parent->top; \ | backtrack->prev = parent->top; \ |
4636 | fallback->cc = (ccstart); \ | backtrack->cc = (ccstart); \ |
4637 | parent->top = fallback; \ | parent->top = backtrack; \ |
4638 | } \ | } \ |
4639 | while (0) | while (0) |
4640 | ||
4641 | #define PUSH_FALLBACK_NOVALUE(size, ccstart) \ | #define PUSH_BACKTRACK_NOVALUE(size, ccstart) \ |
4642 | do \ | do \ |
4643 | { \ | { \ |
4644 | fallback = sljit_alloc_memory(compiler, (size)); \ | backtrack = sljit_alloc_memory(compiler, (size)); \ |
4645 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ |
4646 | return; \ | return; \ |
4647 | memset(fallback, 0, size); \ | memset(backtrack, 0, size); \ |
4648 | fallback->prev = parent->top; \ | backtrack->prev = parent->top; \ |
4649 | fallback->cc = (ccstart); \ | backtrack->cc = (ccstart); \ |
4650 | parent->top = fallback; \ | parent->top = backtrack; \ |
4651 | } \ | } \ |
4652 | while (0) | while (0) |
4653 | ||
4654 | #define FALLBACK_AS(type) ((type *)fallback) | #define BACKTRACK_AS(type) ((type *)backtrack) |
4655 | ||
4656 | static pcre_uchar *compile_ref_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail) | static pcre_uchar *compile_ref_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail) |
4657 | { | { |
4658 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4659 | int offset = GET2(cc, 1) << 1; | int offset = GET2(cc, 1) << 1; |
# | Line 3904 struct sljit_jump *nopartial; | Line 4664 struct sljit_jump *nopartial; |
4664 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
4665 | /* OVECTOR(1) contains the "string begin - 1" constant. */ | /* OVECTOR(1) contains the "string begin - 1" constant. */ |
4666 | if (withchecks && !common->jscript_compat) | if (withchecks && !common->jscript_compat) |
4667 | 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))); |
4668 | ||
4669 | #if defined SUPPORT_UTF && defined SUPPORT_UCP | #if defined SUPPORT_UTF && defined SUPPORT_UCP |
4670 | if (common->utf && *cc == OP_REFI) | if (common->utf && *cc == OP_REFI) |
# | Line 3921 if (common->utf && *cc == OP_REFI) | Line 4681 if (common->utf && *cc == OP_REFI) |
4681 | 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)); |
4682 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
4683 | if (common->mode == JIT_COMPILE) | if (common->mode == JIT_COMPILE) |
4684 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1)); | add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1)); |
4685 | else | else |
4686 | { | { |
4687 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); |
4688 | nopartial = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); | nopartial = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); |
4689 | check_partial(common, FALSE); | check_partial(common, FALSE); |
4690 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
4691 | JUMPHERE(nopartial); | JUMPHERE(nopartial); |
4692 | } | } |
4693 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); |
# | Line 3942 else | Line 4702 else |
4702 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
4703 | partial = CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0); | partial = CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0); |
4704 | if (common->mode == JIT_COMPILE) | if (common->mode == JIT_COMPILE) |
4705 | add_jump(compiler, fallbacks, partial); | add_jump(compiler, backtracks, partial); |
4706 | ||
4707 | 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)); |
4708 | 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)); |
4709 | ||
4710 | if (common->mode != JIT_COMPILE) | if (common->mode != JIT_COMPILE) |
4711 | { | { |
# | Line 3957 else | Line 4717 else |
4717 | partial = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0); | partial = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0); |
4718 | OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); | OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); |
4719 | 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)); |
4720 | 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)); |
4721 | JUMPHERE(partial); | JUMPHERE(partial); |
4722 | check_partial(common, FALSE); | check_partial(common, FALSE); |
4723 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
4724 | JUMPHERE(nopartial); | JUMPHERE(nopartial); |
4725 | } | } |
4726 | } | } |
# | Line 3968 else | Line 4728 else |
4728 | if (jump != NULL) | if (jump != NULL) |
4729 | { | { |
4730 | if (emptyfail) | if (emptyfail) |
4731 | add_jump(compiler, fallbacks, jump); | add_jump(compiler, backtracks, jump); |
4732 | else | else |
4733 | JUMPHERE(jump); | JUMPHERE(jump); |
4734 | } | } |
4735 | return cc + 1 + IMM2_SIZE; | return cc + 1 + IMM2_SIZE; |
4736 | } | } |
4737 | ||
4738 | 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_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
4739 | { | { |
4740 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4741 | fallback_common *fallback; | backtrack_common *backtrack; |
4742 | pcre_uchar type; | pcre_uchar type; |
4743 | struct sljit_label *label; | struct sljit_label *label; |
4744 | struct sljit_jump *zerolength; | struct sljit_jump *zerolength; |
# | Line 3987 pcre_uchar *ccbegin = cc; | Line 4747 pcre_uchar *ccbegin = cc; |
4747 | int min = 0, max = 0; | int min = 0, max = 0; |
4748 | BOOL minimize; | BOOL minimize; |
4749 | ||
4750 | PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL); |
4751 | ||
4752 | type = cc[1 + IMM2_SIZE]; | type = cc[1 + IMM2_SIZE]; |
4753 | minimize = (type & 0x1) != 0; | minimize = (type & 0x1) != 0; |
# | Line 4039 if (!minimize) | Line 4799 if (!minimize) |
4799 | { | { |
4800 | allocate_stack(common, 1); | allocate_stack(common, 1); |
4801 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
4802 | zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks); | zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks); |
4803 | } | } |
4804 | ||
4805 | if (min > 1 || max > 1) | if (min > 1 || max > 1) |
4806 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); |
4807 | ||
4808 | label = LABEL(); | label = LABEL(); |
4809 | compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, FALSE, FALSE); | compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE); |
4810 | ||
4811 | if (min > 1 || max > 1) | if (min > 1 || max > 1) |
4812 | { | { |
# | Line 4074 if (!minimize) | Line 4834 if (!minimize) |
4834 | } | } |
4835 | ||
4836 | JUMPHERE(zerolength); | JUMPHERE(zerolength); |
4837 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); |
4838 | ||
4839 | decrease_call_count(common); | decrease_call_count(common); |
4840 | return cc; | return cc; |
# | Line 4092 if (min == 0) | Line 4852 if (min == 0) |
4852 | jump = JUMP(SLJIT_JUMP); | jump = JUMP(SLJIT_JUMP); |
4853 | } | } |
4854 | else | else |
4855 | zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks); | zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks); |
4856 | ||
4857 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); |
4858 | if (max > 0) | if (max > 0) |
4859 | 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)); |
4860 | ||
4861 | compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, TRUE, TRUE); | compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE); |
4862 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
4863 | ||
4864 | if (min > 1) | if (min > 1) |
# | Line 4106 if (min > 1) | Line 4866 if (min > 1) |
4866 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
4867 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
4868 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); |
4869 | 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)->matchingpath); |
4870 | } | } |
4871 | else if (max > 0) | else if (max > 0) |
4872 | 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 4119 decrease_call_count(common); | Line 4879 decrease_call_count(common); |
4879 | return cc; | return cc; |
4880 | } | } |
4881 | ||
4882 | static SLJIT_INLINE pcre_uchar *compile_recurse_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) | static SLJIT_INLINE pcre_uchar *compile_recurse_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
4883 | { | { |
4884 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4885 | fallback_common *fallback; | backtrack_common *backtrack; |
4886 | recurse_entry *entry = common->entries; | recurse_entry *entry = common->entries; |
4887 | recurse_entry *prev = NULL; | recurse_entry *prev = NULL; |
4888 | int start = GET(cc, 1); | int start = GET(cc, 1); |
4889 | ||
4890 | PUSH_FALLBACK(sizeof(recurse_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL); |
4891 | while (entry != NULL) | while (entry != NULL) |
4892 | { | { |
4893 | if (entry->start == start) | if (entry->start == start) |
# | Line 4172 if (entry->entry == NULL) | Line 4932 if (entry->entry == NULL) |
4932 | else | else |
4933 | JUMPTO(SLJIT_FAST_CALL, entry->entry); | JUMPTO(SLJIT_FAST_CALL, entry->entry); |
4934 | /* Leave if the match is failed. */ | /* Leave if the match is failed. */ |
4935 | 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)); |
4936 | return cc + 1 + LINK_SIZE; | return cc + 1 + LINK_SIZE; |
4937 | } | } |
4938 | ||
4939 | static pcre_uchar *compile_assert_hotpath(compiler_common *common, pcre_uchar *cc, assert_fallback *fallback, BOOL conditional) | static pcre_uchar *compile_assert_matchingpath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional) |
4940 | { | { |
4941 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4942 | int framesize; | int framesize; |
4943 | int localptr; | int localptr; |
4944 | fallback_common altfallback; | backtrack_common altbacktrack; |
4945 | pcre_uchar *ccbegin; | pcre_uchar *ccbegin; |
4946 | pcre_uchar opcode; | pcre_uchar opcode; |
4947 | pcre_uchar bra = OP_BRA; | pcre_uchar bra = OP_BRA; |
4948 | jump_list *tmp = NULL; | jump_list *tmp = NULL; |
4949 | jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks; | jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks; |
4950 | jump_list **found; | jump_list **found; |
4951 | /* Saving previous accept variables. */ | /* Saving previous accept variables. */ |
4952 | struct sljit_label *save_leavelabel = common->leavelabel; | struct sljit_label *save_quitlabel = common->quitlabel; |
4953 | struct sljit_label *save_acceptlabel = common->acceptlabel; | struct sljit_label *save_acceptlabel = common->acceptlabel; |
4954 | jump_list *save_leave = common->leave; | jump_list *save_quit = common->quit; |
4955 | jump_list *save_accept = common->accept; | jump_list *save_accept = common->accept; |
4956 | struct sljit_jump *jump; | struct sljit_jump *jump; |
4957 | struct sljit_jump *brajump = NULL; | struct sljit_jump *brajump = NULL; |
# | Line 4205 if (*cc == OP_BRAZERO || *cc == OP_BRAMI | Line 4965 if (*cc == OP_BRAZERO || *cc == OP_BRAMI |
4965 | localptr = PRIV_DATA(cc); | localptr = PRIV_DATA(cc); |
4966 | SLJIT_ASSERT(localptr != 0); | SLJIT_ASSERT(localptr != 0); |
4967 | framesize = get_framesize(common, cc, FALSE); | framesize = get_framesize(common, cc, FALSE); |
4968 | fallback->framesize = framesize; | backtrack->framesize = framesize; |
4969 | fallback->localptr = localptr; | backtrack->localptr = localptr; |
4970 | opcode = *cc; | opcode = *cc; |
4971 | SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT); | SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT); |
4972 | found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target; | found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target; |
# | Line 4215 cc += GET(cc, 1); | Line 4975 cc += GET(cc, 1); |
4975 | ||
4976 | if (bra == OP_BRAMINZERO) | if (bra == OP_BRAMINZERO) |
4977 | { | { |
4978 | /* This is a braminzero fallback path. */ | /* This is a braminzero backtrack path. */ |
4979 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
4980 | free_stack(common, 1); | free_stack(common, 1); |
4981 | brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); | brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); |
# | Line 4238 else | Line 4998 else |
4998 | init_frame(common, ccbegin, framesize + 1, 2, FALSE); | init_frame(common, ccbegin, framesize + 1, 2, FALSE); |
4999 | } | } |
5000 | ||
5001 | memset(&altfallback, 0, sizeof(fallback_common)); | memset(&altbacktrack, 0, sizeof(backtrack_common)); |
5002 | common->leavelabel = NULL; | common->quitlabel = NULL; |
5003 | common->leave = NULL; | common->quit = NULL; |
5004 | while (1) | while (1) |
5005 | { | { |
5006 | common->acceptlabel = NULL; | common->acceptlabel = NULL; |
5007 | common->accept = NULL; | common->accept = NULL; |
5008 | altfallback.top = NULL; | altbacktrack.top = NULL; |
5009 | altfallback.topfallbacks = NULL; | altbacktrack.topbacktracks = NULL; |
5010 | ||
5011 | if (*ccbegin == OP_ALT) | if (*ccbegin == OP_ALT) |
5012 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
5013 | ||
5014 | altfallback.cc = ccbegin; | altbacktrack.cc = ccbegin; |
5015 | compile_hotpath(common, ccbegin + 1 + LINK_SIZE, cc, &altfallback); | compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); |
5016 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5017 | { | { |
5018 | common->leavelabel = save_leavelabel; | common->quitlabel = save_quitlabel; |
5019 | common->acceptlabel = save_acceptlabel; | common->acceptlabel = save_acceptlabel; |
5020 | common->leave = save_leave; | common->quit = save_quit; |
5021 | common->accept = save_accept; | common->accept = save_accept; |
5022 | return NULL; | return NULL; |
5023 | } | } |
# | Line 4307 while (1) | Line 5067 while (1) |
5067 | } | } |
5068 | add_jump(compiler, found, JUMP(SLJIT_JUMP)); | add_jump(compiler, found, JUMP(SLJIT_JUMP)); |
5069 | ||
5070 | compile_fallbackpath(common, altfallback.top); | compile_backtrackingpath(common, altbacktrack.top); |
5071 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5072 | { | { |
5073 | common->leavelabel = save_leavelabel; | common->quitlabel = save_quitlabel; |
5074 | common->acceptlabel = save_acceptlabel; | common->acceptlabel = save_acceptlabel; |
5075 | common->leave = save_leave; | common->quit = save_quit; |
5076 | common->accept = save_accept; | common->accept = save_accept; |
5077 | return NULL; | return NULL; |
5078 | } | } |
5079 | set_jumps(altfallback.topfallbacks, LABEL()); | set_jumps(altbacktrack.topbacktracks, LABEL()); |
5080 | ||
5081 | if (*cc != OP_ALT) | if (*cc != OP_ALT) |
5082 | break; | break; |
# | Line 4325 while (1) | Line 5085 while (1) |
5085 | cc += GET(cc, 1); | cc += GET(cc, 1); |
5086 | } | } |
5087 | /* None of them matched. */ | /* None of them matched. */ |
5088 | if (common->leave != NULL) | if (common->quit != NULL) |
5089 | set_jumps(common->leave, LABEL()); | set_jumps(common->quit, LABEL()); |
5090 | ||
5091 | if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) | if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) |
5092 | { | { |
# | Line 4393 if (opcode == OP_ASSERT || opcode == OP_ | Line 5153 if (opcode == OP_ASSERT || opcode == OP_ |
5153 | ||
5154 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
5155 | { | { |
5156 | fallback->hotpath = LABEL(); | backtrack->matchingpath = LABEL(); |
5157 | sljit_set_label(jump, fallback->hotpath); | sljit_set_label(jump, backtrack->matchingpath); |
5158 | } | } |
5159 | else if (bra == OP_BRAMINZERO) | else if (bra == OP_BRAMINZERO) |
5160 | { | { |
5161 | JUMPTO(SLJIT_JUMP, fallback->hotpath); | JUMPTO(SLJIT_JUMP, backtrack->matchingpath); |
5162 | JUMPHERE(brajump); | JUMPHERE(brajump); |
5163 | if (framesize >= 0) | if (framesize >= 0) |
5164 | { | { |
# | Line 4406 if (opcode == OP_ASSERT || opcode == OP_ | Line 5166 if (opcode == OP_ASSERT || opcode == OP_ |
5166 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
5167 | 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)); |
5168 | } | } |
5169 | set_jumps(fallback->common.topfallbacks, LABEL()); | set_jumps(backtrack->common.topbacktracks, LABEL()); |
5170 | } | } |
5171 | } | } |
5172 | else | else |
# | Line 4436 else | Line 5196 else |
5196 | } | } |
5197 | ||
5198 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
5199 | fallback->hotpath = LABEL(); | backtrack->matchingpath = LABEL(); |
5200 | else if (bra == OP_BRAMINZERO) | else if (bra == OP_BRAMINZERO) |
5201 | { | { |
5202 | JUMPTO(SLJIT_JUMP, fallback->hotpath); | JUMPTO(SLJIT_JUMP, backtrack->matchingpath); |
5203 | JUMPHERE(brajump); | JUMPHERE(brajump); |
5204 | } | } |
5205 | ||
5206 | if (bra != OP_BRA) | if (bra != OP_BRA) |
5207 | { | { |
5208 | SLJIT_ASSERT(found == &fallback->common.topfallbacks); | SLJIT_ASSERT(found == &backtrack->common.topbacktracks); |
5209 | set_jumps(fallback->common.topfallbacks, LABEL()); | set_jumps(backtrack->common.topbacktracks, LABEL()); |
5210 | fallback->common.topfallbacks = NULL; | backtrack->common.topbacktracks = NULL; |
5211 | } | } |
5212 | } | } |
5213 | ||
5214 | common->leavelabel = save_leavelabel; | common->quitlabel = save_quitlabel; |
5215 | common->acceptlabel = save_acceptlabel; | common->acceptlabel = save_acceptlabel; |
5216 | common->leave = save_leave; | common->quit = save_quit; |
5217 | common->accept = save_accept; | common->accept = save_accept; |
5218 | return cc + 1 + LINK_SIZE; | return cc + 1 + LINK_SIZE; |
5219 | } | } |
# | Line 4622 return condition; | Line 5382 return condition; |
5382 | Or nothing, if trace is unnecessary | Or nothing, if trace is unnecessary |
5383 | */ | */ |
5384 | ||
5385 | static pcre_uchar *compile_bracket_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) | static pcre_uchar *compile_bracket_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
5386 | { | { |
5387 | DEFINE_COMPILER; | DEFINE_COMPILER; |
5388 | fallback_common *fallback; | backtrack_common *backtrack; |
5389 | pcre_uchar opcode; | pcre_uchar opcode; |
5390 | int localptr = 0; | int localptr = 0; |
5391 | int offset = 0; | int offset = 0; |
5392 | int stacksize; | int stacksize; |
5393 | pcre_uchar *ccbegin; | pcre_uchar *ccbegin; |
5394 | pcre_uchar *hotpath; | pcre_uchar *matchingpath; |
5395 | pcre_uchar bra = OP_BRA; | pcre_uchar bra = OP_BRA; |
5396 | pcre_uchar ket; | pcre_uchar ket; |
5397 | assert_fallback *assert; | assert_backtrack *assert; |
5398 | BOOL has_alternatives; | BOOL has_alternatives; |
5399 | struct sljit_jump *jump; | struct sljit_jump *jump; |
5400 | struct sljit_jump *skip; | struct sljit_jump *skip; |
5401 | struct sljit_label *rmaxlabel = NULL; | struct sljit_label *rmaxlabel = NULL; |
5402 | struct sljit_jump *braminzerojump = NULL; | struct sljit_jump *braminzerojump = NULL; |
5403 | ||
5404 | PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL); |
5405 | ||
5406 | if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) | if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) |
5407 | { | { |
# | Line 4652 if (*cc == OP_BRAZERO || *cc == OP_BRAMI | Line 5412 if (*cc == OP_BRAZERO || *cc == OP_BRAMI |
5412 | ||
5413 | opcode = *cc; | opcode = *cc; |
5414 | ccbegin = cc; | ccbegin = cc; |
5415 | hotpath = ccbegin + 1 + LINK_SIZE; | matchingpath = ccbegin + 1 + LINK_SIZE; |
5416 | ||
5417 | 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) |
5418 | { | { |
5419 | /* Drop this bracket_fallback. */ | /* Drop this bracket_backtrack. */ |
5420 | parent->top = fallback->prev; | parent->top = backtrack->prev; |
5421 | return bracketend(cc); | return bracketend(cc); |
5422 | } | } |
5423 | ||
# | Line 4669 cc += GET(cc, 1); | Line 5429 cc += GET(cc, 1); |
5429 | has_alternatives = *cc == OP_ALT; | has_alternatives = *cc == OP_ALT; |
5430 | if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) | if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) |
5431 | { | { |
5432 | has_alternatives = (*hotpath == OP_RREF) ? FALSE : TRUE; | has_alternatives = (*matchingpath == OP_RREF) ? FALSE : TRUE; |
5433 | if (*hotpath == OP_NRREF) | if (*matchingpath == OP_NRREF) |
5434 | { | { |
5435 | stacksize = GET2(hotpath, 1); | stacksize = GET2(matchingpath, 1); |
5436 | if (common->currententry == NULL || stacksize == RREF_ANY) | if (common->currententry == NULL || stacksize == RREF_ANY) |
5437 | has_alternatives = FALSE; | has_alternatives = FALSE; |
5438 | else if (common->currententry->start == 0) | else if (common->currententry->start == 0) |
# | Line 4693 if (opcode == OP_CBRA || opcode == OP_SC | Line 5453 if (opcode == OP_CBRA || opcode == OP_SC |
5453 | offset = GET2(ccbegin, 1 + LINK_SIZE); | offset = GET2(ccbegin, 1 + LINK_SIZE); |
5454 | localptr = OVECTOR_PRIV(offset); | localptr = OVECTOR_PRIV(offset); |
5455 | offset <<= 1; | offset <<= 1; |
5456 | FALLBACK_AS(bracket_fallback)->localptr = localptr; | BACKTRACK_AS(bracket_backtrack)->localptr = localptr; |
5457 | hotpath += IMM2_SIZE; | matchingpath += IMM2_SIZE; |
5458 | } | } |
5459 | else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND) | else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND) |
5460 | { | { |
5461 | /* Other brackets simply allocate the next entry. */ | /* Other brackets simply allocate the next entry. */ |
5462 | localptr = PRIV_DATA(ccbegin); | localptr = PRIV_DATA(ccbegin); |
5463 | SLJIT_ASSERT(localptr != 0); | SLJIT_ASSERT(localptr != 0); |
5464 | FALLBACK_AS(bracket_fallback)->localptr = localptr; | BACKTRACK_AS(bracket_backtrack)->localptr = localptr; |
5465 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
5466 | FALLBACK_AS(bracket_fallback)->u.framesize = get_framesize(common, ccbegin, FALSE); | BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, FALSE); |
5467 | } | } |
5468 | ||
5469 | /* Instructions before the first alternative. */ | /* Instructions before the first alternative. */ |
# | Line 4728 if (bra == OP_BRAZERO) | Line 5488 if (bra == OP_BRAZERO) |
5488 | ||
5489 | if (bra == OP_BRAMINZERO) | if (bra == OP_BRAMINZERO) |
5490 | { | { |
5491 | /* 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) */ |
5492 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
5493 | if (ket != OP_KETRMIN) | if (ket != OP_KETRMIN) |
5494 | { | { |
# | Line 4745 if (bra == OP_BRAMINZERO) | Line 5505 if (bra == OP_BRAMINZERO) |
5505 | skip = JUMP(SLJIT_JUMP); | skip = JUMP(SLJIT_JUMP); |
5506 | JUMPHERE(jump); | JUMPHERE(jump); |
5507 | /* Checking zero-length iteration. */ | /* Checking zero-length iteration. */ |
5508 | if (opcode != OP_ONCE || FALLBACK_AS(bracket_fallback)->u.framesize < 0) | if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
5509 | { | { |
5510 | /* When we come from outside, localptr contains the previous STR_PTR. */ | /* When we come from outside, localptr contains the previous STR_PTR. */ |
5511 | 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 4754 if (bra == OP_BRAMINZERO) | Line 5514 if (bra == OP_BRAMINZERO) |
5514 | { | { |
5515 | /* Except when the whole stack frame must be saved. */ | /* Except when the whole stack frame must be saved. */ |
5516 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
5517 | 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)); |
5518 | } | } |
5519 | JUMPHERE(skip); | JUMPHERE(skip); |
5520 | } | } |
# | Line 4768 if (bra == OP_BRAMINZERO) | Line 5528 if (bra == OP_BRAMINZERO) |
5528 | } | } |
5529 | ||
5530 | if (ket == OP_KETRMIN) | if (ket == OP_KETRMIN) |
5531 | FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL(); | BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); |
5532 | ||
5533 | if (ket == OP_KETRMAX) | if (ket == OP_KETRMAX) |
5534 | { | { |
5535 | rmaxlabel = LABEL(); | rmaxlabel = LABEL(); |
5536 | if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA) | if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA) |
5537 | FALLBACK_AS(bracket_fallback)->althotpath = rmaxlabel; | BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmaxlabel; |
5538 | } | } |
5539 | ||
5540 | /* Handling capturing brackets and alternatives. */ | /* Handling capturing brackets and alternatives. */ |
5541 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
5542 | { | { |
5543 | if (FALLBACK_AS(bracket_fallback)->u.framesize < 0) | if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
5544 | { | { |
5545 | /* Neither capturing brackets nor recursions are not found in the block. */ | /* Neither capturing brackets nor recursions are not found in the block. */ |
5546 | if (ket == OP_KETRMIN) | if (ket == OP_KETRMIN) |
# | Line 4804 if (opcode == OP_ONCE) | Line 5564 if (opcode == OP_ONCE) |
5564 | { | { |
5565 | if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) | if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) |
5566 | { | { |
5567 | allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 2); | allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 2); |
5568 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
5569 | 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)); |
5570 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
5571 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); |
5572 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); |
5573 | 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); |
5574 | } | } |
5575 | else | else |
5576 | { | { |
5577 | allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 1); | allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1); |
5578 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
5579 | 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)); |
5580 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); |
5581 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); |
5582 | init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize, 1, FALSE); | init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize, 1, FALSE); |
5583 | } | } |
5584 | } | } |
5585 | } | } |
# | Line 4853 else if (has_alternatives) | Line 5613 else if (has_alternatives) |
5613 | /* Generating code for the first alternative. */ | /* Generating code for the first alternative. */ |
5614 | if (opcode == OP_COND || opcode == OP_SCOND) | if (opcode == OP_COND || opcode == OP_SCOND) |
5615 | { | { |
5616 | if (*hotpath == OP_CREF) | if (*matchingpath == OP_CREF) |
5617 | { | { |
5618 | SLJIT_ASSERT(has_alternatives); | SLJIT_ASSERT(has_alternatives); |
5619 | add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), | add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), |
5620 | 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(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); |
5621 | hotpath += 1 + IMM2_SIZE; | matchingpath += 1 + IMM2_SIZE; |
5622 | } | } |
5623 | else if (*hotpath == OP_NCREF) | else if (*matchingpath == OP_NCREF) |
5624 | { | { |
5625 | SLJIT_ASSERT(has_alternatives); | SLJIT_ASSERT(has_alternatives); |
5626 | stacksize = GET2(hotpath, 1); | stacksize = GET2(matchingpath, 1); |
5627 | 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)); |
5628 | ||
5629 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); |
5630 | 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); |
5631 | 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); |
5632 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, (stacksize << 8) | (common->ovector_start / sizeof(sljit_w))); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, (stacksize << 8) | (common->ovector_start / sizeof(sljit_w))); |
5633 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0); | GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0); |
5634 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); |
5635 | 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)); |
5636 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); |
5637 | 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)); |
5638 | ||
5639 | JUMPHERE(jump); | JUMPHERE(jump); |
5640 | hotpath += 1 + IMM2_SIZE; | matchingpath += 1 + IMM2_SIZE; |
5641 | } | } |
5642 | else if (*hotpath == OP_RREF || *hotpath == OP_NRREF) | else if (*matchingpath == OP_RREF || *matchingpath == OP_NRREF) |
5643 | { | { |
5644 | /* Never has other case. */ | /* Never has other case. */ |
5645 | FALLBACK_AS(bracket_fallback)->u.condfailed = NULL; | BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL; |
5646 | ||
5647 | stacksize = GET2(hotpath, 1); | stacksize = GET2(matchingpath, 1); |
5648 | if (common->currententry == NULL) | if (common->currententry == NULL) |
5649 | stacksize = 0; | stacksize = 0; |
5650 | else if (stacksize == RREF_ANY) | else if (stacksize == RREF_ANY) |
# | Line 4894 if (opcode == OP_COND || opcode == OP_SC | Line 5654 if (opcode == OP_COND || opcode == OP_SC |
5654 | else | else |
5655 | stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE); | stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE); |
5656 | ||
5657 | if (*hotpath == OP_RREF || stacksize || common->currententry == NULL) | if (*matchingpath == OP_RREF || stacksize || common->currententry == NULL) |
5658 | { | { |
5659 | SLJIT_ASSERT(!has_alternatives); | SLJIT_ASSERT(!has_alternatives); |
5660 | if (stacksize != 0) | if (stacksize != 0) |
5661 | hotpath += 1 + IMM2_SIZE; | matchingpath += 1 + IMM2_SIZE; |
5662 | else | else |
5663 | { | { |
5664 | if (*cc == OP_ALT) | if (*cc == OP_ALT) |
5665 | { | { |
5666 | hotpath = cc + 1 + LINK_SIZE; | matchingpath = cc + 1 + LINK_SIZE; |
5667 | cc += GET(cc, 1); | cc += GET(cc, 1); |
5668 | } | } |
5669 | else | else |
5670 | hotpath = cc; | matchingpath = cc; |
5671 | } | } |
5672 | } | } |
5673 | else | else |
5674 | { | { |
5675 | SLJIT_ASSERT(has_alternatives); | SLJIT_ASSERT(has_alternatives); |
5676 | ||
5677 | stacksize = GET2(hotpath, 1); | stacksize = GET2(matchingpath, 1); |
5678 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); |
5679 | 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); |
5680 | 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); |
5681 | 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)); |
5682 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); |
5683 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0); | GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0); |
5684 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); |
5685 | 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)); |
5686 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); |
5687 | 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)); |
5688 | hotpath += 1 + IMM2_SIZE; | matchingpath += 1 + IMM2_SIZE; |
5689 | } | } |
5690 | } | } |
5691 | else | else |
5692 | { | { |
5693 | SLJIT_ASSERT(has_alternatives && *hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT); | SLJIT_ASSERT(has_alternatives && *matchingpath >= OP_ASSERT && *matchingpath <= OP_ASSERTBACK_NOT); |
5694 | /* Similar code as PUSH_FALLBACK macro. */ | /* Similar code as PUSH_BACKTRACK macro. */ |
5695 | assert = sljit_alloc_memory(compiler, sizeof(assert_fallback)); | assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack)); |
5696 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5697 | return NULL; | return NULL; |
5698 | memset(assert, 0, sizeof(assert_fallback)); | memset(assert, 0, sizeof(assert_backtrack)); |
5699 | assert->common.cc = hotpath; | assert->common.cc = matchingpath; |
5700 | FALLBACK_AS(bracket_fallback)->u.assert = assert; | BACKTRACK_AS(bracket_backtrack)->u.assert = assert; |
5701 | hotpath = compile_assert_hotpath(common, hotpath, assert, TRUE); | matchingpath = compile_assert_matchingpath(common, matchingpath, assert, TRUE); |
5702 | } | } |
5703 | } | } |
5704 | ||
5705 | compile_hotpath(common, hotpath, cc, fallback); | compile_matchingpath(common, matchingpath, cc, backtrack); |
5706 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5707 | return NULL; | return NULL; |
5708 | ||
5709 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
5710 | { | { |
5711 | if (FALLBACK_AS(bracket_fallback)->u.framesize < 0) | if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
5712 | { | { |
5713 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
5714 | /* TMP2 which is set here used by OP_KETRMAX below. */ | /* TMP2 which is set here used by OP_KETRMAX below. */ |
# | Line 4963 if (opcode == OP_ONCE) | Line 5723 if (opcode == OP_ONCE) |
5723 | else | else |
5724 | { | { |
5725 | stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1; | stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1; |
5726 | 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)); |
5727 | if (ket == OP_KETRMAX) | if (ket == OP_KETRMAX) |
5728 | { | { |
5729 | /* TMP2 which is set here used by OP_KETRMAX below. */ | /* TMP2 which is set here used by OP_KETRMAX below. */ |
# | Line 4998 if (has_alternatives) | Line 5758 if (has_alternatives) |
5758 | if (opcode != OP_ONCE) | if (opcode != OP_ONCE) |
5759 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); |
5760 | if (ket != OP_KETRMAX) | if (ket != OP_KETRMAX) |
5761 | FALLBACK_AS(bracket_fallback)->althotpath = LABEL(); | BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); |
5762 | } | } |
5763 | ||
5764 | /* Must be after the hotpath label. */ | /* Must be after the matchingpath label. */ |
5765 | if (offset != 0) | if (offset != 0) |
5766 | { | { |
5767 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
# | Line 5014 if (ket == OP_KETRMAX) | Line 5774 if (ket == OP_KETRMAX) |
5774 | if (opcode == OP_ONCE || opcode >= OP_SBRA) | if (opcode == OP_ONCE || opcode >= OP_SBRA) |
5775 | { | { |
5776 | if (has_alternatives) | if (has_alternatives) |
5777 | FALLBACK_AS(bracket_fallback)->althotpath = LABEL(); | BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); |
5778 | /* Checking zero-length iteration. */ | /* Checking zero-length iteration. */ |
5779 | if (opcode != OP_ONCE) | if (opcode != OP_ONCE) |
5780 | { | |
5781 | 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); |
5782 | /* Drop STR_PTR for greedy plus quantifier. */ | |
5783 | if (bra != OP_BRAZERO) | |
5784 | free_stack(common, 1); | |
5785 | } | |
5786 | else | else |
5787 | /* TMP2 must contain the starting STR_PTR. */ | /* TMP2 must contain the starting STR_PTR. */ |
5788 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel); | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel); |
5789 | } | } |
5790 | else | else |
5791 | JUMPTO(SLJIT_JUMP, rmaxlabel); | JUMPTO(SLJIT_JUMP, rmaxlabel); |
5792 | FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL(); | BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); |
5793 | } | } |
5794 | ||
5795 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
5796 | FALLBACK_AS(bracket_fallback)->zerohotpath = LABEL(); | BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL(); |
5797 | ||
5798 | if (bra == OP_BRAMINZERO) | if (bra == OP_BRAMINZERO) |
5799 | { | { |
5800 | /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */ | /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */ |
5801 | JUMPTO(SLJIT_JUMP, ((braminzero_fallback *)parent)->hotpath); | JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath); |
5802 | if (braminzerojump != NULL) | if (braminzerojump != NULL) |
5803 | { | { |
5804 | JUMPHERE(braminzerojump); | JUMPHERE(braminzerojump); |
5805 | /* We need to release the end pointer to perform the | /* We need to release the end pointer to perform the |
5806 | fallback for the zero-length iteration. When | backtrack for the zero-length iteration. When |
5807 | framesize is < 0, OP_ONCE will do the release itself. */ | framesize is < 0, OP_ONCE will do the release itself. */ |
5808 | if (opcode == OP_ONCE && FALLBACK_AS(bracket_fallback)->u.framesize >= 0) | if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0) |
5809 | { | { |
5810 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
5811 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
# | Line 5048 if (bra == OP_BRAMINZERO) | Line 5813 if (bra == OP_BRAMINZERO) |
5813 | else if (ket == OP_KETRMIN && opcode != OP_ONCE) | else if (ket == OP_KETRMIN && opcode != OP_ONCE) |
5814 | free_stack(common, 1); | free_stack(common, 1); |
5815 | } | } |
5816 | /* Continue to the normal fallback. */ | /* Continue to the normal backtrack. */ |
5817 | } | } |
5818 | ||
5819 | if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO) | if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO) |
# | Line 5061 cc += 1 + LINK_SIZE; | Line 5826 cc += 1 + LINK_SIZE; |
5826 | return cc; | return cc; |
5827 | } | } |
5828 | ||
5829 | static pcre_uchar *compile_bracketpos_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) | static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
5830 | { | { |
5831 | DEFINE_COMPILER; | DEFINE_COMPILER; |
5832 | fallback_common *fallback; | backtrack_common *backtrack; |
5833 | pcre_uchar opcode; | pcre_uchar opcode; |
5834 | int localptr; | int localptr; |
5835 | int cbraprivptr = 0; | int cbraprivptr = 0; |
# | Line 5077 int stack; | Line 5842 int stack; |
5842 | struct sljit_label *loop = NULL; | struct sljit_label *loop = NULL; |
5843 | struct jump_list *emptymatch = NULL; | struct jump_list *emptymatch = NULL; |
5844 | ||
5845 | PUSH_FALLBACK(sizeof(bracketpos_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL); |
5846 | if (*cc == OP_BRAPOSZERO) | if (*cc == OP_BRAPOSZERO) |
5847 | { | { |
5848 | zero = TRUE; | zero = TRUE; |
# | Line 5087 if (*cc == OP_BRAPOSZERO) | Line 5852 if (*cc == OP_BRAPOSZERO) |
5852 | opcode = *cc; | opcode = *cc; |
5853 | localptr = PRIV_DATA(cc); | localptr = PRIV_DATA(cc); |
5854 | SLJIT_ASSERT(localptr != 0); | SLJIT_ASSERT(localptr != 0); |
5855 | FALLBACK_AS(bracketpos_fallback)->localptr = localptr; | BACKTRACK_AS(bracketpos_backtrack)->localptr = localptr; |
5856 | switch(opcode) | switch(opcode) |
5857 | { | { |
5858 | case OP_BRAPOS: | case OP_BRAPOS: |
# | Line 5109 switch(opcode) | Line 5874 switch(opcode) |
5874 | } | } |
5875 | ||
5876 | framesize = get_framesize(common, cc, FALSE); | framesize = get_framesize(common, cc, FALSE); |
5877 | FALLBACK_AS(bracketpos_fallback)->framesize = framesize; | BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize; |
5878 | if (framesize < 0) | if (framesize < 0) |
5879 | { | { |
5880 | stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1; | stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1; |
5881 | if (!zero) | if (!zero) |
5882 | stacksize++; | stacksize++; |
5883 | FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize; | BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; |
5884 | allocate_stack(common, stacksize); | allocate_stack(common, stacksize); |
5885 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); |
5886 | ||
# | Line 5139 else | Line 5904 else |
5904 | stacksize++; | stacksize++; |
5905 | if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) | if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) |
5906 | stacksize++; | stacksize++; |
5907 | FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize; | BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; |
5908 | allocate_stack(common, stacksize); | allocate_stack(common, stacksize); |
5909 | ||
5910 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
# | Line 5166 if (opcode == OP_CBRAPOS || opcode == OP | Line 5931 if (opcode == OP_CBRAPOS || opcode == OP |
5931 | loop = LABEL(); | loop = LABEL(); |
5932 | while (*cc != OP_KETRPOS) | while (*cc != OP_KETRPOS) |
5933 | { | { |
5934 | fallback->top = NULL; | backtrack->top = NULL; |
5935 | fallback->topfallbacks = NULL; | backtrack->topbacktracks = NULL; |
5936 | cc += GET(cc, 1); | cc += GET(cc, 1); |
5937 | ||
5938 | compile_hotpath(common, ccbegin, cc, fallback); | compile_matchingpath(common, ccbegin, cc, backtrack); |
5939 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5940 | return NULL; | return NULL; |
5941 | ||
# | Line 5231 while (*cc != OP_KETRPOS) | Line 5996 while (*cc != OP_KETRPOS) |
5996 | JUMPTO(SLJIT_JUMP, loop); | JUMPTO(SLJIT_JUMP, loop); |
5997 | flush_stubs(common); | flush_stubs(common); |
5998 | ||
5999 | compile_fallbackpath(common, fallback->top); | compile_backtrackingpath(common, backtrack->top); |
6000 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
6001 | return NULL; | return NULL; |
6002 | set_jumps(fallback->topfallbacks, LABEL()); | set_jumps(backtrack->topbacktracks, LABEL()); |
6003 | ||
6004 | if (framesize < 0) | if (framesize < 0) |
6005 | { | { |
# | Line 5264 while (*cc != OP_KETRPOS) | Line 6029 while (*cc != OP_KETRPOS) |
6029 | ccbegin = cc + 1 + LINK_SIZE; | ccbegin = cc + 1 + LINK_SIZE; |
6030 | } | } |
6031 | ||
6032 | fallback->topfallbacks = NULL; | backtrack->topbacktracks = NULL; |
6033 | if (!zero) | if (!zero) |
6034 | { | { |
6035 | if (framesize < 0) | if (framesize < 0) |
6036 | 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)); |
6037 | else /* TMP2 is set to [localptr] above. */ | else /* TMP2 is set to [localptr] above. */ |
6038 | 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)); |
6039 | } | } |
6040 | ||
6041 | /* None of them matched. */ | /* None of them matched. */ |
# | Line 5371 if (end != NULL) | Line 6136 if (end != NULL) |
6136 | return cc; | return cc; |
6137 | } | } |
6138 | ||
6139 | static pcre_uchar *compile_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) | static pcre_uchar *compile_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
6140 | { | { |
6141 | DEFINE_COMPILER; | DEFINE_COMPILER; |
6142 | fallback_common *fallback; | backtrack_common *backtrack; |
6143 | pcre_uchar opcode; | pcre_uchar opcode; |
6144 | pcre_uchar type; | pcre_uchar type; |
6145 | int arg1 = -1, arg2 = -1; | int arg1 = -1, arg2 = -1; |
# | Line 5382 pcre_uchar* end; | Line 6147 pcre_uchar* end; |
6147 | jump_list *nomatch = NULL; | jump_list *nomatch = NULL; |
6148 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
6149 | struct sljit_label *label; | struct sljit_label *label; |
6150 | int localptr = PRIV_DATA(cc); | |
6151 | int base = (localptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_LOCALS_REG); | |
6152 | int offset0 = (localptr == 0) ? STACK(0) : localptr; | |
6153 | int offset1 = (localptr == 0) ? STACK(1) : localptr + (int)sizeof(sljit_w); | |
6154 | int tmp_base, tmp_offset; | |
6155 | ||
6156 | PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL); |
6157 | ||
6158 | cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end); | cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end); |
6159 | ||
6160 | switch (type) | |
6161 | { | |
6162 | case OP_NOT_DIGIT: | |
6163 | case OP_DIGIT: | |
6164 | case OP_NOT_WHITESPACE: | |
6165 | case OP_WHITESPACE: | |
6166 | case OP_NOT_WORDCHAR: | |
6167 | case OP_WORDCHAR: | |
6168 | case OP_ANY: | |
6169 | case OP_ALLANY: | |
6170 | case OP_ANYBYTE: | |
6171 | case OP_ANYNL: | |
6172 | case OP_NOT_HSPACE: | |
6173 | case OP_HSPACE: | |
6174 | case OP_NOT_VSPACE: | |
6175 | case OP_VSPACE: | |
6176 | case OP_CHAR: | |
6177 | case OP_CHARI: | |
6178 | case OP_NOT: | |
6179 | case OP_NOTI: | |
6180 | case OP_CLASS: | |
6181 | case OP_NCLASS: | |
6182 | tmp_base = TMP3; | |
6183 | tmp_offset = 0; | |
6184 | break; | |
6185 | ||
6186 | default: | |
6187 | SLJIT_ASSERT_STOP(); | |
6188 | /* Fall through. */ | |
6189 | ||
6190 | case OP_EXTUNI: | |
6191 | case OP_XCLASS: | |
6192 | case OP_NOTPROP: | |
6193 | case OP_PROP: | |
6194 | tmp_base = SLJIT_MEM1(SLJIT_LOCALS_REG); | |
6195 | tmp_offset = POSSESSIVE0; | |
6196 | break; | |
6197 | } | |
6198 | ||
6199 | switch(opcode) | switch(opcode) |
6200 | { | { |
6201 | case OP_STAR: | case OP_STAR: |
# | Line 5395 switch(opcode) | Line 6204 switch(opcode) |
6204 | case OP_CRRANGE: | case OP_CRRANGE: |
6205 | if (type == OP_ANYNL || type == OP_EXTUNI) | if (type == OP_ANYNL || type == OP_EXTUNI) |
6206 | { | { |
6207 | SLJIT_ASSERT(localptr == 0); | |
6208 | if (opcode == OP_STAR || opcode == OP_UPTO) | if (opcode == OP_STAR || opcode == OP_UPTO) |
6209 | { | { |
6210 | allocate_stack(common, 2); | allocate_stack(common, 2); |
# | Line 5406 switch(opcode) | Line 6216 switch(opcode) |
6216 | allocate_stack(common, 1); | allocate_stack(common, 1); |
6217 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
6218 | } | } |
6219 | ||
6220 | if (opcode == OP_UPTO || opcode == OP_CRRANGE) | if (opcode == OP_UPTO || opcode == OP_CRRANGE) |
6221 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); |
6222 | ||
6223 | label = LABEL(); | label = LABEL(); |
6224 | compile_char1_hotpath(common, type, cc, &fallback->topfallbacks); | compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); |
6225 | if (opcode == OP_UPTO || opcode == OP_CRRANGE) | if (opcode == OP_UPTO || opcode == OP_CRRANGE) |
6226 | { | { |
6227 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); |
# | Line 5422 switch(opcode) | Line 6233 switch(opcode) |
6233 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); |
6234 | } | } |
6235 | ||
6236 | /* We cannot use TMP3 because of this allocate_stack. */ | |
6237 | allocate_stack(common, 1); | allocate_stack(common, 1); |
6238 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
6239 | JUMPTO(SLJIT_JUMP, label); | JUMPTO(SLJIT_JUMP, label); |
# | Line 5430 switch(opcode) | Line 6242 switch(opcode) |
6242 | } | } |
6243 | else | else |
6244 | { | { |
6245 | allocate_stack(common, 2); | if (opcode == OP_PLUS) |
6246 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); |
6247 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); | if (localptr == 0) |
6248 | allocate_stack(common, 2); | |
6249 | OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); | |
6250 | if (opcode <= OP_PLUS) | |
6251 | OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); | |
6252 | else | |
6253 | OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, 1); | |
6254 | label = LABEL(); | label = LABEL(); |
6255 | compile_char1_hotpath(common, type, cc, &nomatch); | compile_char1_matchingpath(common, type, cc, &nomatch); |
6256 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); |
6257 | if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0)) | if (opcode <= OP_PLUS) |
6258 | JUMPTO(SLJIT_JUMP, label); | |
6259 | else if (opcode == OP_CRRANGE && arg1 == 0) | |
6260 | { | { |
6261 | OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); | OP2(SLJIT_ADD, base, offset1, base, offset1, SLJIT_IMM, 1); |
6262 | JUMPTO(SLJIT_JUMP, label); | JUMPTO(SLJIT_JUMP, label); |
6263 | } | } |
6264 | else | else |
6265 | { | { |
6266 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP1, 0, base, offset1); |
6267 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
6268 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); | OP1(SLJIT_MOV, base, offset1, TMP1, 0); |
6269 | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label); | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label); |
6270 | } | } |
6271 | set_jumps(nomatch, LABEL()); | set_jumps(nomatch, LABEL()); |
6272 | if (opcode == OP_PLUS || opcode == OP_CRRANGE) | if (opcode == OP_CRRANGE) |
6273 | add_jump(compiler, &fallback->topfallbacks, | add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, base, offset1, SLJIT_IMM, arg2 + 1)); |
6274 | CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, opcode == OP_PLUS ? 2 : arg2 + 1)); | OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | ||
6275 | } | } |
6276 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); |
6277 | break; | break; |
6278 | ||
6279 | case OP_MINSTAR: | case OP_MINSTAR: |
6280 | case OP_MINPLUS: | case OP_MINPLUS: |
allocate_stack(common, 1); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | ||
6281 | if (opcode == OP_MINPLUS) | if (opcode == OP_MINPLUS) |
6282 | add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); | compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); |
6283 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | if (localptr == 0) |
6284 | allocate_stack(common, 1); | |
6285 | OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); | |
6286 | BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); | |
6287 | break; | break; |
6288 | ||
6289 | case OP_MINUPTO: | case OP_MINUPTO: |
6290 | case OP_CRMINRANGE: | case OP_CRMINRANGE: |
6291 | allocate_stack(common, 2); | if (localptr == 0) |
6292 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | allocate_stack(common, 2); |
6293 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); | OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); |
6294 | OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, 1); | |
6295 | if (opcode == OP_CRMINRANGE) | if (opcode == OP_CRMINRANGE) |
6296 | add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); |
6297 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); |
6298 | break; | break; |
6299 | ||
6300 | case OP_QUERY: | case OP_QUERY: |
6301 | case OP_MINQUERY: | case OP_MINQUERY: |
6302 | allocate_stack(common, 1); | if (localptr == 0) |
6303 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | allocate_stack(common, 1); |
6304 | OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); | |
6305 | if (opcode == OP_QUERY) | if (opcode == OP_QUERY) |
6306 | compile_char1_hotpath(common, type, cc, &fallback->topfallbacks); | compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); |
6307 | FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); | BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); |
6308 | break; | break; |
6309 | ||
6310 | case OP_EXACT: | case OP_EXACT: |
6311 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, arg1); |
6312 | label = LABEL(); | label = LABEL(); |
6313 | compile_char1_hotpath(common, type, cc, &fallback->topfallbacks); | compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); |
6314 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); | OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); |
6315 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | JUMPTO(SLJIT_C_NOT_ZERO, label); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); | ||
CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label); | ||
6316 | break; | break; |
6317 | ||
6318 | case OP_POSSTAR: | case OP_POSSTAR: |
6319 | case OP_POSPLUS: | case OP_POSPLUS: |
6320 | case OP_POSUPTO: | case OP_POSUPTO: |
6321 | if (opcode != OP_POSSTAR) | if (opcode == OP_POSPLUS) |
6322 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1); | compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); |
6323 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); | if (opcode == OP_POSUPTO) |
6324 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_IMM, arg1); | |
6325 | OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); | |
6326 | label = LABEL(); | label = LABEL(); |
6327 | compile_char1_hotpath(common, type, cc, &nomatch); | compile_char1_matchingpath(common, type, cc, &nomatch); |
6328 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); | OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); |
6329 | if (opcode != OP_POSUPTO) | if (opcode != OP_POSUPTO) |
{ | ||
if (opcode == OP_POSPLUS) | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2); | ||
6330 | JUMPTO(SLJIT_JUMP, label); | JUMPTO(SLJIT_JUMP, label); |
} | ||
6331 | else | else |
6332 | { | { |
6333 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_IMM, 1); |
6334 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | JUMPTO(SLJIT_C_NOT_ZERO, label); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); | ||
CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label); | ||
6335 | } | } |
6336 | set_jumps(nomatch, LABEL()); | set_jumps(nomatch, LABEL()); |
6337 | if (opcode == OP_POSPLUS) | OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset); |
add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2)); | ||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | ||
6338 | break; | break; |
6339 | ||
6340 | case OP_POSQUERY: | case OP_POSQUERY: |
6341 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); | OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); |
6342 | compile_char1_hotpath(common, type, cc, &nomatch); | compile_char1_matchingpath(common, type, cc, &nomatch); |
6343 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); | OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); |
6344 | set_jumps(nomatch, LABEL()); | set_jumps(nomatch, LABEL()); |
6345 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset); |
6346 | break; | break; |
6347 | ||
6348 | default: | default: |
# | Line 5540 decrease_call_count(common); | Line 6354 decrease_call_count(common); |
6354 | return end; | return end; |
6355 | } | } |
6356 | ||
6357 | 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_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
6358 | { | { |
6359 | DEFINE_COMPILER; | DEFINE_COMPILER; |
6360 | fallback_common *fallback; | backtrack_common *backtrack; |
6361 | ||
6362 | PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL); | PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL); |
6363 | ||
6364 | if (*cc == OP_FAIL) | if (*cc == OP_FAIL) |
6365 | { | { |
6366 | add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); |
6367 | return cc + 1; | return cc + 1; |
6368 | } | } |
6369 | ||
# | Line 5569 else | Line 6383 else |
6383 | 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); |
6384 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
6385 | 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)); |
6386 | 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)); |
6387 | 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)); |
6388 | if (common->acceptlabel == NULL) | if (common->acceptlabel == NULL) |
6389 | 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 5580 if (common->acceptlabel == NULL) | Line 6394 if (common->acceptlabel == NULL) |
6394 | 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)); |
6395 | else | else |
6396 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel); | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel); |
6397 | add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); |
6398 | return cc + 1; | return cc + 1; |
6399 | } | } |
6400 | ||
6401 | static SLJIT_INLINE pcre_uchar *compile_close_hotpath(compiler_common *common, pcre_uchar *cc) | static SLJIT_INLINE pcre_uchar *compile_close_matchingpath(compiler_common *common, pcre_uchar *cc) |
6402 | { | { |
6403 | DEFINE_COMPILER; | DEFINE_COMPILER; |
6404 | int offset = GET2(cc, 1); | int offset = GET2(cc, 1); |
# | Line 5600 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_R | Line 6414 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_R |
6414 | return cc + 1 + IMM2_SIZE; | return cc + 1 + IMM2_SIZE; |
6415 | } | } |
6416 | ||
6417 | static void compile_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, fallback_common *parent) | static void compile_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) |
6418 | { | { |
6419 | DEFINE_COMPILER; | DEFINE_COMPILER; |
6420 | fallback_common *fallback; | backtrack_common *backtrack; |
6421 | ||
6422 | while (cc < ccend) | while (cc < ccend) |
6423 | { | { |
# | Line 5639 while (cc < ccend) | Line 6453 while (cc < ccend) |
6453 | case OP_NOT: | case OP_NOT: |
6454 | case OP_NOTI: | case OP_NOTI: |
6455 | case OP_REVERSE: | case OP_REVERSE: |
6456 | cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); |
6457 | break; | break; |
6458 | ||
6459 | case OP_SET_SOM: | case OP_SET_SOM: |
6460 | PUSH_FALLBACK_NOVALUE(sizeof(fallback_common), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); |
6461 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
6462 | allocate_stack(common, 1); | allocate_stack(common, 1); |
6463 | 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); |
# | Line 5654 while (cc < ccend) | Line 6468 while (cc < ccend) |
6468 | case OP_CHAR: | case OP_CHAR: |
6469 | case OP_CHARI: | case OP_CHARI: |
6470 | if (common->mode == JIT_COMPILE) | if (common->mode == JIT_COMPILE) |
6471 | cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | cc = compile_charn_matchingpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); |
6472 | else | else |
6473 | cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); |
6474 | break; | break; |
6475 | ||
6476 | case OP_STAR: | case OP_STAR: |
# | Line 5724 while (cc < ccend) | Line 6538 while (cc < ccend) |
6538 | case OP_TYPEPOSPLUS: | case OP_TYPEPOSPLUS: |
6539 | case OP_TYPEPOSQUERY: | case OP_TYPEPOSQUERY: |
6540 | case OP_TYPEPOSUPTO: | case OP_TYPEPOSUPTO: |
6541 | cc = compile_iterator_hotpath(common, cc, parent); | cc = compile_iterator_matchingpath(common, cc, parent); |
6542 | break; | break; |
6543 | ||
6544 | case OP_CLASS: | case OP_CLASS: |
6545 | case OP_NCLASS: | case OP_NCLASS: |
6546 | 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) |
6547 | cc = compile_iterator_hotpath(common, cc, parent); | cc = compile_iterator_matchingpath(common, cc, parent); |
6548 | else | else |
6549 | cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); |
6550 | break; | break; |
6551 | ||
6552 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 |
6553 | case OP_XCLASS: | case OP_XCLASS: |
6554 | 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) |
6555 | cc = compile_iterator_hotpath(common, cc, parent); | cc = compile_iterator_matchingpath(common, cc, parent); |
6556 | else | else |
6557 | cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); |
6558 | break; | break; |
6559 | #endif | #endif |
6560 | ||
6561 | case OP_REF: | case OP_REF: |
6562 | case OP_REFI: | case OP_REFI: |
6563 | 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) |
6564 | cc = compile_ref_iterator_hotpath(common, cc, parent); | cc = compile_ref_iterator_matchingpath(common, cc, parent); |
6565 | else | else |
6566 | cc = compile_ref_hotpath(common, cc, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks, TRUE, FALSE); | cc = compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE); |
6567 | break; | break; |
6568 | ||
6569 | case OP_RECURSE: | case OP_RECURSE: |
6570 | cc = compile_recurse_hotpath(common, cc, parent); | cc = compile_recurse_matchingpath(common, cc, parent); |
6571 | break; | break; |
6572 | ||
6573 | case OP_ASSERT: | case OP_ASSERT: |
6574 | case OP_ASSERT_NOT: | case OP_ASSERT_NOT: |
6575 | case OP_ASSERTBACK: | case OP_ASSERTBACK: |
6576 | case OP_ASSERTBACK_NOT: | case OP_ASSERTBACK_NOT: |
6577 | PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc); |
6578 | cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE); | cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE); |
6579 | break; | break; |
6580 | ||
6581 | case OP_BRAMINZERO: | case OP_BRAMINZERO: |
6582 | PUSH_FALLBACK_NOVALUE(sizeof(braminzero_fallback), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc); |
6583 | cc = bracketend(cc + 1); | cc = bracketend(cc + 1); |
6584 | if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN) | if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN) |
6585 | { | { |
# | Line 5778 while (cc < ccend) | Line 6592 while (cc < ccend) |
6592 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
6593 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0); |
6594 | } | } |
6595 | FALLBACK_AS(braminzero_fallback)->hotpath = LABEL(); | BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL(); |
6596 | if (cc[1] > OP_ASSERTBACK_NOT) | if (cc[1] > OP_ASSERTBACK_NOT) |
6597 | decrease_call_count(common); | decrease_call_count(common); |
6598 | break; | break; |
# | Line 5791 while (cc < ccend) | Line 6605 while (cc < ccend) |
6605 | case OP_SBRA: | case OP_SBRA: |
6606 | case OP_SCBRA: | case OP_SCBRA: |
6607 | case OP_SCOND: | case OP_SCOND: |
6608 | cc = compile_bracket_hotpath(common, cc, parent); | cc = compile_bracket_matchingpath(common, cc, parent); |
6609 | break; | break; |
6610 | ||
6611 | case OP_BRAZERO: | case OP_BRAZERO: |
6612 | if (cc[1] > OP_ASSERTBACK_NOT) | if (cc[1] > OP_ASSERTBACK_NOT) |
6613 | cc = compile_bracket_hotpath(common, cc, parent); | cc = compile_bracket_matchingpath(common, cc, parent); |
6614 | else | else |
6615 | { | { |
6616 | PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc); |
6617 | cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE); | cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE); |
6618 | } | } |
6619 | break; | break; |
6620 | ||
# | Line 5809 while (cc < ccend) | Line 6623 while (cc < ccend) |
6623 | case OP_SBRAPOS: | case OP_SBRAPOS: |
6624 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
6625 | case OP_BRAPOSZERO: | case OP_BRAPOSZERO: |
6626 | cc = compile_bracketpos_hotpath(common, cc, parent); | cc = compile_bracketpos_matchingpath(common, cc, parent); |
6627 | break; | break; |
6628 | ||
6629 | case OP_MARK: | case OP_MARK: |
6630 | PUSH_FALLBACK_NOVALUE(sizeof(fallback_common), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); |
6631 | SLJIT_ASSERT(common->mark_ptr != 0); | SLJIT_ASSERT(common->mark_ptr != 0); |
6632 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); |
6633 | allocate_stack(common, 1); | allocate_stack(common, 1); |
# | Line 5826 while (cc < ccend) | Line 6640 while (cc < ccend) |
6640 | break; | break; |
6641 | ||
6642 | case OP_COMMIT: | case OP_COMMIT: |
6643 | PUSH_FALLBACK_NOVALUE(sizeof(fallback_common), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); |
6644 | cc += 1; | cc += 1; |
6645 | break; | break; |
6646 | ||
6647 | case OP_FAIL: | case OP_FAIL: |
6648 | case OP_ACCEPT: | case OP_ACCEPT: |
6649 | case OP_ASSERT_ACCEPT: | case OP_ASSERT_ACCEPT: |
6650 | cc = compile_fail_accept_hotpath(common, cc, parent); | cc = compile_fail_accept_matchingpath(common, cc, parent); |
6651 | break; | break; |
6652 | ||
6653 | case OP_CLOSE: | case OP_CLOSE: |
6654 | cc = compile_close_hotpath(common, cc); | cc = compile_close_matchingpath(common, cc); |
6655 | break; | break; |
6656 | ||
6657 | case OP_SKIPZERO: | case OP_SKIPZERO: |
# | Line 5854 while (cc < ccend) | Line 6668 while (cc < ccend) |
6668 | SLJIT_ASSERT(cc == ccend); | SLJIT_ASSERT(cc == ccend); |
6669 | } | } |
6670 | ||
6671 | #undef PUSH_FALLBACK | #undef PUSH_BACKTRACK |
6672 | #undef PUSH_FALLBACK_NOVALUE | #undef PUSH_BACKTRACK_NOVALUE |
6673 | #undef FALLBACK_AS | #undef BACKTRACK_AS |
6674 | ||
6675 | #define COMPILE_FALLBACKPATH(current) \ | #define COMPILE_BACKTRACKINGPATH(current) \ |
6676 | do \ | do \ |
6677 | { \ | { \ |
6678 | compile_fallbackpath(common, (current)); \ | compile_backtrackingpath(common, (current)); \ |
6679 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ |
6680 | return; \ | return; \ |
6681 | } \ | } \ |
# | Line 5869 SLJIT_ASSERT(cc == ccend); | Line 6683 SLJIT_ASSERT(cc == ccend); |
6683 | ||
6684 | #define CURRENT_AS(type) ((type *)current) | #define CURRENT_AS(type) ((type *)current) |
6685 | ||
6686 | static void compile_iterator_fallbackpath(compiler_common *common, struct fallback_common *current) | static void compile_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
6687 | { | { |
6688 | DEFINE_COMPILER; | DEFINE_COMPILER; |
6689 | pcre_uchar *cc = current->cc; | pcre_uchar *cc = current->cc; |
# | Line 5878 pcre_uchar type; | Line 6692 pcre_uchar type; |
6692 | int arg1 = -1, arg2 = -1; | int arg1 = -1, arg2 = -1; |
6693 | struct sljit_label *label = NULL; | struct sljit_label *label = NULL; |
6694 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
6695 | jump_list *jumplist = NULL; | |
6696 | int localptr = PRIV_DATA(cc); | |
6697 | int base = (localptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_LOCALS_REG); | |
6698 | int offset0 = (localptr == 0) ? STACK(0) : localptr; | |
6699 | int offset1 = (localptr == 0) ? STACK(1) : localptr + (int)sizeof(sljit_w); | |
6700 | ||
6701 | cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL); | cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL); |
6702 | ||
# | Line 5889 switch(opcode) | Line 6708 switch(opcode) |
6708 | case OP_CRRANGE: | case OP_CRRANGE: |
6709 | if (type == OP_ANYNL || type == OP_EXTUNI) | if (type == OP_ANYNL || type == OP_EXTUNI) |
6710 | { | { |
6711 | set_jumps(current->topfallbacks, LABEL()); | SLJIT_ASSERT(localptr == 0); |
6712 | set_jumps(current->topbacktracks, LABEL()); | |
6713 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
6714 | free_stack(common, 1); | free_stack(common, 1); |
6715 | 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)->matchingpath); |
6716 | } | } |
6717 | else | else |
6718 | { | { |
6719 | if (opcode == OP_STAR || opcode == OP_UPTO) |