/[pcre]/code/trunk/pcre_jit_compile.c
ViewVC logotype

Contents of /code/trunk/pcre_jit_compile.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 695 - (hide annotations) (download)
Sat Sep 17 06:05:38 2011 UTC (21 months ago) by zherczeg
File MIME type: text/plain
File size: 198033 byte(s)
Swap MAX_INDEX and CALL_COUNT, since CALL_COUNT is used far more frequently so it should be a register. 5% progress on a 64 bit x86 machine.
1 ph10 664 /*************************************************
2     * Perl-Compatible Regular Expressions *
3     *************************************************/
4    
5     /* PCRE is a library of functions to support regular expressions whose syntax
6     and semantics are as close as possible to those of the Perl 5 language.
7    
8     Written by Philip Hazel
9     Copyright (c) 1997-2008 University of Cambridge
10    
11     The machine code generator part (this module) was written by Zoltan Herczeg
12     Copyright (c) 2010-2011
13    
14     -----------------------------------------------------------------------------
15     Redistribution and use in source and binary forms, with or without
16     modification, are permitted provided that the following conditions are met:
17    
18     * Redistributions of source code must retain the above copyright notice,
19     this list of conditions and the following disclaimer.
20    
21     * Redistributions in binary form must reproduce the above copyright
22     notice, this list of conditions and the following disclaimer in the
23     documentation and/or other materials provided with the distribution.
24    
25     * Neither the name of the University of Cambridge nor the names of its
26     contributors may be used to endorse or promote products derived from
27     this software without specific prior written permission.
28    
29     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32     ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39     POSSIBILITY OF SUCH DAMAGE.
40     -----------------------------------------------------------------------------
41     */
42    
43     #ifdef HAVE_CONFIG_H
44     #include "config.h"
45     #endif
46    
47     #include "pcre_internal.h"
48    
49     #ifdef SUPPORT_JIT
50    
51     /* All-in-one: Since we use the JIT compiler only from here,
52     we just include it. This way we don't need to touch the build
53     system files. */
54    
55     #define SLJIT_CONFIG_AUTO 1
56     #define SLJIT_VERBOSE 0
57     #define SLJIT_DEBUG 0
58    
59     #include "sljit/sljitLir.c"
60    
61     #if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
62     #error "Unsupported architecture"
63     #endif
64    
65     /* Allocate memory on the stack. Fast, but limited size. */
66     #define LOCAL_SPACE_SIZE 32768
67    
68     #define STACK_GROWTH_RATE 8192
69    
70     /* Enable to check that the allocation could destroy temporaries. */
71     #if defined SLJIT_DEBUG && SLJIT_DEBUG
72     #define DESTROY_REGISTERS 1
73     #endif
74    
75     /*
76     Short summary about the backtracking mechanism empolyed by the jit code generator:
77    
78     The code generator follows the recursive nature of the PERL compatible regular
79     expressions. The basic blocks of regular expressions are condition checkers
80     whose execute different commands depending on the result of the condition check.
81     The relationship between the operators can be horizontal (concatenation) and
82     vertical (sub-expression) (See struct fallback_common for more details).
83    
84     'ab' - 'a' and 'b' regexps are concatenated
85     'a+' - 'a' is the sub-expression of the '+' operator
86    
87     The condition checkers are boolean (true/false) checkers. Machine code is generated
88     for the checker itself and for the actions depending on the result of the checker.
89     The 'true' case is called as the hot path (expected path), and the other is called as
90     the 'fallback' path. Branch instructions are expesive for all CPUs, so we avoid taken
91     branches on the hot path.
92    
93     Greedy star operator (*) :
94     Hot path: match happens.
95     Fallback path: match failed.
96     Non-greedy star operator (*?) :
97     Hot path: no need to perform a match.
98     Fallback path: match is required.
99    
100     The following example shows how the code generated for a capturing bracket
101     with two alternatives. Let A, B, C, D are arbirary regular expressions, and
102     we have the following regular expression:
103    
104     A(B|C)D
105    
106     The generated code will be the following:
107    
108     A hot path
109     '(' hot path (pushing arguments to the stack)
110     B hot path
111     ')' hot path (pushing arguments to the stack)
112     D hot path
113     return with successful match
114    
115     D fallback path
116     ')' fallback path (If we arrived from "C" jump to the fallback of "C")
117     B fallback path
118     C expected path
119     jump to D hot path
120     C fallback path
121     A fallback path
122 ph10 691
123 ph10 664 Notice, that the order of fallback code paths are the opposite of the fast
124     code paths. In this way the topmost value on the stack is always belong
125     to the current fallback code path. The fallback code path must check
126     whether there is a next alternative. If so, it needs to jump back to
127     the hot path eventually. Otherwise it needs to clear out its own stack
128     frame and continue the execution on the fallback code paths.
129     */
130    
131     /*
132     Saved stack frames:
133    
134     Atomic blocks and asserts require reloading the values of local variables
135     when the fallback mechanism performed. Because of OP_RECURSE, the locals
136     are not necessarly known in compile time, thus we need a dynamic restore
137     mechanism.
138    
139     The stack frames are stored in a chain list, and have the following format:
140     ([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]
141    
142     Thus we can restore the locals to a particular point in the stack.
143     */
144    
145     typedef struct jit_arguments {
146     /* Pointers first. */
147     struct sljit_stack *stack;
148     PCRE_SPTR str;
149     PCRE_SPTR begin;
150     PCRE_SPTR end;
151     int *offsets;
152     uschar *ptr;
153     /* Everything else after. */
154     int offsetcount;
155 ph10 677 int calllimit;
156 ph10 664 uschar notbol;
157     uschar noteol;
158     uschar notempty;
159     uschar notempty_atstart;
160     } jit_arguments;
161    
162     typedef struct executable_function {
163     void *executable_func;
164     pcre_jit_callback callback;
165     void *userdata;
166     } executable_function;
167    
168     typedef struct jump_list {
169     struct sljit_jump *jump;
170     struct jump_list *next;
171     } jump_list;
172    
173     enum stub_types { stack_alloc, max_index };
174    
175     typedef struct stub_list {
176     enum stub_types type;
177     int data;
178     struct sljit_jump *start;
179     struct sljit_label *leave;
180     struct stub_list *next;
181     } stub_list;
182    
183     typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);
184    
185     /* The following structure is the key data type for the recursive
186     code generator. It is allocated by compile_hotpath, and contains
187     the aguments for compile_fallbackpath. Must be the first member
188     of its descendants. */
189     typedef struct fallback_common {
190     /* Concatenation stack. */
191     struct fallback_common *prev;
192     jump_list *nextfallbacks;
193     /* Internal stack (for component operators). */
194     struct fallback_common *top;
195     jump_list *topfallbacks;
196     /* Opcode pointer. */
197     uschar *cc;
198     } fallback_common;
199    
200     typedef struct assert_fallback {
201     fallback_common common;
202     jump_list *condfailed;
203     /* Less than 0 (-1) if a frame is not needed. */
204     int framesize;
205     /* Points to our private memory word on the stack. */
206     int localptr;
207     /* For iterators. */
208     struct sljit_label *hotpath;
209     } assert_fallback;
210    
211     typedef struct bracket_fallback {
212     fallback_common common;
213     /* Where to coninue if an alternative is successfully matched. */
214     struct sljit_label *althotpath;
215     /* For rmin and rmax iterators. */
216     struct sljit_label *recursivehotpath;
217     /* For greedy ? operator. */
218     struct sljit_label *zerohotpath;
219     /* Contains the branches of a failed condition. */
220     union {
221     /* Both for OP_COND, OP_SCOND. */
222     jump_list *condfailed;
223     assert_fallback *assert;
224     /* For OP_ONCE. -1 if not needed. */
225     int framesize;
226     } u;
227     /* Points to our private memory word on the stack. */
228     int localptr;
229     } bracket_fallback;
230    
231     typedef struct bracketpos_fallback {
232     fallback_common common;
233     /* Points to our private memory word on the stack. */
234     int localptr;
235     /* Reverting stack is needed. */
236     int framesize;
237     /* Allocated stack size. */
238     int stacksize;
239     } bracketpos_fallback;
240    
241     typedef struct braminzero_fallback {
242     fallback_common common;
243     struct sljit_label *hotpath;
244     } braminzero_fallback;
245    
246     typedef struct iterator_fallback {
247     fallback_common common;
248     /* Next iteration. */
249     struct sljit_label *hotpath;
250     } iterator_fallback;
251    
252     typedef struct recurse_entry {
253     struct recurse_entry *next;
254     /* Contains the function entry. */
255     struct sljit_label *entry;
256     /* Collects the calls until the function is not created. */
257     jump_list *calls;
258     /* Points to the starting opcode. */
259     int start;
260     } recurse_entry;
261    
262     typedef struct recurse_fallback {
263     fallback_common common;
264     } recurse_fallback;
265    
266     typedef struct compiler_common {
267     struct sljit_compiler *compiler;
268     uschar *start;
269     int localsize;
270     int *localptrs;
271     const uschar *fcc;
272     sljit_w lcc;
273     int cbraptr;
274     int nltype;
275     int newline;
276     int bsr_nltype;
277     int endonly;
278     sljit_w ctypes;
279     struct sljit_label *acceptlabel;
280     stub_list *stubs;
281     recurse_entry *entries;
282     recurse_entry *currententry;
283     jump_list *accept;
284 ph10 677 jump_list *calllimit;
285 ph10 664 jump_list *stackalloc;
286     jump_list *revertframes;
287     jump_list *wordboundary;
288     jump_list *anynewline;
289     jump_list *hspace;
290     jump_list *vspace;
291     jump_list *casefulcmp;
292     jump_list *caselesscmp;
293     BOOL jscript_compat;
294     #ifdef SUPPORT_UTF8
295     BOOL utf8;
296     #ifdef SUPPORT_UCP
297     BOOL useucp;
298     #endif
299     jump_list *utf8readchar;
300     jump_list *utf8readtype8;
301     #endif
302     #ifdef SUPPORT_UCP
303     jump_list *getucd;
304     #endif
305     } compiler_common;
306    
307     /* For byte_sequence_compare. */
308    
309     typedef struct compare_context {
310     int length;
311     int sourcereg;
312     #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
313     int byteptr;
314     union {
315     int asint;
316     short asshort;
317     sljit_ub asbyte;
318     sljit_ub asbytes[4];
319     } c;
320     union {
321     int asint;
322     short asshort;
323     sljit_ub asbyte;
324     sljit_ub asbytes[4];
325     } oc;
326     #endif
327     } compare_context;
328    
329     enum {
330     frame_end = 0,
331     frame_setmaxindex = -1,
332     frame_setstrbegin = -2
333     };
334    
335     /* Used for accessing the elements of the stack. */
336     #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w))
337    
338     #define TMP1 SLJIT_TEMPORARY_REG1
339     #define TMP2 SLJIT_TEMPORARY_REG3
340     #define TMP3 SLJIT_TEMPORARY_EREG2
341     #define STR_PTR SLJIT_GENERAL_REG1
342     #define STR_END SLJIT_GENERAL_REG2
343     #define STACK_TOP SLJIT_TEMPORARY_REG2
344     #define STACK_LIMIT SLJIT_GENERAL_REG3
345     #define ARGUMENTS SLJIT_GENERAL_EREG1
346 zherczeg 695 #define CALL_COUNT SLJIT_GENERAL_EREG2
347 ph10 664 #define RETURN_ADDR SLJIT_TEMPORARY_EREG1
348    
349     /* Locals layout. */
350     /* These two locals can be used by the current opcode. */
351     #define LOCALS0 (0 * sizeof(sljit_w))
352     #define LOCALS1 (1 * sizeof(sljit_w))
353     /* Two local variables for possessive quantifiers (char1 cannot use them). */
354     #define POSSESSIVE0 (2 * sizeof(sljit_w))
355     #define POSSESSIVE1 (3 * sizeof(sljit_w))
356     /* Head of the saved local variables */
357     #define LOCALS_HEAD (4 * sizeof(sljit_w))
358     /* Head of the last recursion. */
359     #define RECURSIVE_HEAD (5 * sizeof(sljit_w))
360 ph10 677 /* Number of recursions. */
361 zherczeg 695 #define MAX_INDEX (6 * sizeof(sljit_w))
362 ph10 677 /* Max limit of recursions. */
363     #define CALL_LIMIT (7 * sizeof(sljit_w))
364 ph10 664 /* Last known position of the requested byte. */
365 ph10 677 #define REQ_BYTE_PTR (8 * sizeof(sljit_w))
366 ph10 664 /* End pointer of the first line. */
367 ph10 677 #define FIRSTLINE_END (9 * sizeof(sljit_w))
368 ph10 664 /* The output vector is stored on the stack, and contains pointers
369     to characters. The vector data is divided into two groups: the first
370     group contains the start / end character pointers, and the second is
371     the start pointers when the end of the capturing group has not yet reached. */
372 ph10 677 #define OVECTOR_START (10 * sizeof(sljit_w))
373 ph10 664 #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w))
374     #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w))
375     #define PRIV(cc) (common->localptrs[(cc) - common->start])
376    
377     /* Shortcuts. */
378     #define DEFINE_COMPILER \
379     struct sljit_compiler *compiler = common->compiler
380     #define OP1(op, dst, dstw, src, srcw) \
381     sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
382     #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
383     sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
384     #define LABEL() \
385     sljit_emit_label(compiler)
386     #define JUMP(type) \
387     sljit_emit_jump(compiler, (type))
388     #define JUMPTO(type, label) \
389     sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
390     #define JUMPHERE(jump) \
391     sljit_set_label((jump), sljit_emit_label(compiler))
392     #define CMP(type, src1, src1w, src2, src2w) \
393     sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
394     #define CMPTO(type, src1, src1w, src2, src2w, label) \
395     sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
396     #define COND_VALUE(op, dst, dstw, type) \
397     sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))
398    
399     static uschar* bracketend(uschar* cc)
400     {
401     SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
402     do cc += GET(cc, 1); while (*cc == OP_ALT);
403     SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
404     cc += 1 + LINK_SIZE;
405     return cc;
406     }
407    
408 ph10 691 /* Functions whose might need modification for all new supported opcodes:
409 ph10 664 next_opcode
410     get_localspace
411     set_localptrs
412     get_framesize
413     init_frame
414     get_localsize
415     copy_locals
416     compile_hotpath
417     compile_fallbackpath
418     */
419    
420     static uschar *next_opcode(compiler_common *common, uschar *cc)
421     {
422     SLJIT_UNUSED_ARG(common);
423     switch(*cc)
424     {
425     case OP_SOD:
426     case OP_SOM:
427     case OP_SET_SOM:
428     case OP_NOT_WORD_BOUNDARY:
429     case OP_WORD_BOUNDARY:
430     case OP_NOT_DIGIT:
431     case OP_DIGIT:
432     case OP_NOT_WHITESPACE:
433     case OP_WHITESPACE:
434     case OP_NOT_WORDCHAR:
435     case OP_WORDCHAR:
436     case OP_ANY:
437     case OP_ALLANY:
438     case OP_ANYNL:
439     case OP_NOT_HSPACE:
440     case OP_HSPACE:
441     case OP_NOT_VSPACE:
442     case OP_VSPACE:
443     case OP_EXTUNI:
444     case OP_EODN:
445     case OP_EOD:
446     case OP_CIRC:
447     case OP_CIRCM:
448     case OP_DOLL:
449     case OP_DOLLM:
450     case OP_TYPESTAR:
451     case OP_TYPEMINSTAR:
452     case OP_TYPEPLUS:
453     case OP_TYPEMINPLUS:
454     case OP_TYPEQUERY:
455     case OP_TYPEMINQUERY:
456     case OP_TYPEPOSSTAR:
457     case OP_TYPEPOSPLUS:
458     case OP_TYPEPOSQUERY:
459     case OP_CRSTAR:
460     case OP_CRMINSTAR:
461     case OP_CRPLUS:
462     case OP_CRMINPLUS:
463     case OP_CRQUERY:
464     case OP_CRMINQUERY:
465     case OP_DEF:
466     case OP_BRAZERO:
467     case OP_BRAMINZERO:
468     case OP_BRAPOSZERO:
469     case OP_FAIL:
470     case OP_ACCEPT:
471     case OP_ASSERT_ACCEPT:
472     case OP_SKIPZERO:
473     return cc + 1;
474    
475     case OP_CHAR:
476     case OP_CHARI:
477     case OP_NOT:
478     case OP_NOTI:
479    
480     case OP_STAR:
481     case OP_MINSTAR:
482     case OP_PLUS:
483     case OP_MINPLUS:
484     case OP_QUERY:
485     case OP_MINQUERY:
486     case OP_POSSTAR:
487     case OP_POSPLUS:
488     case OP_POSQUERY:
489     case OP_STARI:
490     case OP_MINSTARI:
491     case OP_PLUSI:
492     case OP_MINPLUSI:
493     case OP_QUERYI:
494     case OP_MINQUERYI:
495     case OP_POSSTARI:
496     case OP_POSPLUSI:
497     case OP_POSQUERYI:
498     case OP_NOTSTAR:
499     case OP_NOTMINSTAR:
500     case OP_NOTPLUS:
501     case OP_NOTMINPLUS:
502     case OP_NOTQUERY:
503     case OP_NOTMINQUERY:
504     case OP_NOTPOSSTAR:
505     case OP_NOTPOSPLUS:
506     case OP_NOTPOSQUERY:
507     case OP_NOTSTARI:
508     case OP_NOTMINSTARI:
509     case OP_NOTPLUSI:
510     case OP_NOTMINPLUSI:
511     case OP_NOTQUERYI:
512     case OP_NOTMINQUERYI:
513     case OP_NOTPOSSTARI:
514     case OP_NOTPOSPLUSI:
515     case OP_NOTPOSQUERYI:
516     cc += 2;
517     #ifdef SUPPORT_UTF8
518     if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
519     #endif
520     return cc;
521    
522     case OP_UPTO:
523     case OP_MINUPTO:
524     case OP_EXACT:
525     case OP_POSUPTO:
526     case OP_UPTOI:
527     case OP_MINUPTOI:
528     case OP_EXACTI:
529     case OP_POSUPTOI:
530     case OP_NOTUPTO:
531     case OP_NOTMINUPTO:
532     case OP_NOTEXACT:
533     case OP_NOTPOSUPTO:
534     case OP_NOTUPTOI:
535     case OP_NOTMINUPTOI:
536     case OP_NOTEXACTI:
537     case OP_NOTPOSUPTOI:
538     cc += 4;
539     #ifdef SUPPORT_UTF8
540     if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
541     #endif
542     return cc;
543    
544     case OP_NOTPROP:
545     case OP_PROP:
546     case OP_TYPEUPTO:
547     case OP_TYPEMINUPTO:
548     case OP_TYPEEXACT:
549     case OP_TYPEPOSUPTO:
550     case OP_REF:
551     case OP_REFI:
552     case OP_CREF:
553     case OP_CLOSE:
554     cc += 3;
555     return cc;
556    
557     case OP_CRRANGE:
558     case OP_CRMINRANGE:
559     return cc + 5;
560    
561     case OP_CLASS:
562     case OP_NCLASS:
563     return cc + 33;
564    
565     #ifdef SUPPORT_UTF8
566     case OP_XCLASS:
567     return cc + GET(cc, 1);
568     #endif
569    
570     case OP_RECURSE:
571     case OP_ASSERT:
572     case OP_ASSERT_NOT:
573     case OP_ASSERTBACK:
574     case OP_ASSERTBACK_NOT:
575     case OP_REVERSE:
576     case OP_ONCE:
577     case OP_BRA:
578     case OP_BRAPOS:
579     case OP_COND:
580     case OP_SBRA:
581     case OP_SBRAPOS:
582     case OP_SCOND:
583     case OP_ALT:
584     case OP_KET:
585     case OP_KETRMAX:
586     case OP_KETRMIN:
587     case OP_KETRPOS:
588     return cc + 1 + LINK_SIZE;
589    
590     case OP_CBRA:
591     case OP_CBRAPOS:
592     case OP_SCBRA:
593     case OP_SCBRAPOS:
594     return cc + 1 + LINK_SIZE + 2;
595    
596     default:
597     return NULL;
598     }
599     }
600    
601     static int get_localspace(compiler_common *common, uschar *cc, uschar *ccend)
602     {
603     int localspace = 0;
604     uschar *alternative;
605     /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
606     while (cc < ccend)
607     {
608     switch(*cc)
609     {
610     case OP_ASSERT:
611     case OP_ASSERT_NOT:
612     case OP_ASSERTBACK:
613     case OP_ASSERTBACK_NOT:
614     case OP_ONCE:
615     case OP_BRAPOS:
616     case OP_SBRA:
617     case OP_SBRAPOS:
618     case OP_SCOND:
619     localspace += sizeof(sljit_w);
620     cc += 1 + LINK_SIZE;
621     break;
622    
623     case OP_CBRAPOS:
624     case OP_SCBRAPOS:
625     localspace += sizeof(sljit_w);
626     cc += 1 + LINK_SIZE + 2;
627     break;
628    
629     case OP_COND:
630     /* Might be a hidden SCOND. */
631     alternative = cc + GET(cc, 1);
632     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
633     localspace += sizeof(sljit_w);
634     cc += 1 + LINK_SIZE;
635     break;
636    
637     default:
638     cc = next_opcode(common, cc);
639     if (cc == NULL)
640     return -1;
641     break;
642     }
643     }
644     return localspace;
645     }
646    
647     static void set_localptrs(compiler_common *common, int localptr, uschar *ccend)
648     {
649     uschar *cc = common->start;
650     uschar *alternative;
651     while (cc < ccend)
652     {
653     switch(*cc)
654     {
655     case OP_ASSERT:
656     case OP_ASSERT_NOT:
657     case OP_ASSERTBACK:
658     case OP_ASSERTBACK_NOT:
659     case OP_ONCE:
660     case OP_BRAPOS:
661     case OP_SBRA:
662     case OP_SBRAPOS:
663     case OP_SCOND:
664     common->localptrs[cc - common->start] = localptr;
665     localptr += sizeof(sljit_w);
666     cc += 1 + LINK_SIZE;
667     break;
668    
669     case OP_CBRAPOS:
670     case OP_SCBRAPOS:
671     common->localptrs[cc - common->start] = localptr;
672     localptr += sizeof(sljit_w);
673     cc += 1 + LINK_SIZE + 2;
674     break;
675    
676     case OP_COND:
677     /* Might be a hidden SCOND. */
678     alternative = cc + GET(cc, 1);
679     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
680     {
681     common->localptrs[cc - common->start] = localptr;
682     localptr += sizeof(sljit_w);
683     }
684     cc += 1 + LINK_SIZE;
685     break;
686    
687     default:
688     cc = next_opcode(common, cc);
689     SLJIT_ASSERT(cc != NULL);
690     break;
691     }
692     }
693     }
694    
695     /* Returns with -1 if no need for frame. */
696     static int get_framesize(compiler_common *common, uschar *cc, BOOL recursive)
697     {
698     uschar *ccend = bracketend(cc);
699     uschar *end;
700     int length = 0;
701     BOOL possessive = FALSE;
702     BOOL needs_frame = FALSE;
703     BOOL needs_maxindex = FALSE;
704     BOOL setsom_found = FALSE;
705    
706     if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
707     {
708     length = 3 + 2;
709     needs_maxindex = TRUE;
710     possessive = TRUE;
711     }
712    
713     cc = next_opcode(common, cc);
714     SLJIT_ASSERT(cc != NULL);
715     while (cc < ccend)
716     switch(*cc)
717     {
718     case OP_SET_SOM:
719     case OP_RECURSE:
720     if (!setsom_found)
721     {
722     length += 2;
723     setsom_found = TRUE;
724     }
725     cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;
726     break;
727    
728     case OP_ASSERT:
729     case OP_ASSERT_NOT:
730     case OP_ASSERTBACK:
731     case OP_ASSERTBACK_NOT:
732     case OP_ONCE:
733     if (needs_frame || length > 0)
734     {
735     cc = bracketend(cc);
736     break;
737     }
738     /* Check whether a frame must be created. */
739     end = bracketend(cc);
740     while (cc < end)
741     {
742     if (*cc == OP_SET_SOM || *cc == OP_CBRA || *cc == OP_CBRAPOS
743     || *cc == OP_SCBRA || *cc == OP_SCBRAPOS || *cc == OP_RECURSE)
744     needs_frame = TRUE;
745     cc = next_opcode(common, cc);
746     SLJIT_ASSERT(cc != NULL);
747     }
748     break;
749    
750     case OP_CBRA:
751     case OP_CBRAPOS:
752     case OP_SCBRA:
753     case OP_SCBRAPOS:
754     if (!needs_maxindex)
755     {
756     needs_maxindex = TRUE;
757     length += 2;
758     }
759     length += 3;
760     cc += 1 + LINK_SIZE + 2;
761     break;
762    
763     default:
764     cc = next_opcode(common, cc);
765     SLJIT_ASSERT(cc != NULL);
766     break;
767     }
768    
769     /* Possessive quantifiers can use a special case. */
770     if (SLJIT_UNLIKELY(possessive) && !needs_frame && length == 3 + 2)
771     return -1;
772    
773     if (length > 0)
774     return length + 2;
775     return needs_frame ? 0 : -1;
776     }
777    
778     static void init_frame(compiler_common *common, uschar *cc, int stackpos, int stacktop, BOOL recursive)
779     {
780     /* TMP2 must contain STACK_TOP - (-STACK(stackpos)) */
781     DEFINE_COMPILER;
782     uschar *ccend = bracketend(cc);
783     BOOL needs_maxindex = FALSE;
784     BOOL setsom_found = FALSE;
785     int offset;
786    
787     if (stackpos < stacktop)
788     {
789     SLJIT_ASSERT(stackpos + 1 == stacktop);
790     return;
791     }
792    
793     stackpos = STACK(stackpos);
794     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD);
795     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0);
796     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacktop), TMP1, 0);
797    
798     if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS))
799     cc = next_opcode(common, cc);
800     SLJIT_ASSERT(cc != NULL);
801     while (cc < ccend)
802     switch(*cc)
803     {
804     case OP_SET_SOM:
805     case OP_RECURSE:
806     if (!setsom_found)
807     {
808     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
809     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin);
810     stackpos += (int)sizeof(sljit_w);
811     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
812     stackpos += (int)sizeof(sljit_w);
813     setsom_found = TRUE;
814     }
815     cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;
816     break;
817    
818     case OP_ASSERT:
819     case OP_ASSERT_NOT:
820     case OP_ASSERTBACK:
821     case OP_ASSERTBACK_NOT:
822     case OP_ONCE:
823     cc = bracketend(cc);
824     break;
825    
826     case OP_CBRA:
827     case OP_CBRAPOS:
828     case OP_SCBRA:
829     case OP_SCBRAPOS:
830     if (!needs_maxindex)
831     {
832 zherczeg 695 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), MAX_INDEX);
833 ph10 664 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmaxindex);
834     stackpos += (int)sizeof(sljit_w);
835 zherczeg 695 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
836 ph10 664 stackpos += (int)sizeof(sljit_w);
837     needs_maxindex = TRUE;
838     }
839     offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
840     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
841     stackpos += (int)sizeof(sljit_w);
842     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
843     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
844     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
845     stackpos += (int)sizeof(sljit_w);
846     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
847     stackpos += (int)sizeof(sljit_w);
848    
849     cc += 1 + LINK_SIZE + 2;
850     break;
851    
852     default:
853     cc = next_opcode(common, cc);
854     SLJIT_ASSERT(cc != NULL);
855     break;
856     }
857    
858     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end);
859     SLJIT_ASSERT(stackpos == STACK(stacktop + 1));
860     }
861    
862     static SLJIT_INLINE int get_localsize(compiler_common *common, uschar *cc, uschar *ccend)
863     {
864     int localsize = 2;
865     uschar *alternative;
866     /* Calculate the sum of the local variables. */
867     while (cc < ccend)
868     {
869     switch(*cc)
870     {
871     case OP_ASSERT:
872     case OP_ASSERT_NOT:
873     case OP_ASSERTBACK:
874     case OP_ASSERTBACK_NOT:
875     case OP_ONCE:
876     case OP_BRAPOS:
877     case OP_SBRA:
878     case OP_SBRAPOS:
879     case OP_SCOND:
880     localsize++;
881     cc += 1 + LINK_SIZE;
882     break;
883    
884     case OP_CBRA:
885     case OP_SCBRA:
886     localsize++;
887     cc += 1 + LINK_SIZE + 2;
888     break;
889    
890     case OP_CBRAPOS:
891     case OP_SCBRAPOS:
892     localsize += 2;
893     cc += 1 + LINK_SIZE + 2;
894     break;
895    
896     case OP_COND:
897     /* Might be a hidden SCOND. */
898     alternative = cc + GET(cc, 1);
899     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
900     localsize++;
901     cc += 1 + LINK_SIZE;
902     break;
903    
904     default:
905     cc = next_opcode(common, cc);
906     SLJIT_ASSERT(cc != NULL);
907     break;
908     }
909     }
910     SLJIT_ASSERT(cc == ccend);
911     return localsize;
912     }
913    
914     static void copy_locals(compiler_common *common, uschar *cc, uschar *ccend,
915     BOOL save, int stackptr, int stacktop)
916     {
917     DEFINE_COMPILER;
918     int srcw[2];
919     int count;
920     BOOL tmp1next = TRUE;
921     BOOL tmp1empty = TRUE;
922     BOOL tmp2empty = TRUE;
923     uschar *alternative;
924     enum {
925     start,
926     loop,
927     end
928     } status;
929    
930     status = save ? start : loop;
931     stackptr = STACK(stackptr - 2);
932     stacktop = STACK(stacktop - 1);
933    
934     if (!save)
935     {
936     stackptr += sizeof(sljit_w);
937     if (stackptr < stacktop)
938     {
939     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
940     stackptr += sizeof(sljit_w);
941     tmp1empty = FALSE;
942     }
943     if (stackptr < stacktop)
944     {
945     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
946     stackptr += sizeof(sljit_w);
947     tmp2empty = FALSE;
948     }
949     /* The tmp1next must be TRUE in either way. */
950     }
951    
952     while (status != end)
953     {
954     count = 0;
955     switch(status)
956     {
957     case start:
958     SLJIT_ASSERT(save);
959     count = 1;
960     srcw[0] = RECURSIVE_HEAD;
961     status = loop;
962     break;
963    
964     case loop:
965     if (cc >= ccend)
966     {
967     status = end;
968     break;
969     }
970    
971     switch(*cc)
972     {
973     case OP_ASSERT:
974     case OP_ASSERT_NOT:
975     case OP_ASSERTBACK:
976     case OP_ASSERTBACK_NOT:
977     case OP_ONCE:
978     case OP_BRAPOS:
979     case OP_SBRA:
980     case OP_SBRAPOS:
981     case OP_SCOND:
982     count = 1;
983     srcw[0] = PRIV(cc);
984     SLJIT_ASSERT(srcw[0] != 0);
985     cc += 1 + LINK_SIZE;
986     break;
987    
988     case OP_CBRA:
989     case OP_SCBRA:
990     count = 1;
991     srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
992     cc += 1 + LINK_SIZE + 2;
993     break;
994    
995     case OP_CBRAPOS:
996     case OP_SCBRAPOS:
997     count = 2;
998     srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
999     srcw[0] = PRIV(cc);
1000     SLJIT_ASSERT(srcw[0] != 0);
1001     cc += 1 + LINK_SIZE + 2;
1002     break;
1003    
1004     case OP_COND:
1005     /* Might be a hidden SCOND. */
1006     alternative = cc + GET(cc, 1);
1007     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
1008     {
1009     count = 1;
1010     srcw[0] = PRIV(cc);
1011     SLJIT_ASSERT(srcw[0] != 0);
1012     }
1013     cc += 1 + LINK_SIZE;
1014     break;
1015    
1016     default:
1017     cc = next_opcode(common, cc);
1018     SLJIT_ASSERT(cc != NULL);
1019     break;
1020     }
1021     break;
1022    
1023     case end:
1024     SLJIT_ASSERT_STOP();
1025     break;
1026     }
1027    
1028     while (count > 0)
1029     {
1030     count--;
1031     if (save)
1032     {
1033     if (tmp1next)
1034     {
1035     if (!tmp1empty)
1036     {
1037     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1038     stackptr += sizeof(sljit_w);
1039     }
1040     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
1041     tmp1empty = FALSE;
1042     tmp1next = FALSE;
1043     }
1044     else
1045     {
1046     if (!tmp2empty)
1047     {
1048     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1049     stackptr += sizeof(sljit_w);
1050     }
1051     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
1052     tmp2empty = FALSE;
1053     tmp1next = TRUE;
1054     }
1055     }
1056     else
1057     {
1058     if (tmp1next)
1059     {
1060     SLJIT_ASSERT(!tmp1empty);
1061     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0);
1062     tmp1empty = stackptr >= stacktop;
1063     if (!tmp1empty)
1064     {
1065     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1066     stackptr += sizeof(sljit_w);
1067     }
1068     tmp1next = FALSE;
1069     }
1070     else
1071     {
1072     SLJIT_ASSERT(!tmp2empty);
1073     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0);
1074     tmp2empty = stackptr >= stacktop;
1075     if (!tmp2empty)
1076     {
1077     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1078     stackptr += sizeof(sljit_w);
1079     }
1080     tmp1next = TRUE;
1081     }
1082     }
1083     }
1084     }
1085    
1086     if (save)
1087     {
1088     if (tmp1next)
1089     {
1090     if (!tmp1empty)
1091     {
1092     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1093     stackptr += sizeof(sljit_w);
1094     }
1095     if (!tmp2empty)
1096     {
1097     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1098     stackptr += sizeof(sljit_w);
1099     }
1100     }
1101     else
1102     {
1103     if (!tmp2empty)
1104     {
1105     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1106     stackptr += sizeof(sljit_w);
1107     }
1108     if (!tmp1empty)
1109     {
1110     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1111     stackptr += sizeof(sljit_w);
1112     }
1113     }
1114     }
1115     SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
1116     }
1117    
1118     static SLJIT_INLINE BOOL ispowerof2(unsigned int value)
1119     {
1120     return (value & (value - 1)) == 0;
1121     }
1122    
1123     static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)
1124     {
1125     while (list)
1126     {
1127     /* sljit_set_label is clever enough to do nothing
1128     if either the jump or the label is NULL */
1129     sljit_set_label(list->jump, label);
1130     list = list->next;
1131     }
1132     }
1133    
1134     static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump)
1135     {
1136     jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));
1137     if (list_item)
1138     {
1139     list_item->next = *list;
1140     list_item->jump = jump;
1141     *list = list_item;
1142     }
1143     }
1144    
1145     static void add_stub(compiler_common *common, enum stub_types type, int data, struct sljit_jump *start)
1146     {
1147     DEFINE_COMPILER;
1148     stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list));
1149    
1150     if (list_item)
1151     {
1152     list_item->type = type;
1153     list_item->data = data;
1154     list_item->start = start;
1155     list_item->leave = LABEL();
1156     list_item->next = common->stubs;
1157     common->stubs = list_item;
1158     }
1159     }
1160    
1161     static void flush_stubs(compiler_common *common)
1162     {
1163     DEFINE_COMPILER;
1164     stub_list* list_item = common->stubs;
1165    
1166     while (list_item)
1167     {
1168     JUMPHERE(list_item->start);
1169     switch(list_item->type)
1170     {
1171     case stack_alloc:
1172     add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));
1173     break;
1174    
1175     case max_index:
1176 zherczeg 695 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), MAX_INDEX, SLJIT_IMM, list_item->data);
1177 ph10 664 break;
1178     }
1179     JUMPTO(SLJIT_JUMP, list_item->leave);
1180     list_item = list_item->next;
1181     }
1182     common->stubs = NULL;
1183     }
1184    
1185 ph10 677 static SLJIT_INLINE void decrease_call_count(compiler_common *common)
1186     {
1187     DEFINE_COMPILER;
1188    
1189 zherczeg 695 OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 0, SLJIT_IMM, 1);
1190 ph10 677 add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));
1191     }
1192    
1193 ph10 664 static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
1194     {
1195     /* May destroy all locals and registers except TMP2. */
1196     DEFINE_COMPILER;
1197    
1198     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
1199     #ifdef DESTROY_REGISTERS
1200     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
1201     OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
1202     OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
1203     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0);
1204     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
1205     #endif
1206     add_stub(common, stack_alloc, 0, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0));
1207     }
1208    
1209     static SLJIT_INLINE void free_stack(compiler_common *common, int size)
1210     {
1211     DEFINE_COMPILER;
1212     OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
1213     }
1214    
1215     static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)
1216     {
1217     DEFINE_COMPILER;
1218     struct sljit_label *loop;
1219     int i;
1220     /* At this point we can freely use all temporary registers. */
1221     /* TMP1 returns with begin - 1. */
1222 zherczeg 695 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), MAX_INDEX, SLJIT_IMM, 1);
1223 ph10 664 OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, 1);
1224     if (length < 8)
1225     {
1226     for (i = 0; i < length; i++)
1227     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_TEMPORARY_REG1, 0);
1228     }
1229     else
1230     {
1231     OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START - sizeof(sljit_w));
1232     OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length);
1233     loop = LABEL();
1234     OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0);
1235     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1);
1236     JUMPTO(SLJIT_C_NOT_ZERO, loop);
1237     }
1238     }
1239    
1240     static SLJIT_INLINE void copy_ovector(compiler_common *common)
1241     {
1242     DEFINE_COMPILER;
1243     struct sljit_label *loop;
1244     struct sljit_jump *earlyexit;
1245    
1246     /* At this point we can freely use all registers. */
1247     OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0);
1248     OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));
1249     OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
1250     OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin));
1251     OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START);
1252     /* Unlikely, but possible */
1253     earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0);
1254     loop = LABEL();
1255     OP2(SLJIT_SUB, SLJIT_GENERAL_REG2, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), 0, SLJIT_TEMPORARY_REG1, 0);
1256     OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_GENERAL_REG1, 0, SLJIT_IMM, sizeof(sljit_w));
1257     /* Copy the integer value to the output buffer */
1258     OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_GENERAL_REG2, 0);
1259     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
1260     JUMPTO(SLJIT_C_NOT_ZERO, loop);
1261     JUMPHERE(earlyexit);
1262     }
1263    
1264     static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, uschar* cc)
1265     {
1266     /* Detects if the character has an othercase. */
1267     unsigned int c;
1268    
1269     #ifdef SUPPORT_UTF8
1270     if (common->utf8)
1271     {
1272     GETCHAR(c, cc);
1273     if (c > 127)
1274     {
1275     #ifdef SUPPORT_UCP
1276     return c != UCD_OTHERCASE(c);
1277     #else
1278     return FALSE;
1279     #endif
1280     }
1281     }
1282     else
1283     #endif
1284     c = *cc;
1285     return common->fcc[c] != c;
1286     }
1287    
1288     static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)
1289     {
1290     /* Returns with the othercase. */
1291     #ifdef SUPPORT_UTF8
1292     if (common->utf8 && c > 127)
1293     {
1294     #ifdef SUPPORT_UCP
1295     return UCD_OTHERCASE(c);
1296     #else
1297     return c;
1298     #endif
1299     }
1300     #endif
1301     return common->fcc[c];
1302     }
1303    
1304     static unsigned int char_get_othercase_bit(compiler_common *common, uschar* cc)
1305     {
1306     /* Detects if the character and its othercase has only 1 bit difference. */
1307     unsigned int c, oc, bit;
1308     #ifdef SUPPORT_UTF8
1309     int n;
1310     #endif
1311    
1312     #ifdef SUPPORT_UTF8
1313     if (common->utf8)
1314     {
1315     GETCHAR(c, cc);
1316     if (c <= 127)
1317     oc = common->fcc[c];
1318     else
1319     {
1320     #ifdef SUPPORT_UCP
1321     oc = UCD_OTHERCASE(c);
1322     #else
1323     oc = c;
1324     #endif
1325     }
1326     }
1327     else
1328     {
1329     c = *cc;
1330     oc = common->fcc[c];
1331     }
1332     #else
1333     c = *cc;
1334     oc = common->fcc[c];
1335     #endif
1336    
1337     SLJIT_ASSERT(c != oc);
1338    
1339     bit = c ^ oc;
1340     /* Optimized for English alphabet. */
1341     if (c <= 127 && bit == 0x20)
1342     return (0 << 8) | 0x20;
1343    
1344     /* Since c != oc, they must have at least 1 bit difference. */
1345     if (!ispowerof2(bit))
1346     return 0;
1347    
1348     #ifdef SUPPORT_UTF8
1349     if (common->utf8 && c > 127)
1350     {
1351     n = _pcre_utf8_table4[*cc & 0x3f];
1352     while ((bit & 0x3f) == 0)
1353     {
1354     n--;
1355     bit >>= 6;
1356     }
1357     return (n << 8) | bit;
1358     }
1359     #endif
1360     return (0 << 8) | bit;
1361     }
1362    
1363     static SLJIT_INLINE void check_input_end(compiler_common *common, jump_list **fallbacks)
1364     {
1365     DEFINE_COMPILER;
1366     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
1367     }
1368    
1369     static void read_char(compiler_common *common)
1370     {
1371     /* Reads the character into TMP1, updates STR_PTR.
1372     Does not check STR_END. TMP2 Destroyed. */
1373     DEFINE_COMPILER;
1374     #ifdef SUPPORT_UTF8
1375     struct sljit_jump *jump;
1376     #endif
1377    
1378     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1379     #ifdef SUPPORT_UTF8
1380     if (common->utf8)
1381     {
1382     /* Should not found a value between 128 and 192 here. */
1383     jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 192);
1384     add_jump(compiler, &common->utf8readchar, JUMP(SLJIT_FAST_CALL));
1385     JUMPHERE(jump);
1386     }
1387     #endif
1388     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1389     }
1390    
1391     static void peek_char(compiler_common *common)
1392     {
1393     /* Reads the character into TMP1, keeps STR_PTR.
1394     Does not check STR_END. TMP2 Destroyed. */
1395     DEFINE_COMPILER;
1396     #ifdef SUPPORT_UTF8
1397     struct sljit_jump *jump;
1398     #endif
1399    
1400     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1401     #ifdef SUPPORT_UTF8
1402     if (common->utf8)
1403     {
1404     /* Should not found a value between 128 and 192 here. */
1405     jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 192);
1406     add_jump(compiler, &common->utf8readchar, JUMP(SLJIT_FAST_CALL));
1407     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1408     JUMPHERE(jump);
1409     }
1410     #endif
1411     }
1412    
1413     static void read_char8_type(compiler_common *common)
1414     {
1415     /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
1416     DEFINE_COMPILER;
1417     #ifdef SUPPORT_UTF8
1418     struct sljit_jump *jump;
1419     #endif
1420    
1421     #ifdef SUPPORT_UTF8
1422     if (common->utf8)
1423     {
1424     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
1425     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1426     /* This can be an extra read in some situations, but hopefully
1427     it is a clever early read in most cases. */
1428     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1429     /* Should not found a value between 128 and 192 here. */
1430     jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 192);
1431     add_jump(compiler, &common->utf8readtype8, JUMP(SLJIT_FAST_CALL));
1432     JUMPHERE(jump);
1433     return;
1434     }
1435     #endif
1436     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1437     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1438     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
1439     }
1440    
1441     static void skip_char_back(compiler_common *common)
1442     {
1443     /* Goes one character back. Only affects STR_PTR. Does not check begin. */
1444     DEFINE_COMPILER;
1445     #ifdef SUPPORT_UTF8
1446     struct sljit_label *label;
1447    
1448     if (common->utf8)
1449     {
1450     label = LABEL();
1451     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1452     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1453     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
1454     CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);
1455     return;
1456     }
1457     #endif
1458     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1459     }
1460    
1461     static void check_newlinechar(compiler_common *common, int nltype, jump_list **fallbacks, BOOL jumpiftrue)
1462     {
1463     /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
1464     DEFINE_COMPILER;
1465    
1466     if (nltype == NLTYPE_ANY)
1467     {
1468     add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
1469     add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1470     }
1471     else if (nltype == NLTYPE_ANYCRLF)
1472     {
1473     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR);
1474     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
1475     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
1476     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
1477     add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1478     }
1479     else
1480     {
1481     SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline <= 255);
1482     add_jump(compiler, fallbacks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
1483     }
1484     }
1485    
1486     #ifdef SUPPORT_UTF8
1487     static void do_utf8readchar(compiler_common *common)
1488     {
1489     /* Fast decoding an utf8 character. TMP1 contains the first byte
1490     of the character (>= 192). Return char value in TMP1, length - 1 in TMP2. */
1491     DEFINE_COMPILER;
1492     struct sljit_jump *jump;
1493    
1494     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1495     /* Searching for the first zero. */
1496     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
1497     jump = JUMP(SLJIT_C_NOT_ZERO);
1498     /* 2 byte sequence */
1499     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1500     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1501     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f);
1502     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
1503     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1504     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1505     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
1506     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1507     JUMPHERE(jump);
1508    
1509     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10);
1510     jump = JUMP(SLJIT_C_NOT_ZERO);
1511     /* 3 byte sequence */
1512     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1513     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f);
1514     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12);
1515     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1516     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1517     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1518     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2);
1519     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 2);
1520     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1521     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1522     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 2);
1523     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1524     JUMPHERE(jump);
1525    
1526     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x08);
1527     jump = JUMP(SLJIT_C_NOT_ZERO);
1528     /* 4 byte sequence */
1529     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1530     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07);
1531     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18);
1532     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1533     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
1534     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1535     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2);
1536     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1537     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1538     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1539     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 3);
1540     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 3);
1541     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1542     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1543     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 3);
1544     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1545     JUMPHERE(jump);
1546    
1547     /* 5 byte sequence */
1548     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1549     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x03);
1550     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 24);
1551     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1552     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 18);
1553     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1554     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2);
1555     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1556     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
1557     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1558     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 3);
1559     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1560     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1561     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1562     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 4);
1563     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 4);
1564     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1565     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1566     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 4);
1567     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1568     }
1569    
1570     static void do_utf8readtype8(compiler_common *common)
1571     {
1572     /* Fast decoding an utf8 character type. TMP2 contains the first byte
1573     of the character (>= 192) and TMP1 is destroyed. Return value in TMP1. */
1574     DEFINE_COMPILER;
1575     struct sljit_jump *jump;
1576     struct sljit_jump *compare;
1577    
1578     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1579    
1580     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
1581     jump = JUMP(SLJIT_C_NOT_ZERO);
1582     /* 2 byte sequence */
1583     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1584     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1585     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);
1586     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1587     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
1588     OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
1589     compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
1590     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1591     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1592    
1593     JUMPHERE(compare);
1594     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1595     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1596     JUMPHERE(jump);
1597    
1598     /* We only have types for characters less than 256. */
1599     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)_pcre_utf8_char_sizes);
1600     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1601     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1602     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1603     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1604     }
1605    
1606     #endif
1607    
1608     #ifdef SUPPORT_UCP
1609    
1610     /* UCD_BLOCK_SIZE must be 128 (see the assert below). */
1611     #define UCD_BLOCK_MASK 127
1612     #define UCD_BLOCK_SHIFT 7
1613    
1614     static void do_getucd(compiler_common *common)
1615     {
1616     /* Search the UCD record for the character comes in TMP1.
1617     Returns chartype in TMP1 and UCD offset in TMP2. */
1618     DEFINE_COMPILER;
1619    
1620     SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
1621    
1622     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1623     OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1624     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)_pcre_ucd_stage1);
1625     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
1626     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1627     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
1628     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_stage2);
1629     OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
1630     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, chartype));
1631     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
1632     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1633     }
1634     #endif
1635    
1636     static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline)
1637     {
1638     DEFINE_COMPILER;
1639     struct sljit_label *mainloop;
1640     struct sljit_label *newlinelabel = NULL;
1641     struct sljit_jump *start;
1642     struct sljit_jump *end = NULL;
1643     struct sljit_jump *nl = NULL;
1644     jump_list *newline = NULL;
1645     BOOL newlinecheck = FALSE;
1646     BOOL readbyte = FALSE;
1647    
1648     if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY ||
1649     common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
1650     newlinecheck = TRUE;
1651    
1652     if (firstline)
1653     {
1654     /* Search for the end of the first line. */
1655     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0);
1656     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_END, 0);
1657    
1658     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
1659     {
1660     mainloop = LABEL();
1661     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1662     end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1663     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -1);
1664     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
1665     CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
1666     CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
1667     OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0, SLJIT_IMM, 1);
1668     }
1669     else
1670     {
1671     end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1672     mainloop = LABEL();
1673     /* Continual stores does not cause data dependency. */
1674     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);
1675     read_char(common);
1676     check_newlinechar(common, common->nltype, &newline, TRUE);
1677     CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
1678     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);
1679     set_jumps(newline, LABEL());
1680     }
1681    
1682     JUMPHERE(end);
1683     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
1684     }
1685    
1686     start = JUMP(SLJIT_JUMP);
1687    
1688     if (newlinecheck)
1689     {
1690     newlinelabel = LABEL();
1691     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1692     end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1693     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1694     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
1695     COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1696     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1697     nl = JUMP(SLJIT_JUMP);
1698     }
1699    
1700     mainloop = LABEL();
1701    
1702     /* Increasing the STR_PTR here requires one less jump in the most common case. */
1703     #ifdef SUPPORT_UTF8
1704     if (common->utf8) readbyte = TRUE;
1705     #endif
1706     if (newlinecheck) readbyte = TRUE;
1707    
1708     if (readbyte)
1709     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1710    
1711     if (newlinecheck)
1712     CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);
1713    
1714     #ifdef SUPPORT_UTF8
1715     if (common->utf8)
1716     {
1717     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
1718     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1719     }
1720     else
1721     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1722     #else
1723     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1724     #endif
1725     JUMPHERE(start);
1726    
1727     if (newlinecheck)
1728     {
1729     JUMPHERE(end);
1730     JUMPHERE(nl);
1731     }
1732    
1733     return mainloop;
1734     }
1735    
1736     static SLJIT_INLINE void fast_forward_first_byte(compiler_common *common, pcre_uint16 firstbyte, BOOL firstline)
1737     {
1738     DEFINE_COMPILER;
1739     struct sljit_label *start;
1740     struct sljit_jump *leave;
1741     struct sljit_jump *found;
1742     pcre_uint16 oc, bit;
1743    
1744     if (firstline)
1745     {
1746     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1747     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1748     }
1749    
1750     start = LABEL();
1751     leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1752     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1753    
1754     if ((firstbyte & REQ_CASELESS) == 0)
1755     found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, firstbyte & 0xff);
1756     else
1757     {
1758     firstbyte &= 0xff;
1759     oc = common->fcc[firstbyte];
1760     bit = firstbyte ^ oc;
1761     if (ispowerof2(bit))
1762     {
1763     OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit);
1764     found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, firstbyte | bit);
1765     }
1766     else
1767     {
1768     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, firstbyte);
1769     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
1770     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
1771     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
1772     found = JUMP(SLJIT_C_NOT_ZERO);
1773     }
1774     }
1775    
1776     #ifdef SUPPORT_UTF8
1777     if (common->utf8)
1778     {
1779     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
1780     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1781     }
1782     else
1783     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1784     #else
1785     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1786     #endif
1787     JUMPTO(SLJIT_JUMP, start);
1788     JUMPHERE(found);
1789     JUMPHERE(leave);
1790    
1791     if (firstline)
1792     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1793     }
1794    
1795     static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline)
1796     {
1797     DEFINE_COMPILER;
1798     struct sljit_label *loop;
1799     struct sljit_jump *lastchar;
1800     struct sljit_jump *firstchar;
1801     struct sljit_jump *leave;
1802     struct sljit_jump *foundcr = NULL;
1803     struct sljit_jump *notfoundnl;
1804     jump_list *newline = NULL;
1805    
1806     if (firstline)
1807     {
1808     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1809     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1810     }
1811    
1812     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
1813     {
1814     lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1815     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1816     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1817     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
1818     firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
1819    
1820     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);
1821     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
1822     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL);
1823     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1824    
1825     loop = LABEL();
1826     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1827     leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1828     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -2);
1829     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), -1);
1830     CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);
1831     CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);
1832    
1833     JUMPHERE(leave);
1834     JUMPHERE(firstchar);
1835     JUMPHERE(lastchar);
1836    
1837     if (firstline)
1838     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1839     return;
1840     }
1841    
1842     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1843     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1844     firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
1845     skip_char_back(common);
1846    
1847     loop = LABEL();
1848     read_char(common);
1849     lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1850     if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
1851     foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
1852     check_newlinechar(common, common->nltype, &newline, FALSE);
1853     set_jumps(newline, loop);
1854    
1855     if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
1856     {
1857     leave = JUMP(SLJIT_JUMP);
1858     JUMPHERE(foundcr);
1859     notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1860     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1861     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
1862     COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1863     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1864     JUMPHERE(notfoundnl);
1865     JUMPHERE(leave);
1866     }
1867     JUMPHERE(lastchar);
1868     JUMPHERE(firstchar);
1869    
1870     if (firstline)
1871     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1872     }
1873    
1874     static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline)
1875     {
1876     DEFINE_COMPILER;
1877     struct sljit_label *start;
1878     struct sljit_jump *leave;
1879     struct sljit_jump *found;
1880    
1881     if (firstline)
1882     {
1883     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1884     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1885     }
1886    
1887     start = LABEL();
1888     leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1889     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1890     #ifdef SUPPORT_UTF8
1891     if (common->utf8)
1892     OP1(SLJIT_MOV_UB, TMP3, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
1893     #endif
1894     OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
1895     OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
1896     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits);
1897     OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
1898     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
1899     found = JUMP(SLJIT_C_NOT_ZERO);
1900    
1901     #ifdef SUPPORT_UTF8
1902     if (common->utf8)
1903     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP3, 0);
1904     else
1905     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1906     #else
1907     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1908     #endif
1909     JUMPTO(SLJIT_JUMP, start);
1910     JUMPHERE(found);
1911     JUMPHERE(leave);
1912    
1913     if (firstline)
1914     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1915     }
1916    
1917     static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uint16 reqbyte, BOOL has_firstbyte)
1918     {
1919     DEFINE_COMPILER;
1920     struct sljit_label *loop;
1921     struct sljit_jump *toolong;
1922     struct sljit_jump *alreadyfound;
1923     struct sljit_jump *found;
1924     struct sljit_jump *foundoc = NULL;
1925     struct sljit_jump *notfound;
1926     pcre_uint16 oc, bit;
1927    
1928     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_BYTE_PTR);
1929     OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);
1930     toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0);
1931     alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0);
1932    
1933     if (has_firstbyte)
1934     OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, 1);
1935     else
1936     OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);
1937    
1938     loop = LABEL();
1939     notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0);
1940    
1941     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), 0);
1942     if ((reqbyte & REQ_CASELESS) == 0)
1943     found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte & 0xff);
1944     else
1945     {
1946     reqbyte &= 0xff;
1947     oc = common->fcc[reqbyte];
1948     bit = reqbyte ^ oc;
1949     if (ispowerof2(bit))
1950     {
1951     OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);
1952     found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte | bit);
1953     }
1954     else
1955     {
1956     found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte);
1957     foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc);
1958     }
1959     }
1960     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1961     JUMPTO(SLJIT_JUMP, loop);
1962    
1963     JUMPHERE(found);
1964     if (foundoc)
1965     JUMPHERE(foundoc);
1966     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_BYTE_PTR, TMP1, 0);
1967     JUMPHERE(alreadyfound);
1968     JUMPHERE(toolong);
1969     return notfound;
1970     }
1971    
1972     static void do_revertframes(compiler_common *common)
1973     {
1974     DEFINE_COMPILER;
1975     struct sljit_jump *earlyexit;
1976     struct sljit_jump *jump;
1977     struct sljit_label *mainloop;
1978    
1979     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1980     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD);
1981    
1982     /* Drop frames until we reach STACK_TOP. */
1983     earlyexit = CMP(SLJIT_C_LESS, TMP1, 0, STACK_TOP, 0);
1984     mainloop = LABEL();
1985     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
1986     jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
1987     OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_LOCALS_REG, 0);
1988     OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
1989     OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w));
1990     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w));
1991     JUMPTO(SLJIT_JUMP, mainloop);
1992    
1993     JUMPHERE(jump);
1994     jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
1995     /* End of dropping frames. */
1996     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
1997     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP1, 0);
1998     CMPTO(SLJIT_C_GREATER_EQUAL, TMP1, 0, STACK_TOP, 0, mainloop);
1999     JUMPHERE(earlyexit);
2000     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2001    
2002     JUMPHERE(jump);
2003     jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setmaxindex);
2004     /* Set max index. */
2005 zherczeg 695 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
2006 ph10 664 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2007 zherczeg 695 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), MAX_INDEX, TMP2, 0);
2008 ph10 664 JUMPTO(SLJIT_JUMP, mainloop);
2009    
2010     JUMPHERE(jump);
2011     jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin);
2012     /* Set max index. */
2013     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
2014     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2015     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
2016     JUMPTO(SLJIT_JUMP, mainloop);
2017    
2018     JUMPHERE(jump);
2019     /* Unknown command. */
2020     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2021     JUMPTO(SLJIT_JUMP, mainloop);
2022     }
2023    
2024     static void check_wordboundary(compiler_common *common)
2025     {
2026     DEFINE_COMPILER;
2027     struct sljit_jump *beginend;
2028 ph10 670 #ifdef SUPPORT_UTF8
2029 ph10 664 struct sljit_jump *jump;
2030 ph10 670 #endif
2031 ph10 664
2032     SLJIT_ASSERT(ctype_word == 0x10);
2033    
2034     sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize);
2035     /* Get type of the previous char, and put it to LOCALS1. */
2036     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2037     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
2038     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0);
2039     beginend = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
2040     skip_char_back(common);
2041     read_char(common);
2042    
2043     /* Testing char type. */
2044     #ifdef SUPPORT_UCP
2045     if (common->useucp)
2046     {
2047     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
2048     jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
2049     add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2050     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
2051     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2052     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2053     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
2054     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2055     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2056     JUMPHERE(jump);
2057     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
2058     }
2059     else
2060     #endif
2061     {
2062     #ifdef SUPPORT_UTF8
2063     /* Here LOCALS1 has already been zeroed. */
2064     jump = NULL;
2065     if (common->utf8)
2066     jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2067     #endif
2068     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
2069     OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);
2070     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2071     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
2072     #ifdef SUPPORT_UTF8
2073     if (jump != NULL)
2074     JUMPHERE(jump);
2075     #endif
2076     }
2077     JUMPHERE(beginend);
2078    
2079     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2080     beginend = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2081     peek_char(common);
2082    
2083     /* Testing char type. This is a code duplication. */
2084     #ifdef SUPPORT_UCP
2085     if (common->useucp)
2086     {
2087     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
2088     jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
2089     add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2090     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
2091     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2092     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2093     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
2094     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2095     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2096     JUMPHERE(jump);
2097     }
2098     else
2099     #endif
2100     {
2101     #ifdef SUPPORT_UTF8
2102     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2103     jump = NULL;
2104     if (common->utf8)
2105     jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2106     #endif
2107     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
2108     OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);
2109     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
2110     #ifdef SUPPORT_UTF8
2111     if (jump != NULL)
2112     JUMPHERE(jump);
2113     #endif
2114     }
2115     JUMPHERE(beginend);
2116    
2117     OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2118     sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2119     }
2120    
2121     static void check_anynewline(compiler_common *common)
2122     {
2123     /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2124     DEFINE_COMPILER;
2125    
2126     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2127    
2128     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
2129     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
2130     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2131     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
2132     #ifdef SUPPORT_UTF8
2133     if (common->utf8)
2134     {
2135     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2136     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
2137     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
2138     }
2139     #endif
2140     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2141     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2142     }
2143    
2144     static void check_hspace(compiler_common *common)
2145     {
2146     /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2147     DEFINE_COMPILER;
2148    
2149     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2150    
2151     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
2152     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2153     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
2154     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2155     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
2156     #ifdef SUPPORT_UTF8
2157     if (common->utf8)
2158     {
2159     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2160     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
2161     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2162     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
2163     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2164     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
2165     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
2166     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2167     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
2168     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2169     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
2170     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2171     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
2172     }
2173     #endif
2174     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2175    
2176     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2177     }
2178    
2179     static void check_vspace(compiler_common *common)
2180     {
2181     /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2182     DEFINE_COMPILER;
2183    
2184     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2185    
2186     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
2187     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
2188     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2189     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
2190     #ifdef SUPPORT_UTF8
2191     if (common->utf8)
2192     {
2193     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2194     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
2195     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
2196     }
2197     #endif
2198     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2199    
2200     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2201     }
2202    
2203     #define CHAR1 STR_END
2204     #define CHAR2 STACK_TOP
2205    
2206     static void do_casefulcmp(compiler_common *common)
2207     {
2208     DEFINE_COMPILER;
2209     struct sljit_jump *jump;
2210     struct sljit_label *label;
2211    
2212     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2213     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2214     OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
2215     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0);
2216     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2217     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2218    
2219     label = LABEL();
2220     OP1(SLJIT_MOVU_UB, CHAR1, 0, SLJIT_MEM1(TMP1), 1);
2221     OP1(SLJIT_MOVU_UB, CHAR2, 0, SLJIT_MEM1(STR_PTR), 1);
2222     jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
2223     OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
2224     JUMPTO(SLJIT_C_NOT_ZERO, label);
2225    
2226     JUMPHERE(jump);
2227     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2228     OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0);
2229     OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2230     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2231     }
2232    
2233     #define LCC_TABLE STACK_LIMIT
2234    
2235     static void do_caselesscmp(compiler_common *common)
2236     {
2237     DEFINE_COMPILER;
2238     struct sljit_jump *jump;
2239     struct sljit_label *label;
2240    
2241     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2242     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2243    
2244     OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);
2245     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0);
2246     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0);
2247     OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc);
2248     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2249     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2250    
2251     label = LABEL();
2252     OP1(SLJIT_MOVU_UB, CHAR1, 0, SLJIT_MEM1(TMP1), 1);
2253     OP1(SLJIT_MOVU_UB, CHAR2, 0, SLJIT_MEM1(STR_PTR), 1);
2254     OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
2255     OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
2256     jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
2257     OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
2258     JUMPTO(SLJIT_C_NOT_ZERO, label);
2259    
2260     JUMPHERE(jump);
2261     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2262     OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0);
2263     OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2264     OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2265     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2266     }
2267    
2268     #undef LCC_TABLE
2269     #undef CHAR1
2270     #undef CHAR2
2271    
2272     #ifdef SUPPORT_UTF8
2273     #ifdef SUPPORT_UCP
2274    
2275     static uschar * SLJIT_CALL do_utf8caselesscmp(uschar *src1, jit_arguments *args, uschar *end1)
2276     {
2277     /* This function would be ineffective to do in JIT level. */
2278     int c1, c2;
2279     uschar *src2 = args->ptr;
2280     uschar *end2 = (uschar*)args->end;
2281    
2282     while (src1 < end1)
2283     {
2284     if (src2 >= end2)
2285     return 0;
2286     GETCHARINC(c1, src1);
2287     GETCHARINC(c2, src2);
2288     if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return 0;
2289     }
2290     return src2;
2291     }
2292    
2293     #endif
2294     #endif
2295    
2296     static uschar *byte_sequence_compare(compiler_common *common, BOOL caseless, uschar *cc,
2297     compare_context* context, jump_list **fallbacks)
2298     {
2299     DEFINE_COMPILER;
2300     unsigned int othercasebit = 0;
2301     uschar *othercasebyte = NULL;
2302     #ifdef SUPPORT_UTF8
2303     int utf8length;
2304     #endif
2305    
2306     if (caseless && char_has_othercase(common, cc))
2307     {
2308     othercasebit = char_get_othercase_bit(common, cc);
2309     SLJIT_ASSERT(othercasebit);
2310     /* Extracting bit difference info. */
2311     othercasebyte = cc + (othercasebit >> 8);
2312     othercasebit &= 0xff;
2313     }
2314    
2315     if (context->sourcereg == -1)
2316     {
2317     #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2318     if (context->length >= 4)
2319     OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2320     else if (context->length >= 2)
2321     OP1(SLJIT_MOV_SH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2322     else
2323     #endif
2324     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2325     context->sourcereg = TMP2;
2326     }
2327    
2328     #ifdef SUPPORT_UTF8
2329     utf8length = 1;
2330     if (common->utf8 && *cc >= 0xc0)
2331     utf8length += _pcre_utf8_table4[*cc & 0x3f];
2332    
2333     do
2334     {
2335     #endif
2336    
2337     context->length--;
2338     #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2339    
2340     /* Unaligned read is supported. */
2341     if (othercasebit != 0 && othercasebyte == cc)
2342     {
2343     context->c.asbytes[context->byteptr] = *cc | othercasebit;
2344     context->oc.asbytes[context->byteptr] = othercasebit;
2345     }
2346     else
2347     {
2348     context->c.asbytes[context->byteptr] = *cc;
2349     context->oc.asbytes[context->byteptr] = 0;
2350     }
2351     context->byteptr++;
2352    
2353     if (context->byteptr >= 4 || context->length == 0 || (context->byteptr == 2 && context->length == 1))
2354     {
2355     if (context->length >= 4)
2356     OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2357     else if (context->length >= 2)
2358     OP1(SLJIT_MOV_SH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2359     else if (context->length >= 1)
2360     OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2361     context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
2362    
2363     switch(context->byteptr)
2364     {
2365     case 4:
2366     if (context->oc.asint != 0)
2367     OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);
2368     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));
2369     break;
2370    
2371     case 2:
2372     if (context->oc.asshort != 0)
2373     OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asshort);
2374     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asshort | context->oc.asshort));
2375     break;
2376    
2377     case 1:
2378     if (context->oc.asbyte != 0)
2379     OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);
2380     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));
2381     break;
2382    
2383     default:
2384     SLJIT_ASSERT_STOP();
2385     break;
2386     }
2387     context->byteptr = 0;
2388     }
2389 ph10 691
2390 ph10 664 #else
2391    
2392     /* Unaligned read is unsupported. */
2393     if (context->length > 0)
2394     OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2395     context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
2396    
2397     if (othercasebit != 0 && othercasebyte == cc)
2398     {
2399     OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);
2400     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));
2401     }
2402     else
2403     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));
2404    
2405     #endif
2406    
2407     cc++;
2408     #ifdef SUPPORT_UTF8
2409     utf8length--;
2410     }
2411     while (utf8length > 0);
2412     #endif
2413    
2414     return cc;
2415     }
2416    
2417     #ifdef SUPPORT_UTF8
2418    
2419     #define SET_TYPE_OFFSET(value) \
2420     if ((value) != typeoffset) \
2421     { \
2422     if ((value) > typeoffset) \
2423     OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
2424     else \
2425     OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
2426     } \
2427     typeoffset = (value);
2428    
2429     #define SET_CHAR_OFFSET(value) \
2430     if ((value) != charoffset) \
2431     { \
2432     if ((value) > charoffset) \
2433     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
2434     else \
2435     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
2436     } \
2437     charoffset = (value);
2438    
2439     static void compile_xclass_hotpath(compiler_common *common, uschar *cc, jump_list **fallbacks)
2440     {
2441     DEFINE_COMPILER;
2442     jump_list *found = NULL;
2443     jump_list **list = (*cc & XCL_NOT) == 0 ? &found : fallbacks;
2444     unsigned int c;
2445     int compares;
2446     struct sljit_jump *jump = NULL;
2447     uschar *ccbegin;
2448     #ifdef SUPPORT_UCP
2449     BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
2450     BOOL charsaved = FALSE;
2451     int typereg = TMP1, scriptreg = TMP1, typeoffset;
2452     #endif
2453     int charoffset, invertcmp, numberofcmps;
2454    
2455     /* Although SUPPORT_UTF8 must be defined, we are not necessary in utf8 mode. */
2456     check_input_end(common, fallbacks);
2457     read_char(common);
2458    
2459     if ((*cc++ & XCL_MAP) != 0)
2460     {
2461     OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
2462     if (common->utf8)
2463     jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2464    
2465     OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
2466     OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
2467     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
2468     OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
2469     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
2470     add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO));
2471    
2472     if (common->utf8)
2473     JUMPHERE(jump);
2474     OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2475     #ifdef SUPPORT_UCP
2476     charsaved = TRUE;
2477     #endif
2478     cc += 32;
2479     }
2480    
2481     /* Scanning the necessary info. */
2482     ccbegin = cc;
2483     compares = 0;
2484     while (*cc != XCL_END)
2485     {
2486     compares++;
2487     if (*cc == XCL_SINGLE)
2488     {
2489     cc += 2;
2490     #ifdef SUPPORT_UTF8
2491     if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
2492     #endif
2493     #ifdef SUPPORT_UCP
2494     needschar = TRUE;
2495     #endif
2496     }
2497     else if (*cc == XCL_RANGE)
2498     {
2499     cc += 2;
2500     #ifdef SUPPORT_UTF8
2501     if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
2502     #endif
2503     cc++;
2504     #ifdef SUPPORT_UTF8
2505     if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
2506     #endif
2507     #ifdef SUPPORT_UCP
2508     needschar = TRUE;
2509     #endif
2510     }
2511     #ifdef SUPPORT_UCP
2512     else
2513     {
2514     SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
2515     cc++;
2516     switch(*cc)
2517     {
2518     case PT_ANY:
2519     break;
2520    
2521     case PT_LAMP:
2522     case PT_GC:
2523     case PT_PC:
2524     case PT_ALNUM:
2525     needstype = TRUE;
2526     break;
2527    
2528     case PT_SC:
2529     needsscript = TRUE;
2530     break;
2531    
2532     case PT_SPACE:
2533     case PT_PXSPACE:
2534     case PT_WORD:
2535     needstype = TRUE;
2536     needschar = TRUE;
2537     break;
2538    
2539     default:
2540     SLJIT_ASSERT_STOP();
2541     break;
2542     }
2543     cc += 2;
2544     }
2545     #endif
2546     }
2547    
2548     #ifdef SUPPORT_UCP
2549     /* Simple register allocation. TMP1 is preferred if possible. */
2550     if (needstype || needsscript)
2551     {
2552     if (needschar && !charsaved)
2553     OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
2554     add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2555     if (needschar)
2556     {
2557     if (needstype)
2558     {
2559     OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
2560     typereg = RETURN_ADDR;
2561     }
2562    
2563     if (needsscript)
2564     scriptreg = TMP3;
2565     OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2566     }
2567     else if (needstype && needsscript)
2568     scriptreg = TMP3;
2569     /* In all other cases only one of them was specified, and that can goes to TMP1. */
2570    
2571     if (needsscript)
2572     {
2573     if (scriptreg == TMP1)
2574     {
2575     OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, script));
2576     OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3);
2577     }
2578     else
2579     {
2580     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
2581     OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, script));
2582     OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0);
2583     }
2584     }
2585     }
2586     #endif
2587    
2588     /* Generating code. */
2589     cc = ccbegin;
2590     charoffset = 0;
2591     numberofcmps = 0;
2592     #ifdef SUPPORT_UCP
2593     typeoffset = 0;
2594     #endif
2595    
2596     while (*cc != XCL_END)
2597     {
2598     compares--;
2599     invertcmp = (compares == 0 && list != fallbacks);
2600     jump = NULL;
2601    
2602     if (*cc == XCL_SINGLE)
2603     {
2604     cc ++;
2605     #ifdef SUPPORT_UTF8
2606     if (common->utf8)
2607     {
2608     GETCHARINC(c, cc);
2609     }
2610     else
2611     #endif
2612     c = *cc++;
2613    
2614     if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
2615     {
2616     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2617     COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2618     numberofcmps++;
2619     }
2620     else if (numberofcmps > 0)
2621     {
2622     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2623     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2624     jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2625     numberofcmps = 0;
2626     }
2627     else
2628     {
2629     jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
2630     numberofcmps = 0;
2631     }
2632     }
2633     else if (*cc == XCL_RANGE)
2634     {
2635     cc ++;
2636     #ifdef SUPPORT_UTF8
2637     if (common->utf8)
2638     {
2639     GETCHARINC(c, cc);
2640     }
2641     else
2642     #endif
2643     c = *cc++;
2644     SET_CHAR_OFFSET(c);
2645     #ifdef SUPPORT_UTF8
2646     if (common->utf8)
2647     {
2648     GETCHARINC(c, cc);
2649     }
2650     else
2651     #endif
2652     c = *cc++;
2653     if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
2654     {
2655     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2656     COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2657     numberofcmps++;
2658     }
2659     else if (numberofcmps > 0)
2660     {
2661     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2662     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2663     jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2664     numberofcmps = 0;
2665     }
2666     else
2667     {
2668     jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
2669     numberofcmps = 0;
2670     }
2671     }
2672     #ifdef SUPPORT_UCP
2673     else
2674     {
2675     if (*cc == XCL_NOTPROP)
2676     invertcmp ^= 0x1;
2677     cc++;
2678     switch(*cc)
2679     {
2680     case PT_ANY:
2681     if (list != fallbacks)
2682     {
2683     if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))
2684     continue;
2685     }
2686     else if (cc[-1] == XCL_NOTPROP)
2687     continue;
2688     jump = JUMP(SLJIT_JUMP);
2689     break;
2690    
2691     case PT_LAMP:
2692     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
2693     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2694     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
2695     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2696     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
2697     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2698     jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2699     break;
2700    
2701     case PT_GC:
2702     c = _pcre_ucp_typerange[(int)cc[1] * 2];
2703     SET_TYPE_OFFSET(c);
2704     jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, _pcre_ucp_typerange[(int)cc[1] * 2 + 1] - c);
2705     break;
2706    
2707     case PT_PC:
2708     jump = CMP(SLJIT_C_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset);
2709     break;
2710    
2711     case PT_SC:
2712     jump = CMP(SLJIT_C_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]);
2713     break;
2714    
2715     case PT_SPACE:
2716     case PT_PXSPACE:
2717     if (*cc == PT_SPACE)
2718     {
2719     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2720     jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 11 - charoffset);
2721     }
2722     SET_CHAR_OFFSET(9);
2723     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9);
2724     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2725     if (*cc == PT_SPACE)
2726     JUMPHERE(jump);
2727    
2728     SET_TYPE_OFFSET(ucp_Zl);
2729     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
2730     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2731     jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2732     break;
2733    
2734     case PT_WORD:
2735     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset);
2736     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2737     /* ... fall through */
2738    
2739     case PT_ALNUM:
2740     SET_TYPE_OFFSET(ucp_Ll);
2741     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2742     COND_VALUE((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2743     SET_TYPE_OFFSET(ucp_Nd);
2744     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2745     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2746     jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2747     break;
2748     }
2749     cc += 2;
2750     }
2751     #endif
2752    
2753     if (jump != NULL)
2754     add_jump(compiler, compares > 0 ? list : fallbacks, jump);
2755     }
2756    
2757     if (found != NULL)
2758     set_jumps(found, LABEL());
2759     }
2760    
2761     #undef SET_TYPE_OFFSET
2762     #undef SET_CHAR_OFFSET
2763    
2764     #endif
2765    
2766     static uschar *compile_char1_hotpath(compiler_common *common, uschar type, uschar *cc, jump_list **fallbacks)
2767     {
2768     DEFINE_COMPILER;
2769     int length;
2770     unsigned int c, oc, bit;
2771     compare_context context;
2772     struct sljit_jump *jump[4];
2773     #ifdef SUPPORT_UTF8
2774 ph10 670 struct sljit_label *label;
2775 ph10 664 #ifdef SUPPORT_UCP
2776     uschar propdata[5];
2777     #endif
2778     #endif
2779    
2780     switch(type)
2781     {
2782     case OP_SOD:
2783     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2784     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
2785     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
2786     return cc;
2787    
2788     case OP_SOM:
2789     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2790     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
2791     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
2792     return cc;
2793    
2794     case OP_NOT_WORD_BOUNDARY:
2795     case OP_WORD_BOUNDARY:
2796     add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
2797     add_jump(compiler, fallbacks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
2798     return cc;
2799    
2800     case OP_NOT_DIGIT:
2801     case OP_DIGIT:
2802     check_input_end(common, fallbacks);
2803     read_char8_type(common);
2804     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
2805     add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
2806     return cc;
2807    
2808     case OP_NOT_WHITESPACE:
2809     case OP_WHITESPACE:
2810     check_input_end(common, fallbacks);
2811     read_char8_type(common);
2812     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
2813     add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
2814     return cc;
2815    
2816     case OP_NOT_WORDCHAR:
2817     case OP_WORDCHAR:
2818     check_input_end(common, fallbacks);
2819     read_char8_type(common);
2820     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
2821     add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
2822     return cc;
2823    
2824     case OP_ANY:
2825     check_input_end(common, fallbacks);
2826     read_char(common);
2827     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2828     {
2829     jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
2830     jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2831     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2832     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));
2833     JUMPHERE(jump[1]);
2834     JUMPHERE(jump[0]);
2835     }
2836     else
2837     check_newlinechar(common, common->nltype, fallbacks, TRUE);
2838     return cc;
2839    
2840     case OP_ALLANY:
2841     check_input_end(common, fallbacks);
2842     #ifdef SUPPORT_UTF8
2843     if (common->utf8)
2844     {
2845     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2846     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
2847     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2848     return cc;
2849     }
2850     #endif
2851     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2852     return cc;
2853    
2854     #ifdef SUPPORT_UTF8
2855     #ifdef SUPPORT_UCP
2856     case OP_NOTPROP:
2857     case OP_PROP:
2858     propdata[0] = 0;
2859     propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;
2860     propdata[2] = cc[0];
2861     propdata[3] = cc[1];
2862     propdata[4] = XCL_END;
2863     compile_xclass_hotpath(common, propdata, fallbacks);
2864     return cc + 2;
2865     #endif
2866     #endif
2867    
2868     case OP_ANYNL:
2869     check_input_end(common, fallbacks);
2870     read_char(common);
2871     jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
2872     jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2873     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2874     jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
2875     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2876     jump[3] = JUMP(SLJIT_JUMP);
2877     JUMPHERE(jump[0]);
2878     check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE);
2879     JUMPHERE(jump[1]);
2880     JUMPHERE(jump[2]);
2881     JUMPHERE(jump[3]);
2882     return cc;
2883    
2884     case OP_NOT_HSPACE:
2885     case OP_HSPACE:
2886     check_input_end(common, fallbacks);
2887     read_char(common);
2888     add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
2889     add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
2890     return cc;
2891    
2892     case OP_NOT_VSPACE:
2893     case OP_VSPACE:
2894     check_input_end(common, fallbacks);
2895     read_char(common);
2896     add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
2897     add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
2898     return cc;
2899    
2900     #ifdef SUPPORT_UCP
2901     case OP_EXTUNI:
2902     check_input_end(common, fallbacks);
2903     read_char(common);
2904     add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2905     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
2906     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc));
2907    
2908     label = LABEL();
2909     jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2910     OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
2911     read_char(common);
2912     add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2913     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
2914     CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc, label);
2915    
2916     OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
2917     JUMPHERE(jump[0]);
2918     return cc;
2919     #endif
2920    
2921     case OP_EODN:
2922     jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2923     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2924     {
2925     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
2926     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2927     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
2928     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
2929     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
2930     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
2931     }
2932     else if (common->nltype == NLTYPE_FIXED)
2933     {
2934     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 1);
2935     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2936     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
2937     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
2938     }
2939     else
2940     {
2941     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2942     jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
2943     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
2944     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
2945     jump[2] = JUMP(SLJIT_C_GREATER);
2946     add_jump(compiler, fallbacks, JUMP(SLJIT_C_LESS));
2947     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 1);
2948     jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
2949     add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP));
2950    
2951     JUMPHERE(jump[1]);
2952     if (common->nltype == NLTYPE_ANYCRLF)
2953     {
2954     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 1);
2955     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0));
2956     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
2957     }
2958     else
2959     {
2960     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0);
2961     read_char(common);
2962     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
2963     add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
2964     add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
2965     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2966     }
2967     JUMPHERE(jump[2]);
2968     JUMPHERE(jump[3]);
2969     }
2970     JUMPHERE(jump[0]);
2971     return cc;
2972    
2973     case OP_EOD:
2974     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
2975     return cc;
2976    
2977     case OP_CIRC:
2978     OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
2979     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
2980     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0));
2981     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
2982     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
2983     return cc;
2984    
2985     case OP_CIRCM:
2986     OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
2987     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
2988     jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0);
2989     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
2990     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
2991     jump[0] = JUMP(SLJIT_JUMP);
2992     JUMPHERE(jump[1]);
2993    
2994     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, end));
2995     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP2, 0, STR_PTR, 0));
2996    
2997     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2998     {
2999     OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
3000     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0));
3001     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -2);
3002     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), -1);
3003     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
3004     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
3005     }
3006     else
3007     {
3008     skip_char_back(common);
3009     read_char(common);
3010     check_newlinechar(common, common->nltype, fallbacks, FALSE);
3011     }
3012     JUMPHERE(jump[0]);
3013     return cc;
3014    
3015     case OP_DOLL:
3016     OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3017     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
3018     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3019    
3020     if (!common->endonly)
3021     compile_char1_hotpath(common, OP_EODN, cc, fallbacks);
3022     else
3023     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
3024     return cc;
3025    
3026     case OP_DOLLM:
3027     jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
3028     OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3029     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
3030     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3031     jump[0] = JUMP(SLJIT_JUMP);
3032     JUMPHERE(jump[1]);
3033    
3034     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3035     {
3036     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
3037     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0));
3038     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
3039     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
3040     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
3041     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
3042     }
3043     else
3044     {
3045     peek_char(common);
3046     check_newlinechar(common, common->nltype, fallbacks, FALSE);
3047     }
3048     JUMPHERE(jump[0]);
3049     return cc;
3050    
3051     case OP_CHAR:
3052     case OP_CHARI:
3053     length = 1;
3054     #ifdef SUPPORT_UTF8
3055     if (common->utf8 && *cc >= 0xc0) length += _pcre_utf8_table4[*cc & 0x3f];
3056     #endif
3057     if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)
3058     {
3059     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, length);
3060     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3061    
3062     context.length = length;
3063     context.sourcereg = -1;
3064     #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3065     context.byteptr = 0;
3066     #endif
3067     return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks);
3068     }
3069     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
3070     read_char(common);
3071     #ifdef SUPPORT_UTF8
3072     if (common->utf8)
3073     {
3074     GETCHAR(c, cc);
3075     }
3076     else
3077     #endif
3078     c = *cc;
3079     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c);
3080     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3081     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c));
3082     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3083     add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
3084     return cc + length;
3085    
3086     case OP_NOT:
3087     case OP_NOTI:
3088     length = 1;
3089     #ifdef SUPPORT_UTF8
3090     if (common->utf8)
3091     {
3092     if (*cc >= 0xc0) length += _pcre_utf8_table4[*cc & 0x3f];
3093    
3094     check_input_end(common, fallbacks);
3095     GETCHAR(c, cc);
3096    
3097     if (c <= 127)
3098     {
3099     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
3100     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
3101     if (type == OP_NOT || !char_has_othercase(common, cc))
3102     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3103     else
3104     {
3105     /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
3106     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x20);
3107     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | 0x20));
3108     }
3109     /* Skip the variable-length character. */
3110     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
3111     return cc + length;
3112     }
3113     else
3114     read_char(common);
3115     }
3116     else
3117     #endif
3118     {
3119     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
3120     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3121     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -1);
3122     c = *cc;
3123     }
3124    
3125     if (type == OP_NOT || !char_has_othercase(common, cc))
3126     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3127     else
3128     {
3129     oc = char_othercase(common, c);
3130     bit = c ^ oc;
3131     if (ispowerof2(bit))
3132     {
3133     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
3134     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
3135     }
3136     else
3137     {
3138     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3139     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc));
3140     }
3141     }
3142     return cc + length;
3143    
3144     case OP_CLASS:
3145     case OP_NCLASS:
3146     check_input_end(common, fallbacks);
3147     read_char(common);
3148     #ifdef SUPPORT_UTF8
3149     jump[0] = NULL;
3150     if (common->utf8)
3151     {
3152     jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
3153     if (type == OP_CLASS)
3154     {
3155     add_jump(compiler, fallbacks, jump[0]);
3156     jump[0] = NULL;
3157     }
3158     }
3159     #endif
3160     OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
3161     OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
3162     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
3163     OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
3164     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
3165     add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
3166     #ifdef SUPPORT_UTF8
3167     if (jump[0] != NULL)
3168     JUMPHERE(jump[0]);
3169     #endif
3170     return cc + 32;
3171    
3172     #ifdef SUPPORT_UTF8
3173     case OP_XCLASS:
3174     compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks);
3175     return cc + GET(cc, 0) - 1;
3176     #endif
3177    
3178     case OP_REVERSE:
3179     length = GET(cc, 0);
3180     SLJIT_ASSERT(length > 0);
3181     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
3182     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
3183     #ifdef SUPPORT_UTF8
3184     if (common->utf8)
3185     {
3186     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
3187     label = LABEL();
3188     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0));
3189     skip_char_back(common);
3190     OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
3191     JUMPTO(SLJIT_C_NOT_ZERO, label);
3192     return cc + LINK_SIZE;
3193     }
3194     #endif
3195     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, length);
3196     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0));
3197     return cc + LINK_SIZE;
3198     }
3199     SLJIT_ASSERT_STOP();
3200     return cc;
3201     }
3202    
3203     static SLJIT_INLINE uschar *compile_charn_hotpath(compiler_common *common, uschar *cc, uschar *ccend, jump_list **fallbacks)
3204     {
3205     /* This function consumes at least one input character. */
3206     /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
3207     DEFINE_COMPILER;
3208     uschar *ccbegin = cc;
3209     compare_context context;
3210     int size;
3211    
3212     context.length = 0;
3213     do
3214     {
3215     if (cc >= ccend)
3216     break;
3217    
3218     if (*cc == OP_CHAR)
3219     {
3220     size = 1;
3221     #ifdef SUPPORT_UTF8
3222     if (common->utf8 && cc[1] >= 0xc0)
3223     size += _pcre_utf8_table4[cc[1] & 0x3f];
3224     #endif
3225     }
3226     else if (*cc == OP_CHARI)
3227     {
3228     size = 1;
3229     #ifdef SUPPORT_UTF8
3230     if (common->utf8)
3231     {
3232     if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3233     size = 0;
3234     else if (cc[1] >= 0xc0)
3235     size += _pcre_utf8_table4[cc[1] & 0x3f];
3236     }
3237 ph10 691 else
3238 ph10 664 #endif
3239     if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3240     size = 0;
3241     }
3242     else
3243     size = 0;
3244    
3245     cc += 1 + size;
3246     context.length += size;
3247     }
3248     while (size > 0 && context.length <= 128);
3249    
3250     cc = ccbegin;
3251     if (context.length > 0)
3252     {
3253     /* We have a fixed-length byte sequence. */
3254     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);
3255     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3256    
3257     context.sourcereg = -1;
3258     #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3259     context.byteptr = 0;
3260     #endif
3261     do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, fallbacks); while (context.length > 0);
3262     return cc;
3263     }
3264    
3265     /* A non-fixed length character will be checked if length == 0. */
3266     return compile_char1_hotpath(common, *cc, cc + 1, fallbacks);
3267     }
3268    
3269     static struct sljit_jump *compile_ref_checks(compiler_common *common, uschar *cc, jump_list **fallbacks)
3270     {
3271     DEFINE_COMPILER;
3272     int offset = GET2(cc, 1) << 1;
3273    
3274     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
3275     if (!common->jscript_compat)
3276     {
3277     if (fallbacks == NULL)
3278     {
3279     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
3280     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3281     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3282     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3283     return JUMP(SLJIT_C_NOT_ZERO);
3284     }
3285     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
3286     }
3287     return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3288     }
3289    
3290     /* Forward definitions. */
3291     static void compile_hotpath(compiler_common *, uschar *, uschar *, fallback_common *);
3292     static void compile_fallbackpath(compiler_common *, struct fallback_common *);
3293    
3294     #define PUSH_FALLBACK(size, ccstart, error) \
3295     do \
3296     { \
3297     fallback = sljit_alloc_memory(compiler, (size)); \
3298     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3299     return error; \
3300     memset(fallback, 0, size); \
3301     fallback->prev = parent->top; \
3302     fallback->cc = (ccstart); \
3303     parent->top = fallback; \
3304     } \
3305     while (0)
3306    
3307     #define PUSH_FALLBACK_NOVALUE(size, ccstart) \
3308     do \
3309     { \
3310     fallback = sljit_alloc_memory(compiler, (size)); \
3311     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3312     return; \
3313     memset(fallback, 0, size); \
3314     fallback->prev = parent->top; \
3315     fallback->cc = (ccstart); \
3316     parent->top = fallback; \
3317     } \
3318     while (0)
3319    
3320     #define FALLBACK_AS(type) ((type*)fallback)
3321    
3322     static uschar *compile_ref_hotpath(compiler_common *common, uschar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail)
3323     {
3324     DEFINE_COMPILER;
3325     int offset = GET2(cc, 1) << 1;
3326     struct sljit_jump *jump = NULL;
3327    
3328     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
3329     if (withchecks && !common->jscript_compat)
3330     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
3331    
3332     #ifdef SUPPORT_UTF8
3333     #ifdef SUPPORT_UCP
3334     if (common->utf8 && *cc == OP_REFI)
3335     {
3336     SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3);
3337     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3338     if (withchecks)
3339     jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0);
3340    
3341     /* Needed to save important temporary registers. */
3342     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
3343     OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);
3344     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, ptr), STR_PTR, 0);
3345     sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf8caselesscmp));
3346     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
3347     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
3348     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
3349     }
3350     else
3351     #endif
3352     #endif
3353     {
3354     OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
3355     if (withchecks)
3356     jump = JUMP(SLJIT_C_ZERO);
3357     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
3358    
3359     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3360     add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
3361     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3362     }
3363    
3364     if (jump != NULL)
3365     {
3366     if (emptyfail)
3367     add_jump(compiler, fallbacks, jump);
3368     else
3369     JUMPHERE(jump);
3370     }
3371     return cc + 3;
3372     }
3373    
3374     static SLJIT_INLINE uschar *compile_ref_iterator_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
3375     {
3376     DEFINE_COMPILER;
3377     fallback_common *fallback;
3378     uschar type;
3379     struct sljit_label *label;
3380     struct sljit_jump *zerolength;
3381     struct sljit_jump *jump = NULL;
3382     uschar *ccbegin = cc;
3383     int min = 0, max = 0;
3384     BOOL minimize;
3385    
3386     PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL);
3387    
3388     type = cc[3];
3389     minimize = (type & 0x1) != 0;
3390     switch(type)
3391     {
3392     case OP_CRSTAR:
3393     case OP_CRMINSTAR:
3394     min = 0;
3395     max = 0;
3396     cc += 4;
3397     break;
3398     case OP_CRPLUS:
3399     case OP_CRMINPLUS:
3400     min = 1;
3401     max = 0;
3402     cc += 4;
3403     break;
3404     case OP_CRQUERY:
3405     case OP_CRMINQUERY:
3406     min = 0;
3407     max = 1;
3408     cc += 4;
3409     break;
3410     case OP_CRRANGE:
3411     case OP_CRMINRANGE:
3412     min = GET2(cc, 3 + 1);
3413     max = GET2(cc, 3 + 3);
3414     cc += 8;
3415     break;
3416     default:
3417     SLJIT_ASSERT_STOP();
3418     break;
3419     }
3420    
3421     if (!minimize)
3422     {
3423     if (min == 0)
3424     {
3425     allocate_stack(common, 2);
3426     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3427     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
3428     /* Temporary release of STR_PTR. */
3429     OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3430     zerolength = compile_ref_checks(common, ccbegin, NULL);
3431     /* Restore if not zero length. */
3432     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3433     }
3434     else
3435     {
3436     allocate_stack(common, 1);
3437     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3438     zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);
3439     }
3440    
3441     if (min > 1 || max > 1)
3442     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
3443    
3444     label = LABEL();
3445     compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, FALSE, FALSE);
3446    
3447     if (min > 1 || max > 1)
3448     {
3449     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
3450     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
3451     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
3452     if (min > 1)
3453     CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label);
3454     if (max > 1)
3455     {
3456     jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);
3457     allocate_stack(common, 1);
3458     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3459     JUMPTO(SLJIT_JUMP, label);
3460     JUMPHERE(jump);
3461     }
3462     }
3463    
3464     if (max == 0)
3465     {
3466     /* Includes min > 1 case as well. */
3467     allocate_stack(common, 1);
3468     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3469     JUMPTO(SLJIT_JUMP, label);
3470     }
3471    
3472     JUMPHERE(zerolength);
3473     FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
3474 ph10 677
3475     decrease_call_count(common);
3476 ph10 664 return cc;
3477     }
3478    
3479     allocate_stack(common, 2);
3480     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3481     if (type != OP_CRMINSTAR)
3482     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
3483    
3484     if (min == 0)
3485     {
3486     zerolength = compile_ref_checks(common, ccbegin, NULL);
3487     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3488     jump = JUMP(SLJIT_JUMP);
3489     }
3490     else
3491     zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);
3492    
3493     FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
3494     if (max > 0)
3495     add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
3496    
3497     compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, TRUE, TRUE);
3498     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3499    
3500     if (min > 1)
3501     {
3502     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3503     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
3504     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
3505     CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, FALLBACK_AS(iterator_fallback)->hotpath);
3506     }
3507     else if (max > 0)
3508     OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
3509    
3510     if (jump != NULL)
3511     JUMPHERE(jump);
3512     JUMPHERE(zerolength);
3513 ph10 677
3514     decrease_call_count(common);
3515 ph10 664 return cc;
3516     }
3517    
3518     static SLJIT_INLINE uschar *compile_recurse_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
3519     {
3520     DEFINE_COMPILER;
3521     fallback_common *fallback;
3522     recurse_entry *entry = common->entries;
3523     recurse_entry *prev = NULL;
3524     int start = GET(cc, 1);
3525    
3526     PUSH_FALLBACK(sizeof(recurse_fallback), cc, NULL);
3527     while (entry != NULL)
3528     {
3529     if (entry->start == start)
3530     break;
3531     prev = entry;
3532     entry = entry->next;
3533     }
3534    
3535     if (entry == NULL)
3536     {
3537     entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));
3538     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3539     return NULL;
3540     entry->next = NULL;
3541     entry->entry = NULL;
3542     entry->calls = NULL;
3543     entry->start = start;
3544    
3545     if (prev != NULL)
3546     prev->next = entry;
3547     else
3548     common->entries = entry;
3549     }
3550    
3551     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
3552     allocate_stack(common, 1);
3553     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
3554    
3555     if (entry->entry == NULL)
3556     add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL));
3557     else
3558     JUMPTO(SLJIT_FAST_CALL, entry->entry);
3559     /* Leave if the match is failed. */
3560     add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0));
3561     return cc + 1 + LINK_SIZE;
3562     }
3563    
3564     static uschar *compile_assert_hotpath(compiler_common *common, uschar *cc, assert_fallback *fallback, BOOL conditional)
3565     {
3566     DEFINE_COMPILER;
3567     int framesize;
3568     int localptr;
3569     fallback_common altfallback;
3570     uschar *ccbegin;
3571     uschar opcode;
3572     uschar bra = OP_BRA;
3573     jump_list *tmp = NULL;
3574     jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks;
3575     jump_list **found;
3576     /* Saving previous accept variables. */
3577     struct sljit_label *save_acceptlabel = common->acceptlabel;
3578     struct sljit_jump *jump;
3579     struct sljit_jump *brajump = NULL;
3580     jump_list *save_accept = common->accept;
3581    
3582     if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
3583     {
3584     SLJIT_ASSERT(!conditional);
3585     bra = *cc;
3586     cc++;
3587     }
3588     localptr = PRIV(cc);
3589     SLJIT_ASSERT(localptr != 0);
3590     framesize = get_framesize(common, cc, FALSE);
3591     fallback->framesize = framesize;
3592     fallback->localptr = localptr;
3593     opcode = *cc;
3594     SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);
3595     found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;
3596     ccbegin = cc;
3597     cc += GET(cc, 1);
3598    
3599     if (bra == OP_BRAMINZERO)
3600     {
3601     /* This is a braminzero fallback path. */
3602     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3603     free_stack(common, 1);
3604     brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3605     }
3606    
3607     if (framesize < 0)
3608     {
3609     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
3610     allocate_stack(common, 1);
3611     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3612     }
3613     else
3614     {
3615     allocate_stack(common, framesize + 2);
3616     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3617     OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1));
3618     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
3619     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3620     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
3621     init_frame(common, ccbegin, framesize + 1, 2, FALSE);
3622     }
3623    
3624     memset(&altfallback, 0, sizeof(fallback_common));
3625     while (1)
3626     {
3627     common->acceptlabel = NULL;
3628     common->accept = NULL;
3629     altfallback.top = NULL;
3630     altfallback.topfallbacks = NULL;
3631    
3632     if (*ccbegin == OP_ALT)
3633     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3634    
3635     altfallback.cc = ccbegin;
3636     compile_hotpath(common, ccbegin + 1 + LINK_SIZE, cc, &altfallback);
3637     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3638     {
3639     common->acceptlabel = save_acceptlabel;
3640     common->accept = save_accept;
3641     return NULL;
3642     }
3643     common->acceptlabel = LABEL();
3644     if (common->accept != NULL)
3645     set_jumps(common->accept, common->acceptlabel);
3646    
3647     if (framesize < 0)
3648     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3649    
3650     if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
3651     {
3652     /* We know that STR_PTR was stored on the top of the stack. */
3653     if (conditional)
3654     {
3655     if (framesize < 0)
3656     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3657     else
3658     {
3659     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3660     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), (framesize + 1) * sizeof(sljit_w));
3661     }
3662     }
3663     else if (bra == OP_BRAZERO)
3664     {
3665     if (framesize < 0)
3666     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3667     else
3668     {
3669     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3670     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
3671     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3672     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w));
3673     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3674     }
3675     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3676     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3677     }
3678     else if (bra == OP_BRAMINZERO)
3679     {
3680     if (framesize >= 0)
3681     {
3682     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3683     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
3684     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3685     }
3686     }
3687     }
3688     add_jump(compiler, found, JUMP(SLJIT_JUMP));
3689    
3690     compile_fallbackpath(common, altfallback.top);
3691     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3692     {
3693     common->acceptlabel = save_acceptlabel;
3694     common->accept = save_accept;
3695     return NULL;
3696     }
3697     set_jumps(altfallback.topfallbacks, LABEL());
3698    
3699     if (*cc != OP_ALT)
3700     break;
3701    
3702     ccbegin = cc;
3703     cc += GET(cc, 1);
3704     }
3705     /* None of them matched. */
3706    
3707     if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
3708     {
3709     /* Assert is failed. */
3710     if (conditional || bra == OP_BRAZERO)
3711     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3712     if (framesize < 0)
3713     {
3714     /* The topmost item should be 0. */
3715     if (bra == OP_BRAZERO)
3716     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3717     else
3718     free_stack(common, 1);
3719     }
3720     else
3721     {
3722     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3723     if (framesize > 0)
3724     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
3725     /* The topmost item should be 0. */
3726     if (bra == OP_BRAZERO)
3727     {
3728     free_stack(common, framesize + 1);
3729     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3730     }
3731     else
3732     free_stack(common, framesize + 2);
3733     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3734     if (framesize > 0)
3735     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0);
3736     }
3737     jump = JUMP(SLJIT_JUMP);
3738     if (bra != OP_BRAZERO)
3739     add_jump(compiler, target, jump);
3740    
3741     /* Assert is successful. */
3742     set_jumps(tmp, LABEL());
3743     if (framesize < 0)
3744     {
3745     /* We know that STR_PTR was stored on the top of the stack. */
3746     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3747     /* Keep the STR_PTR on the top of the stack. */
3748     if (bra == OP_BRAZERO)
3749     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3750     else if (bra == OP_BRAMINZERO)
3751     {
3752     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3753     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3754     }
3755     }
3756     else
3757     {
3758     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3759     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), (framesize + 1) * sizeof(sljit_w));
3760     if (bra == OP_BRAZERO)
3761     {
3762     allocate_stack(common, 1);
3763     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3764     }
3765     else if (bra == OP_BRAMINZERO)
3766     {
3767     allocate_stack(common, 1);
3768     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3769     }
3770     }
3771    
3772     if (bra == OP_BRAZERO)
3773     {
3774     fallback->hotpath = LABEL();
3775     sljit_set_label(jump, fallback->hotpath);
3776     }
3777     else if (bra == OP_BRAMINZERO)
3778     {
3779     JUMPTO(SLJIT_JUMP, fallback->hotpath);
3780     JUMPHERE(brajump);
3781     if (framesize >= 0)
3782     {
3783     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3784     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
3785     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3786     }
3787     set_jumps(fallback->common.topfallbacks, LABEL());
3788     }
3789     }
3790     else
3791     {
3792     /* AssertNot is successful. */
3793     if (framesize < 0)
3794     {
3795     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3796     if (bra != OP_BRA)
3797     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3798     else
3799     free_stack(common, 1);
3800     }
3801     else
3802     {
3803     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3804     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3805     if (framesize > 0)
3806     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
3807     /* The topmost item should be 0. */
3808     if (bra != OP_BRA)
3809     {
3810     free_stack(common, framesize + 1);
3811     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3812     }
3813     else
3814     free_stack(common, framesize + 2);
3815     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3816     if (framesize > 0)
3817     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0);
3818     }
3819    
3820     if (bra == OP_BRAZERO)
3821     fallback->hotpath = LABEL();
3822     else if (bra == OP_BRAMINZERO)
3823     {
3824     JUMPTO(SLJIT_JUMP, fallback->hotpath);
3825     JUMPHERE(brajump);
3826     }
3827    
3828     if (bra != OP_BRA)
3829     {
3830     SLJIT_ASSERT(found == &fallback->common.topfallbacks);
3831     set_jumps(fallback->common.topfallbacks, LABEL());
3832     fallback->common.topfallbacks = NULL;
3833     }
3834     }
3835    
3836     common->acceptlabel = save_acceptlabel;
3837     common->accept = save_accept;
3838     return cc + 1 + LINK_SIZE;
3839     }
3840    
3841     /*
3842     Handling bracketed expressions is probably the most complex part.
3843    
3844     Stack layout naming characters:
3845     S - Push the current STR_PTR
3846     0 - Push a 0 (NULL)
3847     A - Push the current STR_PTR. Needed for restoring the STR_PTR
3848     before the next alternative. Not pushed if there are no alternatives.
3849     M - Any values pushed by the current alternative. Can be empty, or anything.
3850     C - Push the previous OVECTOR(i), OVECTOR(i+1), MAX_INDEX and OVECTOR_PRIV(i) to the stack.
3851     L - Push the previous local (pointed by localptr) to the stack
3852     () - opional values stored on the stack
3853     ()* - optonal, can be stored multiple times
3854    
3855     The following list shows the regular expression templates, their PCRE byte codes
3856     and stack layout supported by pcre-sljit.
3857    
3858     (?:) OP_BRA | OP_KET A M
3859     () OP_CBRA | OP_KET C M
3860     (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*
3861     OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*
3862     (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*
3863     OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*
3864     ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*
3865     OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*
3866     ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*
3867     OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*
3868     (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )
3869     (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )
3870     ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )
3871     ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )
3872     (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*
3873     OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*
3874     (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*
3875     OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*
3876     ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*
3877     OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*
3878     ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*
3879     OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*
3880    
3881    
3882     Stack layout naming characters:
3883     A - Push the alternative index (starting from 0) on the stack.
3884     Not pushed if there is no alternatives.
3885     M - Any values pushed by the current alternative. Can be empty, or anything.
3886    
3887     The next list shows the possible content of a bracket:
3888     (|) OP_*BRA | OP_ALT ... M A
3889     (?()|) OP_*COND | OP_ALT M A
3890     (?>|) OP_ONCE | OP_ALT ... [stack trace] M A
3891     Or nothing, if trace is unnecessary
3892     */
3893    
3894     static uschar *compile_bracket_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
3895     {
3896     DEFINE_COMPILER;
3897     fallback_common *fallback;
3898     uschar opcode;
3899     int localptr = 0;
3900     int offset = 0;
3901     int stacksize;
3902     uschar *ccbegin;
3903     uschar *hotpath;
3904     uschar bra = OP_BRA;
3905     uschar ket;
3906     assert_fallback *assert;
3907     BOOL has_alternatives;
3908     struct sljit_jump *jump;
3909     struct sljit_jump *skip;
3910     struct sljit_label *rmaxlabel = NULL;
3911     struct sljit_jump *braminzerojump = NULL;
3912    
3913     PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL);
3914    
3915     if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
3916     {
3917     bra = *cc;
3918     cc++;
3919     opcode = *cc;
3920     }
3921    
3922     opcode = *cc;
3923     ccbegin = cc;
3924     if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
3925     {
3926     /* Drop this bracket_fallback. */
3927     parent->top = fallback->prev;
3928     return bracketend(cc);
3929     }
3930    
3931     ket = *(bracketend(cc) - 1 - LINK_SIZE);
3932     SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
3933     SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
3934     cc += GET(cc, 1);
3935     has_alternatives = *cc == OP_ALT || opcode == OP_COND || opcode == OP_SCOND;
3936     if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
3937     opcode = OP_SCOND;
3938    
3939     if (opcode == OP_CBRA || opcode == OP_SCBRA)
3940     {
3941     /* Capturing brackets has a pre-allocated space. */
3942     offset = GET2(ccbegin, 1 + LINK_SIZE);
3943     localptr = OVECTOR_PRIV(offset);
3944     offset <<= 1;
3945     FALLBACK_AS(bracket_fallback)->localptr = localptr;
3946     }
3947     else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
3948     {
3949     /* Other brackets simply allocate the next entry. */
3950     localptr = PRIV(ccbegin);
3951     SLJIT_ASSERT(localptr != 0);
3952     FALLBACK_AS(bracket_fallback)->localptr = localptr;
3953     if (opcode == OP_ONCE)
3954     FALLBACK_AS(bracket_fallback)->u.framesize = get_framesize(common, ccbegin, FALSE);
3955     }
3956    
3957     /* Instructions before the first alternative. */
3958     stacksize = 0;
3959     if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
3960     stacksize++;
3961     if (bra == OP_BRAZERO)
3962     stacksize++;
3963    
3964     if (stacksize > 0)
3965     allocate_stack(common, stacksize);
3966    
3967     stacksize = 0;
3968     if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
3969     {
3970     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
3971     stacksize++;
3972     }
3973    
3974     if (bra == OP_BRAZERO)
3975     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
3976    
3977     if (bra == OP_BRAMINZERO)
3978     {
3979     /* This is a fallback path! (Since the hot-path of OP_BRAMINZERO matches to the empty string) */
3980     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3981     if (ket != OP_KETRMIN)
3982     {
3983     free_stack(common, 1);
3984     braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3985     }
3986     else
3987     {
3988     if (opcode == OP_ONCE || opcode >= OP_SBRA)
3989     {
3990     jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3991     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3992     /* Nothing stored during the first run. */
3993     skip = JUMP(SLJIT_JUMP);
3994     JUMPHERE(jump);
3995     /* Checking zero-length iteration. */
3996     if (opcode != OP_ONCE || FALLBACK_AS(bracket_fallback)->u.framesize < 0)
3997     {
3998     /* When we come from outside, localptr contains the previous STR_PTR. */
3999     braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4000     }
4001     else
4002     {
4003     /* Except when the whole stack frame must be saved. */
4004     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4005     braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w));
4006     }
4007     JUMPHERE(skip);
4008     }
4009     else
4010     {
4011     jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
4012     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
4013     JUMPHERE(jump);
4014     }
4015     }
4016     }
4017    
4018     if (ket == OP_KETRMIN)
4019     FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();
4020    
4021     if (ket == OP_KETRMAX)
4022     {
4023     rmaxlabel = LABEL();
4024     if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)
4025     FALLBACK_AS(bracket_fallback)->althotpath = rmaxlabel;
4026     }
4027    
4028     /* Handling capturing brackets and alternatives. */
4029     if (opcode == OP_ONCE)
4030     {
4031     if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)
4032     {
4033     /* Neither capturing brackets nor recursions are not found in the block. */
4034     if (ket == OP_KETRMIN)
4035     {
4036     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4037     allocate_stack(common, 2);
4038     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4039     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4040     OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
4041     }
4042     else if (ket == OP_KETRMAX || has_alternatives)
4043     {
4044     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4045     allocate_stack(common, 1);
4046     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4047     }
4048     else
4049     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4050     }
4051     else
4052     {
4053     if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives)
4054     {
4055     allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 2);
4056     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4057     OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize + 1));
4058     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4059     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4060     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
4061     init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize + 1, 2, FALSE);
4062     }
4063     else
4064     {
4065     allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 1);
4066     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4067     OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize));
4068     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4069     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4070     init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize, 1, FALSE);
4071     }
4072     }
4073     }
4074     else if (opcode == OP_CBRA || opcode == OP_SCBRA)
4075     {
4076     /* Saving the previous values. */
4077     allocate_stack(common, 4);
4078     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
4079     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4080     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4081     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4082 zherczeg 695 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), MAX_INDEX);
4083     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4084 ph10 664 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4085 zherczeg 695 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
4086     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), TMP2, 0);
4087 ph10 664 /* Update MAX_INDEX if necessary. */
4088 zherczeg 695 add_stub(common, max_index, (offset >> 1) + 1, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, (offset >> 1) + 1));
4089 ph10 664 }
4090     else if (opcode == OP_SBRA || opcode == OP_SCOND)
4091     {
4092     /* Saving the previous value. */
4093     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4094     allocate_stack(common, 1);
4095     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4096     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
4097     }
4098     else if (has_alternatives)
4099     {
4100     /* Pushing the starting string pointer. */
4101     allocate_stack(common, 1);
4102     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4103     }
4104    
4105     /* Generating code for the first alternative. */
4106     hotpath = ccbegin + 1 + LINK_SIZE;
4107     if (offset != 0)
4108     hotpath += 2;
4109     if (opcode == OP_COND || opcode == OP_SCOND)
4110     {
4111     if (*hotpath == OP_CREF)
4112     {
4113     add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed),
4114     CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR((GET2(hotpath, 1) << 1)), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
4115     hotpath += 3;
4116     }
4117     else
4118     {
4119     SLJIT_ASSERT(*hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT);
4120     /* Similar code as PUSH_FALLBACK macro. */
4121     assert = sljit_alloc_memory(compiler, sizeof(assert_fallback));
4122     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4123     return NULL;
4124     memset(assert, 0, sizeof(assert_fallback));
4125     assert->common.cc = hotpath;
4126     FALLBACK_AS(bracket_fallback)->u.assert = assert;
4127     hotpath = compile_assert_hotpath(common, hotpath, assert, TRUE);
4128     }
4129     }
4130    
4131     compile_hotpath(common, hotpath, cc, fallback);
4132     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4133     return NULL;
4134    
4135     if (opcode == OP_ONCE)
4136     {
4137     if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)
4138     {
4139     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4140     /* TMP2 which is set here used by OP_KETRMAX below. */
4141     if (ket == OP_KETRMAX)
4142     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
4143     else if (ket == OP_KETRMIN)
4144     {
4145     /* Move the STR_PTR to the localptr. */
4146     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
4147     }
4148     }
4149     else if (ket == OP_KETRMAX)
4150     {
4151     /* TMP2 which is set here used by OP_KETRMAX below. */
4152     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4153     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w));
4154     }
4155     }
4156    
4157     stacksize = 0;
4158     if (ket != OP_KET || bra != OP_BRA)
4159     stacksize++;
4160     if (has_alternatives && opcode != OP_ONCE)
4161     stacksize++;
4162    
4163     if (stacksize > 0)
4164     allocate_stack(common, stacksize);
4165    
4166     stacksize = 0;
4167     if (ket != OP_KET)
4168     {
4169     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
4170     stacksize++;
4171     }
4172     else if (bra != OP_BRA)
4173     {
4174     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4175     stacksize++;
4176     }
4177    
4178     if (has_alternatives)
4179     {
4180     if (opcode != OP_ONCE)
4181     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4182     if (ket != OP_KETRMAX)
4183     FALLBACK_AS(bracket_fallback)->althotpath = LABEL();
4184     }
4185    
4186     /* Must be after the hotpath label. */
4187     if (offset != 0)
4188     {
4189     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4190     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
4191     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
4192     }
4193    
4194     if (ket == OP_KETRMAX)
4195     {
4196     if (opcode == OP_ONCE || opcode >= OP_SBRA)
4197     {
4198     if (has_alternatives)
4199     FALLBACK_AS(bracket_fallback)->althotpath = LABEL();
4200     /* Checking zero-length iteration. */
4201     if (opcode != OP_ONCE)
4202     CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel);
4203     else
4204     /* TMP2 must contain the starting STR_PTR. */
4205     CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);
4206     }
4207     else
4208     JUMPTO(SLJIT_JUMP, rmaxlabel);
4209     FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();
4210     }
4211    
4212     if (bra == OP_BRAZERO)
4213     FALLBACK_AS(bracket_fallback)->zerohotpath = LABEL();
4214    
4215     if (bra == OP_BRAMINZERO)
4216     {
4217     /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */
4218     JUMPTO(SLJIT_JUMP, ((braminzero_fallback*)parent)->hotpath);
4219     if (braminzerojump != NULL)
4220     {
4221     JUMPHERE(braminzerojump);
4222     /* We need to release the end pointer to perform the
4223     fallback for the zero-length iteration. When
4224     framesize is < 0, OP_ONCE will do the release itself. */
4225     if (opcode == OP_ONCE && FALLBACK_AS(bracket_fallback)->u.framesize >= 0)
4226     {
4227     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4228     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
4229     }
4230     else if (ket == OP_KETRMIN && opcode != OP_ONCE)
4231     free_stack(common, 1);
4232     }
4233     /* Continue to the normal fallback. */
4234     }
4235    
4236 ph10 677 if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
4237     decrease_call_count(common);
4238    
4239 ph10 664 /* Skip the other alternatives. */
4240     while (*cc == OP_ALT)
4241     cc += GET(cc, 1);
4242     cc += 1 + LINK_SIZE;
4243     return cc;
4244     }
4245    
4246     static uschar *compile_bracketpos_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
4247     {
4248     DEFINE_COMPILER;
4249     fallback_common *fallback;
4250     uschar opcode;
4251     int localptr;
4252     int cbraprivptr = 0;
4253     int framesize;
4254     int stacksize;
4255     int offset = 0;
4256     BOOL zero = FALSE;
4257     uschar *ccbegin = NULL;
4258     int stack;
4259     struct sljit_label *loop = NULL;
4260     struct jump_list *emptymatch = NULL;
4261    
4262     PUSH_FALLBACK(sizeof(bracketpos_fallback), cc, NULL);
4263     if (*cc == OP_BRAPOSZERO)
4264     {
4265     zero = TRUE;
4266     cc++;
4267     }
4268    
4269     opcode = *cc;
4270     localptr = PRIV(cc);
4271     SLJIT_ASSERT(localptr != 0);
4272     FALLBACK_AS(bracketpos_fallback)->localptr = localptr;
4273     switch(opcode)
4274     {
4275     case OP_BRAPOS:
4276     case OP_SBRAPOS:
4277     ccbegin = cc + 1 + LINK_SIZE;
4278     break;
4279    
4280     case OP_CBRAPOS:
4281     case OP_SCBRAPOS:
4282     offset = GET2(cc, 1 + LINK_SIZE);
4283     cbraprivptr = OVECTOR_PRIV(offset);
4284     offset <<= 1;
4285     ccbegin = cc + 1 + LINK_SIZE + 2;
4286     break;
4287    
4288     default:
4289     SLJIT_ASSERT_STOP();
4290     break;
4291     }
4292    
4293     framesize = get_framesize(common, cc, FALSE);
4294     FALLBACK_AS(bracketpos_fallback)->framesize = framesize;
4295     if (framesize < 0)
4296     {
4297     stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 3 : 1;
4298     if (!zero)
4299     stacksize++;
4300     FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;
4301     allocate_stack(common, stacksize);
4302     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4303    
4304     if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4305     {
4306     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
4307     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4308     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4309 zherczeg