Annotation of embedaddon/pcre/pcre_jit_compile.c, revision 1.1.1.2
1.1 misho 1: /*************************************************
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
1.1.1.2 ! misho 9: Copyright (c) 1997-2012 University of Cambridge
1.1 misho 10:
11: The machine code generator part (this module) was written by Zoltan Herczeg
1.1.1.2 ! misho 12: Copyright (c) 2010-2012
1.1 misho 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:
1.1.1.2 ! misho 55: #define SLJIT_MALLOC(size) (PUBL(malloc))(size)
! 56: #define SLJIT_FREE(ptr) (PUBL(free))(ptr)
1.1 misho 57: #define SLJIT_CONFIG_AUTO 1
58: #define SLJIT_CONFIG_STATIC 1
59: #define SLJIT_VERBOSE 0
60: #define SLJIT_DEBUG 0
61:
62: #include "sljit/sljitLir.c"
63:
64: #if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
1.1.1.2 ! misho 65: #error Unsupported architecture
1.1 misho 66: #endif
67:
68: /* Allocate memory on the stack. Fast, but limited size. */
69: #define LOCAL_SPACE_SIZE 32768
70:
71: #define STACK_GROWTH_RATE 8192
72:
73: /* Enable to check that the allocation could destroy temporaries. */
74: #if defined SLJIT_DEBUG && SLJIT_DEBUG
75: #define DESTROY_REGISTERS 1
76: #endif
77:
78: /*
79: Short summary about the backtracking mechanism empolyed by the jit code generator:
80:
81: The code generator follows the recursive nature of the PERL compatible regular
82: expressions. The basic blocks of regular expressions are condition checkers
83: whose execute different commands depending on the result of the condition check.
84: The relationship between the operators can be horizontal (concatenation) and
85: vertical (sub-expression) (See struct fallback_common for more details).
86:
87: 'ab' - 'a' and 'b' regexps are concatenated
88: 'a+' - 'a' is the sub-expression of the '+' operator
89:
90: The condition checkers are boolean (true/false) checkers. Machine code is generated
91: for the checker itself and for the actions depending on the result of the checker.
92: The 'true' case is called as the hot path (expected path), and the other is called as
93: the 'fallback' path. Branch instructions are expesive for all CPUs, so we avoid taken
94: branches on the hot path.
95:
96: Greedy star operator (*) :
97: Hot path: match happens.
98: Fallback path: match failed.
99: Non-greedy star operator (*?) :
100: Hot path: no need to perform a match.
101: Fallback path: match is required.
102:
103: The following example shows how the code generated for a capturing bracket
104: with two alternatives. Let A, B, C, D are arbirary regular expressions, and
105: we have the following regular expression:
106:
107: A(B|C)D
108:
109: The generated code will be the following:
110:
111: A hot path
112: '(' hot path (pushing arguments to the stack)
113: B hot path
114: ')' hot path (pushing arguments to the stack)
115: D hot path
116: return with successful match
117:
118: D fallback path
119: ')' fallback path (If we arrived from "C" jump to the fallback of "C")
120: B fallback path
121: C expected path
122: jump to D hot path
123: C fallback path
124: A fallback path
125:
126: Notice, that the order of fallback code paths are the opposite of the fast
127: code paths. In this way the topmost value on the stack is always belong
128: to the current fallback code path. The fallback code path must check
129: whether there is a next alternative. If so, it needs to jump back to
130: the hot path eventually. Otherwise it needs to clear out its own stack
131: frame and continue the execution on the fallback code paths.
132: */
133:
134: /*
135: Saved stack frames:
136:
137: Atomic blocks and asserts require reloading the values of local variables
138: when the fallback mechanism performed. Because of OP_RECURSE, the locals
139: are not necessarly known in compile time, thus we need a dynamic restore
140: mechanism.
141:
142: The stack frames are stored in a chain list, and have the following format:
143: ([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]
144:
145: Thus we can restore the locals to a particular point in the stack.
146: */
147:
148: typedef struct jit_arguments {
149: /* Pointers first. */
150: struct sljit_stack *stack;
1.1.1.2 ! misho 151: const pcre_uchar *str;
! 152: const pcre_uchar *begin;
! 153: const pcre_uchar *end;
1.1 misho 154: int *offsets;
1.1.1.2 ! misho 155: pcre_uchar *ptr;
1.1 misho 156: /* Everything else after. */
157: int offsetcount;
158: int calllimit;
1.1.1.2 ! misho 159: pcre_uint8 notbol;
! 160: pcre_uint8 noteol;
! 161: pcre_uint8 notempty;
! 162: pcre_uint8 notempty_atstart;
1.1 misho 163: } jit_arguments;
164:
165: typedef struct executable_function {
166: void *executable_func;
1.1.1.2 ! misho 167: PUBL(jit_callback) callback;
1.1 misho 168: void *userdata;
169: sljit_uw executable_size;
170: } executable_function;
171:
172: typedef struct jump_list {
173: struct sljit_jump *jump;
174: struct jump_list *next;
175: } jump_list;
176:
177: enum stub_types { stack_alloc };
178:
179: typedef struct stub_list {
180: enum stub_types type;
181: int data;
182: struct sljit_jump *start;
183: struct sljit_label *leave;
184: struct stub_list *next;
185: } stub_list;
186:
187: typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);
188:
189: /* The following structure is the key data type for the recursive
190: code generator. It is allocated by compile_hotpath, and contains
191: the aguments for compile_fallbackpath. Must be the first member
192: of its descendants. */
193: typedef struct fallback_common {
194: /* Concatenation stack. */
195: struct fallback_common *prev;
196: jump_list *nextfallbacks;
197: /* Internal stack (for component operators). */
198: struct fallback_common *top;
199: jump_list *topfallbacks;
200: /* Opcode pointer. */
1.1.1.2 ! misho 201: pcre_uchar *cc;
1.1 misho 202: } fallback_common;
203:
204: typedef struct assert_fallback {
205: fallback_common common;
206: jump_list *condfailed;
207: /* Less than 0 (-1) if a frame is not needed. */
208: int framesize;
209: /* Points to our private memory word on the stack. */
210: int localptr;
211: /* For iterators. */
212: struct sljit_label *hotpath;
213: } assert_fallback;
214:
215: typedef struct bracket_fallback {
216: fallback_common common;
217: /* Where to coninue if an alternative is successfully matched. */
218: struct sljit_label *althotpath;
219: /* For rmin and rmax iterators. */
220: struct sljit_label *recursivehotpath;
221: /* For greedy ? operator. */
222: struct sljit_label *zerohotpath;
223: /* Contains the branches of a failed condition. */
224: union {
225: /* Both for OP_COND, OP_SCOND. */
226: jump_list *condfailed;
227: assert_fallback *assert;
228: /* For OP_ONCE. -1 if not needed. */
229: int framesize;
230: } u;
231: /* Points to our private memory word on the stack. */
232: int localptr;
233: } bracket_fallback;
234:
235: typedef struct bracketpos_fallback {
236: fallback_common common;
237: /* Points to our private memory word on the stack. */
238: int localptr;
239: /* Reverting stack is needed. */
240: int framesize;
241: /* Allocated stack size. */
242: int stacksize;
243: } bracketpos_fallback;
244:
245: typedef struct braminzero_fallback {
246: fallback_common common;
247: struct sljit_label *hotpath;
248: } braminzero_fallback;
249:
250: typedef struct iterator_fallback {
251: fallback_common common;
252: /* Next iteration. */
253: struct sljit_label *hotpath;
254: } iterator_fallback;
255:
256: typedef struct recurse_entry {
257: struct recurse_entry *next;
258: /* Contains the function entry. */
259: struct sljit_label *entry;
260: /* Collects the calls until the function is not created. */
261: jump_list *calls;
262: /* Points to the starting opcode. */
263: int start;
264: } recurse_entry;
265:
266: typedef struct recurse_fallback {
267: fallback_common common;
268: } recurse_fallback;
269:
270: typedef struct compiler_common {
271: struct sljit_compiler *compiler;
1.1.1.2 ! misho 272: pcre_uchar *start;
1.1 misho 273: int localsize;
274: int *localptrs;
1.1.1.2 ! misho 275: const pcre_uint8 *fcc;
1.1 misho 276: sljit_w lcc;
277: int cbraptr;
278: int nltype;
279: int newline;
280: int bsr_nltype;
281: int endonly;
282: sljit_w ctypes;
283: sljit_uw name_table;
284: sljit_w name_count;
285: sljit_w name_entry_size;
286: struct sljit_label *acceptlabel;
287: stub_list *stubs;
288: recurse_entry *entries;
289: recurse_entry *currententry;
290: jump_list *accept;
291: jump_list *calllimit;
292: jump_list *stackalloc;
293: jump_list *revertframes;
294: jump_list *wordboundary;
295: jump_list *anynewline;
296: jump_list *hspace;
297: jump_list *vspace;
298: jump_list *casefulcmp;
299: jump_list *caselesscmp;
300: BOOL jscript_compat;
1.1.1.2 ! misho 301: #ifdef SUPPORT_UTF
! 302: BOOL utf;
1.1 misho 303: #ifdef SUPPORT_UCP
1.1.1.2 ! misho 304: BOOL use_ucp;
1.1 misho 305: #endif
1.1.1.2 ! misho 306: jump_list *utfreadchar;
! 307: #ifdef COMPILE_PCRE8
! 308: jump_list *utfreadtype8;
1.1 misho 309: #endif
1.1.1.2 ! misho 310: #endif /* SUPPORT_UTF */
1.1 misho 311: #ifdef SUPPORT_UCP
312: jump_list *getucd;
313: #endif
314: } compiler_common;
315:
316: /* For byte_sequence_compare. */
317:
318: typedef struct compare_context {
319: int length;
320: int sourcereg;
321: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
1.1.1.2 ! misho 322: int ucharptr;
1.1 misho 323: union {
1.1.1.2 ! misho 324: sljit_i asint;
! 325: sljit_uh asushort;
! 326: #ifdef COMPILE_PCRE8
1.1 misho 327: sljit_ub asbyte;
1.1.1.2 ! misho 328: sljit_ub asuchars[4];
! 329: #else
! 330: #ifdef COMPILE_PCRE16
! 331: sljit_uh asuchars[2];
! 332: #endif
! 333: #endif
1.1 misho 334: } c;
335: union {
1.1.1.2 ! misho 336: sljit_i asint;
! 337: sljit_uh asushort;
! 338: #ifdef COMPILE_PCRE8
1.1 misho 339: sljit_ub asbyte;
1.1.1.2 ! misho 340: sljit_ub asuchars[4];
! 341: #else
! 342: #ifdef COMPILE_PCRE16
! 343: sljit_uh asuchars[2];
! 344: #endif
! 345: #endif
1.1 misho 346: } oc;
347: #endif
348: } compare_context;
349:
350: enum {
351: frame_end = 0,
352: frame_setstrbegin = -1
353: };
354:
1.1.1.2 ! misho 355: /* Undefine sljit macros. */
! 356: #undef CMP
! 357:
1.1 misho 358: /* Used for accessing the elements of the stack. */
359: #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w))
360:
361: #define TMP1 SLJIT_TEMPORARY_REG1
362: #define TMP2 SLJIT_TEMPORARY_REG3
363: #define TMP3 SLJIT_TEMPORARY_EREG2
1.1.1.2 ! misho 364: #define STR_PTR SLJIT_SAVED_REG1
! 365: #define STR_END SLJIT_SAVED_REG2
1.1 misho 366: #define STACK_TOP SLJIT_TEMPORARY_REG2
1.1.1.2 ! misho 367: #define STACK_LIMIT SLJIT_SAVED_REG3
! 368: #define ARGUMENTS SLJIT_SAVED_EREG1
! 369: #define CALL_COUNT SLJIT_SAVED_EREG2
1.1 misho 370: #define RETURN_ADDR SLJIT_TEMPORARY_EREG1
371:
372: /* Locals layout. */
373: /* These two locals can be used by the current opcode. */
374: #define LOCALS0 (0 * sizeof(sljit_w))
375: #define LOCALS1 (1 * sizeof(sljit_w))
376: /* Two local variables for possessive quantifiers (char1 cannot use them). */
377: #define POSSESSIVE0 (2 * sizeof(sljit_w))
378: #define POSSESSIVE1 (3 * sizeof(sljit_w))
379: /* Head of the last recursion. */
380: #define RECURSIVE_HEAD (4 * sizeof(sljit_w))
381: /* Max limit of recursions. */
382: #define CALL_LIMIT (5 * sizeof(sljit_w))
383: /* Last known position of the requested byte. */
1.1.1.2 ! misho 384: #define REQ_CHAR_PTR (6 * sizeof(sljit_w))
1.1 misho 385: /* End pointer of the first line. */
386: #define FIRSTLINE_END (7 * sizeof(sljit_w))
387: /* The output vector is stored on the stack, and contains pointers
388: to characters. The vector data is divided into two groups: the first
389: group contains the start / end character pointers, and the second is
390: the start pointers when the end of the capturing group has not yet reached. */
391: #define OVECTOR_START (8 * sizeof(sljit_w))
392: #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w))
393: #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w))
1.1.1.2 ! misho 394: #define PRIV_DATA(cc) (common->localptrs[(cc) - common->start])
! 395:
! 396: #ifdef COMPILE_PCRE8
! 397: #define MOV_UCHAR SLJIT_MOV_UB
! 398: #define MOVU_UCHAR SLJIT_MOVU_UB
! 399: #else
! 400: #ifdef COMPILE_PCRE16
! 401: #define MOV_UCHAR SLJIT_MOV_UH
! 402: #define MOVU_UCHAR SLJIT_MOVU_UH
! 403: #else
! 404: #error Unsupported compiling mode
! 405: #endif
! 406: #endif
1.1 misho 407:
408: /* Shortcuts. */
409: #define DEFINE_COMPILER \
410: struct sljit_compiler *compiler = common->compiler
411: #define OP1(op, dst, dstw, src, srcw) \
412: sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
413: #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
414: sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
415: #define LABEL() \
416: sljit_emit_label(compiler)
417: #define JUMP(type) \
418: sljit_emit_jump(compiler, (type))
419: #define JUMPTO(type, label) \
420: sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
421: #define JUMPHERE(jump) \
422: sljit_set_label((jump), sljit_emit_label(compiler))
423: #define CMP(type, src1, src1w, src2, src2w) \
424: sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
425: #define CMPTO(type, src1, src1w, src2, src2w, label) \
426: sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
427: #define COND_VALUE(op, dst, dstw, type) \
428: sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))
429:
1.1.1.2 ! misho 430: static pcre_uchar* bracketend(pcre_uchar* cc)
1.1 misho 431: {
432: SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
433: do cc += GET(cc, 1); while (*cc == OP_ALT);
434: SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
435: cc += 1 + LINK_SIZE;
436: return cc;
437: }
438:
439: /* Functions whose might need modification for all new supported opcodes:
440: next_opcode
441: get_localspace
442: set_localptrs
443: get_framesize
444: init_frame
445: get_localsize
446: copy_locals
447: compile_hotpath
448: compile_fallbackpath
449: */
450:
1.1.1.2 ! misho 451: static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc)
1.1 misho 452: {
453: SLJIT_UNUSED_ARG(common);
454: switch(*cc)
455: {
456: case OP_SOD:
457: case OP_SOM:
458: case OP_SET_SOM:
459: case OP_NOT_WORD_BOUNDARY:
460: case OP_WORD_BOUNDARY:
461: case OP_NOT_DIGIT:
462: case OP_DIGIT:
463: case OP_NOT_WHITESPACE:
464: case OP_WHITESPACE:
465: case OP_NOT_WORDCHAR:
466: case OP_WORDCHAR:
467: case OP_ANY:
468: case OP_ALLANY:
469: case OP_ANYNL:
470: case OP_NOT_HSPACE:
471: case OP_HSPACE:
472: case OP_NOT_VSPACE:
473: case OP_VSPACE:
474: case OP_EXTUNI:
475: case OP_EODN:
476: case OP_EOD:
477: case OP_CIRC:
478: case OP_CIRCM:
479: case OP_DOLL:
480: case OP_DOLLM:
481: case OP_TYPESTAR:
482: case OP_TYPEMINSTAR:
483: case OP_TYPEPLUS:
484: case OP_TYPEMINPLUS:
485: case OP_TYPEQUERY:
486: case OP_TYPEMINQUERY:
487: case OP_TYPEPOSSTAR:
488: case OP_TYPEPOSPLUS:
489: case OP_TYPEPOSQUERY:
490: case OP_CRSTAR:
491: case OP_CRMINSTAR:
492: case OP_CRPLUS:
493: case OP_CRMINPLUS:
494: case OP_CRQUERY:
495: case OP_CRMINQUERY:
496: case OP_DEF:
497: case OP_BRAZERO:
498: case OP_BRAMINZERO:
499: case OP_BRAPOSZERO:
500: case OP_FAIL:
501: case OP_ACCEPT:
502: case OP_ASSERT_ACCEPT:
503: case OP_SKIPZERO:
504: return cc + 1;
505:
506: case OP_ANYBYTE:
1.1.1.2 ! misho 507: #ifdef SUPPORT_UTF
! 508: if (common->utf) return NULL;
1.1 misho 509: #endif
510: return cc + 1;
511:
512: case OP_CHAR:
513: case OP_CHARI:
514: case OP_NOT:
515: case OP_NOTI:
516: case OP_STAR:
517: case OP_MINSTAR:
518: case OP_PLUS:
519: case OP_MINPLUS:
520: case OP_QUERY:
521: case OP_MINQUERY:
522: case OP_POSSTAR:
523: case OP_POSPLUS:
524: case OP_POSQUERY:
525: case OP_STARI:
526: case OP_MINSTARI:
527: case OP_PLUSI:
528: case OP_MINPLUSI:
529: case OP_QUERYI:
530: case OP_MINQUERYI:
531: case OP_POSSTARI:
532: case OP_POSPLUSI:
533: case OP_POSQUERYI:
534: case OP_NOTSTAR:
535: case OP_NOTMINSTAR:
536: case OP_NOTPLUS:
537: case OP_NOTMINPLUS:
538: case OP_NOTQUERY:
539: case OP_NOTMINQUERY:
540: case OP_NOTPOSSTAR:
541: case OP_NOTPOSPLUS:
542: case OP_NOTPOSQUERY:
543: case OP_NOTSTARI:
544: case OP_NOTMINSTARI:
545: case OP_NOTPLUSI:
546: case OP_NOTMINPLUSI:
547: case OP_NOTQUERYI:
548: case OP_NOTMINQUERYI:
549: case OP_NOTPOSSTARI:
550: case OP_NOTPOSPLUSI:
551: case OP_NOTPOSQUERYI:
552: cc += 2;
1.1.1.2 ! misho 553: #ifdef SUPPORT_UTF
! 554: if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.1 misho 555: #endif
556: return cc;
557:
558: case OP_UPTO:
559: case OP_MINUPTO:
560: case OP_EXACT:
561: case OP_POSUPTO:
562: case OP_UPTOI:
563: case OP_MINUPTOI:
564: case OP_EXACTI:
565: case OP_POSUPTOI:
566: case OP_NOTUPTO:
567: case OP_NOTMINUPTO:
568: case OP_NOTEXACT:
569: case OP_NOTPOSUPTO:
570: case OP_NOTUPTOI:
571: case OP_NOTMINUPTOI:
572: case OP_NOTEXACTI:
573: case OP_NOTPOSUPTOI:
1.1.1.2 ! misho 574: cc += 2 + IMM2_SIZE;
! 575: #ifdef SUPPORT_UTF
! 576: if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.1 misho 577: #endif
578: return cc;
579:
580: case OP_NOTPROP:
581: case OP_PROP:
1.1.1.2 ! misho 582: return cc + 1 + 2;
! 583:
1.1 misho 584: case OP_TYPEUPTO:
585: case OP_TYPEMINUPTO:
586: case OP_TYPEEXACT:
587: case OP_TYPEPOSUPTO:
588: case OP_REF:
589: case OP_REFI:
590: case OP_CREF:
591: case OP_NCREF:
592: case OP_RREF:
593: case OP_NRREF:
594: case OP_CLOSE:
1.1.1.2 ! misho 595: cc += 1 + IMM2_SIZE;
1.1 misho 596: return cc;
597:
598: case OP_CRRANGE:
599: case OP_CRMINRANGE:
1.1.1.2 ! misho 600: return cc + 1 + 2 * IMM2_SIZE;
1.1 misho 601:
602: case OP_CLASS:
603: case OP_NCLASS:
1.1.1.2 ! misho 604: return cc + 1 + 32 / sizeof(pcre_uchar);
1.1 misho 605:
1.1.1.2 ! misho 606: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1 misho 607: case OP_XCLASS:
608: return cc + GET(cc, 1);
609: #endif
610:
611: case OP_RECURSE:
612: case OP_ASSERT:
613: case OP_ASSERT_NOT:
614: case OP_ASSERTBACK:
615: case OP_ASSERTBACK_NOT:
616: case OP_REVERSE:
617: case OP_ONCE:
618: case OP_ONCE_NC:
619: case OP_BRA:
620: case OP_BRAPOS:
621: case OP_COND:
622: case OP_SBRA:
623: case OP_SBRAPOS:
624: case OP_SCOND:
625: case OP_ALT:
626: case OP_KET:
627: case OP_KETRMAX:
628: case OP_KETRMIN:
629: case OP_KETRPOS:
630: return cc + 1 + LINK_SIZE;
631:
632: case OP_CBRA:
633: case OP_CBRAPOS:
634: case OP_SCBRA:
635: case OP_SCBRAPOS:
1.1.1.2 ! misho 636: return cc + 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 637:
638: default:
639: return NULL;
640: }
641: }
642:
1.1.1.2 ! misho 643: static int get_localspace(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
1.1 misho 644: {
645: int localspace = 0;
1.1.1.2 ! misho 646: pcre_uchar *alternative;
1.1 misho 647: /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
648: while (cc < ccend)
649: {
650: switch(*cc)
651: {
652: case OP_ASSERT:
653: case OP_ASSERT_NOT:
654: case OP_ASSERTBACK:
655: case OP_ASSERTBACK_NOT:
656: case OP_ONCE:
657: case OP_ONCE_NC:
658: case OP_BRAPOS:
659: case OP_SBRA:
660: case OP_SBRAPOS:
661: case OP_SCOND:
662: localspace += sizeof(sljit_w);
663: cc += 1 + LINK_SIZE;
664: break;
665:
666: case OP_CBRAPOS:
667: case OP_SCBRAPOS:
668: localspace += sizeof(sljit_w);
1.1.1.2 ! misho 669: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 670: break;
671:
672: case OP_COND:
673: /* Might be a hidden SCOND. */
674: alternative = cc + GET(cc, 1);
675: if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
676: localspace += sizeof(sljit_w);
677: cc += 1 + LINK_SIZE;
678: break;
679:
680: default:
681: cc = next_opcode(common, cc);
682: if (cc == NULL)
683: return -1;
684: break;
685: }
686: }
687: return localspace;
688: }
689:
1.1.1.2 ! misho 690: static void set_localptrs(compiler_common *common, int localptr, pcre_uchar *ccend)
1.1 misho 691: {
1.1.1.2 ! misho 692: pcre_uchar *cc = common->start;
! 693: pcre_uchar *alternative;
1.1 misho 694: while (cc < ccend)
695: {
696: switch(*cc)
697: {
698: case OP_ASSERT:
699: case OP_ASSERT_NOT:
700: case OP_ASSERTBACK:
701: case OP_ASSERTBACK_NOT:
702: case OP_ONCE:
703: case OP_ONCE_NC:
704: case OP_BRAPOS:
705: case OP_SBRA:
706: case OP_SBRAPOS:
707: case OP_SCOND:
708: common->localptrs[cc - common->start] = localptr;
709: localptr += sizeof(sljit_w);
710: cc += 1 + LINK_SIZE;
711: break;
712:
713: case OP_CBRAPOS:
714: case OP_SCBRAPOS:
715: common->localptrs[cc - common->start] = localptr;
716: localptr += sizeof(sljit_w);
1.1.1.2 ! misho 717: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 718: break;
719:
720: case OP_COND:
721: /* Might be a hidden SCOND. */
722: alternative = cc + GET(cc, 1);
723: if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
724: {
725: common->localptrs[cc - common->start] = localptr;
726: localptr += sizeof(sljit_w);
727: }
728: cc += 1 + LINK_SIZE;
729: break;
730:
731: default:
732: cc = next_opcode(common, cc);
733: SLJIT_ASSERT(cc != NULL);
734: break;
735: }
736: }
737: }
738:
739: /* Returns with -1 if no need for frame. */
1.1.1.2 ! misho 740: static int get_framesize(compiler_common *common, pcre_uchar *cc, BOOL recursive)
1.1 misho 741: {
1.1.1.2 ! misho 742: pcre_uchar *ccend = bracketend(cc);
1.1 misho 743: int length = 0;
744: BOOL possessive = FALSE;
745: BOOL setsom_found = FALSE;
746:
747: if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
748: {
749: length = 3;
750: possessive = TRUE;
751: }
752:
753: cc = next_opcode(common, cc);
754: SLJIT_ASSERT(cc != NULL);
755: while (cc < ccend)
756: switch(*cc)
757: {
758: case OP_SET_SOM:
759: case OP_RECURSE:
760: if (!setsom_found)
761: {
762: length += 2;
763: setsom_found = TRUE;
764: }
765: cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;
766: break;
767:
768: case OP_CBRA:
769: case OP_CBRAPOS:
770: case OP_SCBRA:
771: case OP_SCBRAPOS:
772: length += 3;
1.1.1.2 ! misho 773: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 774: break;
775:
776: default:
777: cc = next_opcode(common, cc);
778: SLJIT_ASSERT(cc != NULL);
779: break;
780: }
781:
782: /* Possessive quantifiers can use a special case. */
783: if (SLJIT_UNLIKELY(possessive) && length == 3)
784: return -1;
785:
786: if (length > 0)
787: return length + 1;
788: return -1;
789: }
790:
1.1.1.2 ! misho 791: static void init_frame(compiler_common *common, pcre_uchar *cc, int stackpos, int stacktop, BOOL recursive)
1.1 misho 792: {
793: DEFINE_COMPILER;
1.1.1.2 ! misho 794: pcre_uchar *ccend = bracketend(cc);
1.1 misho 795: BOOL setsom_found = FALSE;
796: int offset;
797:
798: /* >= 1 + shortest item size (2) */
1.1.1.2 ! misho 799: SLJIT_UNUSED_ARG(stacktop);
1.1 misho 800: SLJIT_ASSERT(stackpos >= stacktop + 2);
801:
802: stackpos = STACK(stackpos);
803: if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS))
804: cc = next_opcode(common, cc);
805: SLJIT_ASSERT(cc != NULL);
806: while (cc < ccend)
807: switch(*cc)
808: {
809: case OP_SET_SOM:
810: case OP_RECURSE:
811: if (!setsom_found)
812: {
813: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
814: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin);
815: stackpos += (int)sizeof(sljit_w);
816: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
817: stackpos += (int)sizeof(sljit_w);
818: setsom_found = TRUE;
819: }
820: cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;
821: break;
822:
823: case OP_CBRA:
824: case OP_CBRAPOS:
825: case OP_SCBRA:
826: case OP_SCBRAPOS:
827: offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
828: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
829: stackpos += (int)sizeof(sljit_w);
830: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
831: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
832: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
833: stackpos += (int)sizeof(sljit_w);
834: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
835: stackpos += (int)sizeof(sljit_w);
836:
1.1.1.2 ! misho 837: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 838: break;
839:
840: default:
841: cc = next_opcode(common, cc);
842: SLJIT_ASSERT(cc != NULL);
843: break;
844: }
845:
846: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end);
847: SLJIT_ASSERT(stackpos == STACK(stacktop));
848: }
849:
1.1.1.2 ! misho 850: static SLJIT_INLINE int get_localsize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
1.1 misho 851: {
852: int localsize = 2;
1.1.1.2 ! misho 853: pcre_uchar *alternative;
1.1 misho 854: /* Calculate the sum of the local variables. */
855: while (cc < ccend)
856: {
857: switch(*cc)
858: {
859: case OP_ASSERT:
860: case OP_ASSERT_NOT:
861: case OP_ASSERTBACK:
862: case OP_ASSERTBACK_NOT:
863: case OP_ONCE:
864: case OP_ONCE_NC:
865: case OP_BRAPOS:
866: case OP_SBRA:
867: case OP_SBRAPOS:
868: case OP_SCOND:
869: localsize++;
870: cc += 1 + LINK_SIZE;
871: break;
872:
873: case OP_CBRA:
874: case OP_SCBRA:
875: localsize++;
1.1.1.2 ! misho 876: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 877: break;
878:
879: case OP_CBRAPOS:
880: case OP_SCBRAPOS:
881: localsize += 2;
1.1.1.2 ! misho 882: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 883: break;
884:
885: case OP_COND:
886: /* Might be a hidden SCOND. */
887: alternative = cc + GET(cc, 1);
888: if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
889: localsize++;
890: cc += 1 + LINK_SIZE;
891: break;
892:
893: default:
894: cc = next_opcode(common, cc);
895: SLJIT_ASSERT(cc != NULL);
896: break;
897: }
898: }
899: SLJIT_ASSERT(cc == ccend);
900: return localsize;
901: }
902:
1.1.1.2 ! misho 903: static void copy_locals(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend,
1.1 misho 904: BOOL save, int stackptr, int stacktop)
905: {
906: DEFINE_COMPILER;
907: int srcw[2];
908: int count;
909: BOOL tmp1next = TRUE;
910: BOOL tmp1empty = TRUE;
911: BOOL tmp2empty = TRUE;
1.1.1.2 ! misho 912: pcre_uchar *alternative;
1.1 misho 913: enum {
914: start,
915: loop,
916: end
917: } status;
918:
919: status = save ? start : loop;
920: stackptr = STACK(stackptr - 2);
921: stacktop = STACK(stacktop - 1);
922:
923: if (!save)
924: {
925: stackptr += sizeof(sljit_w);
926: if (stackptr < stacktop)
927: {
928: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
929: stackptr += sizeof(sljit_w);
930: tmp1empty = FALSE;
931: }
932: if (stackptr < stacktop)
933: {
934: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
935: stackptr += sizeof(sljit_w);
936: tmp2empty = FALSE;
937: }
938: /* The tmp1next must be TRUE in either way. */
939: }
940:
941: while (status != end)
942: {
943: count = 0;
944: switch(status)
945: {
946: case start:
947: SLJIT_ASSERT(save);
948: count = 1;
949: srcw[0] = RECURSIVE_HEAD;
950: status = loop;
951: break;
952:
953: case loop:
954: if (cc >= ccend)
955: {
956: status = end;
957: break;
958: }
959:
960: switch(*cc)
961: {
962: case OP_ASSERT:
963: case OP_ASSERT_NOT:
964: case OP_ASSERTBACK:
965: case OP_ASSERTBACK_NOT:
966: case OP_ONCE:
967: case OP_ONCE_NC:
968: case OP_BRAPOS:
969: case OP_SBRA:
970: case OP_SBRAPOS:
971: case OP_SCOND:
972: count = 1;
1.1.1.2 ! misho 973: srcw[0] = PRIV_DATA(cc);
1.1 misho 974: SLJIT_ASSERT(srcw[0] != 0);
975: cc += 1 + LINK_SIZE;
976: break;
977:
978: case OP_CBRA:
979: case OP_SCBRA:
980: count = 1;
981: srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
1.1.1.2 ! misho 982: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 983: break;
984:
985: case OP_CBRAPOS:
986: case OP_SCBRAPOS:
987: count = 2;
988: srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
1.1.1.2 ! misho 989: srcw[0] = PRIV_DATA(cc);
1.1 misho 990: SLJIT_ASSERT(srcw[0] != 0);
1.1.1.2 ! misho 991: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 992: break;
993:
994: case OP_COND:
995: /* Might be a hidden SCOND. */
996: alternative = cc + GET(cc, 1);
997: if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
998: {
999: count = 1;
1.1.1.2 ! misho 1000: srcw[0] = PRIV_DATA(cc);
1.1 misho 1001: SLJIT_ASSERT(srcw[0] != 0);
1002: }
1003: cc += 1 + LINK_SIZE;
1004: break;
1005:
1006: default:
1007: cc = next_opcode(common, cc);
1008: SLJIT_ASSERT(cc != NULL);
1009: break;
1010: }
1011: break;
1012:
1013: case end:
1014: SLJIT_ASSERT_STOP();
1015: break;
1016: }
1017:
1018: while (count > 0)
1019: {
1020: count--;
1021: if (save)
1022: {
1023: if (tmp1next)
1024: {
1025: if (!tmp1empty)
1026: {
1027: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1028: stackptr += sizeof(sljit_w);
1029: }
1030: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
1031: tmp1empty = FALSE;
1032: tmp1next = FALSE;
1033: }
1034: else
1035: {
1036: if (!tmp2empty)
1037: {
1038: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1039: stackptr += sizeof(sljit_w);
1040: }
1041: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
1042: tmp2empty = FALSE;
1043: tmp1next = TRUE;
1044: }
1045: }
1046: else
1047: {
1048: if (tmp1next)
1049: {
1050: SLJIT_ASSERT(!tmp1empty);
1051: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0);
1052: tmp1empty = stackptr >= stacktop;
1053: if (!tmp1empty)
1054: {
1055: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1056: stackptr += sizeof(sljit_w);
1057: }
1058: tmp1next = FALSE;
1059: }
1060: else
1061: {
1062: SLJIT_ASSERT(!tmp2empty);
1063: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0);
1064: tmp2empty = stackptr >= stacktop;
1065: if (!tmp2empty)
1066: {
1067: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1068: stackptr += sizeof(sljit_w);
1069: }
1070: tmp1next = TRUE;
1071: }
1072: }
1073: }
1074: }
1075:
1076: if (save)
1077: {
1078: if (tmp1next)
1079: {
1080: if (!tmp1empty)
1081: {
1082: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1083: stackptr += sizeof(sljit_w);
1084: }
1085: if (!tmp2empty)
1086: {
1087: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1088: stackptr += sizeof(sljit_w);
1089: }
1090: }
1091: else
1092: {
1093: if (!tmp2empty)
1094: {
1095: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1096: stackptr += sizeof(sljit_w);
1097: }
1098: if (!tmp1empty)
1099: {
1100: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1101: stackptr += sizeof(sljit_w);
1102: }
1103: }
1104: }
1105: SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
1106: }
1107:
1108: static SLJIT_INLINE BOOL ispowerof2(unsigned int value)
1109: {
1110: return (value & (value - 1)) == 0;
1111: }
1112:
1113: static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)
1114: {
1115: while (list)
1116: {
1117: /* sljit_set_label is clever enough to do nothing
1118: if either the jump or the label is NULL */
1119: sljit_set_label(list->jump, label);
1120: list = list->next;
1121: }
1122: }
1123:
1124: static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump)
1125: {
1126: jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));
1127: if (list_item)
1128: {
1129: list_item->next = *list;
1130: list_item->jump = jump;
1131: *list = list_item;
1132: }
1133: }
1134:
1135: static void add_stub(compiler_common *common, enum stub_types type, int data, struct sljit_jump *start)
1136: {
1137: DEFINE_COMPILER;
1138: stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list));
1139:
1140: if (list_item)
1141: {
1142: list_item->type = type;
1143: list_item->data = data;
1144: list_item->start = start;
1145: list_item->leave = LABEL();
1146: list_item->next = common->stubs;
1147: common->stubs = list_item;
1148: }
1149: }
1150:
1151: static void flush_stubs(compiler_common *common)
1152: {
1153: DEFINE_COMPILER;
1154: stub_list* list_item = common->stubs;
1155:
1156: while (list_item)
1157: {
1158: JUMPHERE(list_item->start);
1159: switch(list_item->type)
1160: {
1161: case stack_alloc:
1162: add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));
1163: break;
1164: }
1165: JUMPTO(SLJIT_JUMP, list_item->leave);
1166: list_item = list_item->next;
1167: }
1168: common->stubs = NULL;
1169: }
1170:
1171: static SLJIT_INLINE void decrease_call_count(compiler_common *common)
1172: {
1173: DEFINE_COMPILER;
1174:
1175: OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 0, SLJIT_IMM, 1);
1176: add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));
1177: }
1178:
1179: static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
1180: {
1181: /* May destroy all locals and registers except TMP2. */
1182: DEFINE_COMPILER;
1183:
1184: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
1185: #ifdef DESTROY_REGISTERS
1186: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
1187: OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
1188: OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
1189: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0);
1190: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
1191: #endif
1192: add_stub(common, stack_alloc, 0, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0));
1193: }
1194:
1195: static SLJIT_INLINE void free_stack(compiler_common *common, int size)
1196: {
1197: DEFINE_COMPILER;
1198: OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
1199: }
1200:
1201: static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)
1202: {
1203: DEFINE_COMPILER;
1204: struct sljit_label *loop;
1205: int i;
1206: /* At this point we can freely use all temporary registers. */
1207: /* TMP1 returns with begin - 1. */
1.1.1.2 ! misho 1208: OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1209: if (length < 8)
1210: {
1211: for (i = 0; i < length; i++)
1212: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_TEMPORARY_REG1, 0);
1213: }
1214: else
1215: {
1216: OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START - sizeof(sljit_w));
1217: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length);
1218: loop = LABEL();
1219: OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0);
1220: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1);
1221: JUMPTO(SLJIT_C_NOT_ZERO, loop);
1222: }
1223: }
1224:
1225: static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
1226: {
1227: DEFINE_COMPILER;
1228: struct sljit_label *loop;
1229: struct sljit_jump *earlyexit;
1230:
1231: /* At this point we can freely use all registers. */
1.1.1.2 ! misho 1232: OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
1.1 misho 1233: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0);
1234:
1235: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0);
1236: OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));
1237: OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
1238: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin));
1.1.1.2 ! misho 1239: OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START);
1.1 misho 1240: /* Unlikely, but possible */
1241: earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0);
1242: loop = LABEL();
1.1.1.2 ! misho 1243: OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_TEMPORARY_REG1, 0);
! 1244: OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_w));
1.1 misho 1245: /* Copy the integer value to the output buffer */
1.1.1.2 ! misho 1246: #ifdef COMPILE_PCRE16
! 1247: OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1);
! 1248: #endif
! 1249: OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_SAVED_REG2, 0);
1.1 misho 1250: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
1251: JUMPTO(SLJIT_C_NOT_ZERO, loop);
1252: JUMPHERE(earlyexit);
1253:
1254: /* Calculate the return value, which is the maximum ovector value. */
1255: if (topbracket > 1)
1256: {
1257: OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w));
1258: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1);
1259:
1.1.1.2 ! misho 1260: /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */
1.1 misho 1261: loop = LABEL();
1262: OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w)));
1263: OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
1.1.1.2 ! misho 1264: CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG3, 0, loop);
1.1 misho 1265: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0);
1266: }
1267: else
1268: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
1269: }
1270:
1.1.1.2 ! misho 1271: static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc)
1.1 misho 1272: {
1273: /* Detects if the character has an othercase. */
1274: unsigned int c;
1275:
1.1.1.2 ! misho 1276: #ifdef SUPPORT_UTF
! 1277: if (common->utf)
1.1 misho 1278: {
1279: GETCHAR(c, cc);
1280: if (c > 127)
1281: {
1282: #ifdef SUPPORT_UCP
1283: return c != UCD_OTHERCASE(c);
1284: #else
1285: return FALSE;
1286: #endif
1287: }
1.1.1.2 ! misho 1288: #ifndef COMPILE_PCRE8
! 1289: return common->fcc[c] != c;
! 1290: #endif
1.1 misho 1291: }
1292: else
1293: #endif
1294: c = *cc;
1.1.1.2 ! misho 1295: return MAX_255(c) ? common->fcc[c] != c : FALSE;
1.1 misho 1296: }
1297:
1298: static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)
1299: {
1300: /* Returns with the othercase. */
1.1.1.2 ! misho 1301: #ifdef SUPPORT_UTF
! 1302: if (common->utf && c > 127)
1.1 misho 1303: {
1304: #ifdef SUPPORT_UCP
1305: return UCD_OTHERCASE(c);
1306: #else
1307: return c;
1308: #endif
1309: }
1310: #endif
1.1.1.2 ! misho 1311: return TABLE_GET(c, common->fcc, c);
1.1 misho 1312: }
1313:
1.1.1.2 ! misho 1314: static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar* cc)
1.1 misho 1315: {
1316: /* Detects if the character and its othercase has only 1 bit difference. */
1317: unsigned int c, oc, bit;
1.1.1.2 ! misho 1318: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.1 misho 1319: int n;
1320: #endif
1321:
1.1.1.2 ! misho 1322: #ifdef SUPPORT_UTF
! 1323: if (common->utf)
1.1 misho 1324: {
1325: GETCHAR(c, cc);
1326: if (c <= 127)
1327: oc = common->fcc[c];
1328: else
1329: {
1330: #ifdef SUPPORT_UCP
1331: oc = UCD_OTHERCASE(c);
1332: #else
1333: oc = c;
1334: #endif
1335: }
1336: }
1337: else
1338: {
1339: c = *cc;
1.1.1.2 ! misho 1340: oc = TABLE_GET(c, common->fcc, c);
1.1 misho 1341: }
1342: #else
1343: c = *cc;
1.1.1.2 ! misho 1344: oc = TABLE_GET(c, common->fcc, c);
1.1 misho 1345: #endif
1346:
1347: SLJIT_ASSERT(c != oc);
1348:
1349: bit = c ^ oc;
1350: /* Optimized for English alphabet. */
1351: if (c <= 127 && bit == 0x20)
1352: return (0 << 8) | 0x20;
1353:
1354: /* Since c != oc, they must have at least 1 bit difference. */
1355: if (!ispowerof2(bit))
1356: return 0;
1357:
1.1.1.2 ! misho 1358: #ifdef COMPILE_PCRE8
! 1359:
! 1360: #ifdef SUPPORT_UTF
! 1361: if (common->utf && c > 127)
1.1 misho 1362: {
1.1.1.2 ! misho 1363: n = GET_EXTRALEN(*cc);
1.1 misho 1364: while ((bit & 0x3f) == 0)
1365: {
1366: n--;
1367: bit >>= 6;
1368: }
1369: return (n << 8) | bit;
1370: }
1.1.1.2 ! misho 1371: #endif /* SUPPORT_UTF */
1.1 misho 1372: return (0 << 8) | bit;
1.1.1.2 ! misho 1373:
! 1374: #else /* COMPILE_PCRE8 */
! 1375:
! 1376: #ifdef COMPILE_PCRE16
! 1377: #ifdef SUPPORT_UTF
! 1378: if (common->utf && c > 65535)
! 1379: {
! 1380: if (bit >= (1 << 10))
! 1381: bit >>= 10;
! 1382: else
! 1383: return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8));
! 1384: }
! 1385: #endif /* SUPPORT_UTF */
! 1386: return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8));
! 1387: #endif /* COMPILE_PCRE16 */
! 1388:
! 1389: #endif /* COMPILE_PCRE8 */
1.1 misho 1390: }
1391:
1392: static SLJIT_INLINE void check_input_end(compiler_common *common, jump_list **fallbacks)
1393: {
1394: DEFINE_COMPILER;
1395: add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
1396: }
1397:
1398: static void read_char(compiler_common *common)
1399: {
1400: /* Reads the character into TMP1, updates STR_PTR.
1401: Does not check STR_END. TMP2 Destroyed. */
1402: DEFINE_COMPILER;
1.1.1.2 ! misho 1403: #ifdef SUPPORT_UTF
1.1 misho 1404: struct sljit_jump *jump;
1405: #endif
1406:
1.1.1.2 ! misho 1407: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
! 1408: #ifdef SUPPORT_UTF
! 1409: if (common->utf)
1.1 misho 1410: {
1.1.1.2 ! misho 1411: #ifdef COMPILE_PCRE8
1.1 misho 1412: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.1.1.2 ! misho 1413: #else
! 1414: #ifdef COMPILE_PCRE16
! 1415: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
! 1416: #endif
! 1417: #endif /* COMPILE_PCRE8 */
! 1418: add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
1.1 misho 1419: JUMPHERE(jump);
1420: }
1421: #endif
1.1.1.2 ! misho 1422: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1423: }
1424:
1425: static void peek_char(compiler_common *common)
1426: {
1427: /* Reads the character into TMP1, keeps STR_PTR.
1428: Does not check STR_END. TMP2 Destroyed. */
1429: DEFINE_COMPILER;
1.1.1.2 ! misho 1430: #ifdef SUPPORT_UTF
1.1 misho 1431: struct sljit_jump *jump;
1432: #endif
1433:
1.1.1.2 ! misho 1434: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
! 1435: #ifdef SUPPORT_UTF
! 1436: if (common->utf)
1.1 misho 1437: {
1.1.1.2 ! misho 1438: #ifdef COMPILE_PCRE8
1.1 misho 1439: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.1.1.2 ! misho 1440: #else
! 1441: #ifdef COMPILE_PCRE16
! 1442: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
! 1443: #endif
! 1444: #endif /* COMPILE_PCRE8 */
! 1445: add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
1.1 misho 1446: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1447: JUMPHERE(jump);
1448: }
1449: #endif
1450: }
1451:
1452: static void read_char8_type(compiler_common *common)
1453: {
1454: /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
1455: DEFINE_COMPILER;
1.1.1.2 ! misho 1456: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
1.1 misho 1457: struct sljit_jump *jump;
1458: #endif
1459:
1.1.1.2 ! misho 1460: #ifdef SUPPORT_UTF
! 1461: if (common->utf)
1.1 misho 1462: {
1.1.1.2 ! misho 1463: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
! 1464: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
! 1465: #ifdef COMPILE_PCRE8
1.1 misho 1466: /* This can be an extra read in some situations, but hopefully
1.1.1.2 ! misho 1467: it is needed in most cases. */
1.1 misho 1468: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1469: jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
1.1.1.2 ! misho 1470: add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));
! 1471: JUMPHERE(jump);
! 1472: #else
! 1473: #ifdef COMPILE_PCRE16
! 1474: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
! 1475: jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
! 1476: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1.1 misho 1477: JUMPHERE(jump);
1.1.1.2 ! misho 1478: /* Skip low surrogate if necessary. */
! 1479: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00);
! 1480: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800);
! 1481: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
! 1482: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
! 1483: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
! 1484: #endif
! 1485: #endif /* COMPILE_PCRE8 */
1.1 misho 1486: return;
1487: }
1488: #endif
1.1.1.2 ! misho 1489: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
! 1490: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
! 1491: #ifdef COMPILE_PCRE16
! 1492: /* The ctypes array contains only 256 values. */
! 1493: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
! 1494: jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
! 1495: #endif
! 1496: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
! 1497: #ifdef COMPILE_PCRE16
! 1498: JUMPHERE(jump);
! 1499: #endif
1.1 misho 1500: }
1501:
1502: static void skip_char_back(compiler_common *common)
1503: {
1.1.1.2 ! misho 1504: /* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */
1.1 misho 1505: DEFINE_COMPILER;
1.1.1.2 ! misho 1506: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.1 misho 1507: struct sljit_label *label;
1508:
1.1.1.2 ! misho 1509: if (common->utf)
1.1 misho 1510: {
1511: label = LABEL();
1.1.1.2 ! misho 1512: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
! 1513: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1514: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
1515: CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);
1516: return;
1517: }
1518: #endif
1.1.1.2 ! misho 1519: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
! 1520: if (common->utf)
! 1521: {
! 1522: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
! 1523: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
! 1524: /* Skip low surrogate if necessary. */
! 1525: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
! 1526: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
! 1527: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
! 1528: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
! 1529: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
! 1530: return;
! 1531: }
! 1532: #endif
! 1533: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1534: }
1535:
1536: static void check_newlinechar(compiler_common *common, int nltype, jump_list **fallbacks, BOOL jumpiftrue)
1537: {
1538: /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
1539: DEFINE_COMPILER;
1540:
1541: if (nltype == NLTYPE_ANY)
1542: {
1543: add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
1544: add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1545: }
1546: else if (nltype == NLTYPE_ANYCRLF)
1547: {
1548: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR);
1549: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
1550: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
1551: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
1552: add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1553: }
1554: else
1555: {
1.1.1.2 ! misho 1556: SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);
1.1 misho 1557: add_jump(compiler, fallbacks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
1558: }
1559: }
1560:
1.1.1.2 ! misho 1561: #ifdef SUPPORT_UTF
! 1562:
! 1563: #ifdef COMPILE_PCRE8
! 1564: static void do_utfreadchar(compiler_common *common)
1.1 misho 1565: {
1.1.1.2 ! misho 1566: /* Fast decoding a UTF-8 character. TMP1 contains the first byte
1.1 misho 1567: of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */
1568: DEFINE_COMPILER;
1569: struct sljit_jump *jump;
1570:
1571: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1572: /* Searching for the first zero. */
1573: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
1574: jump = JUMP(SLJIT_C_NOT_ZERO);
1.1.1.2 ! misho 1575: /* Two byte sequence. */
! 1576: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
! 1577: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1578: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f);
1579: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
1580: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1581: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 ! misho 1582: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1583: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1584: JUMPHERE(jump);
1585:
1586: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10);
1587: jump = JUMP(SLJIT_C_NOT_ZERO);
1.1.1.2 ! misho 1588: /* Three byte sequence. */
! 1589: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1 misho 1590: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f);
1591: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12);
1592: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1593: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1594: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 ! misho 1595: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
! 1596: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
1.1 misho 1597: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1598: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 ! misho 1599: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2));
1.1 misho 1600: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1601: JUMPHERE(jump);
1602:
1.1.1.2 ! misho 1603: /* Four byte sequence. */
! 1604: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1 misho 1605: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07);
1606: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18);
1607: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1608: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
1609: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 ! misho 1610: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
1.1 misho 1611: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1612: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1613: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 ! misho 1614: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(3));
! 1615: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
1.1 misho 1616: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1617: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 ! misho 1618: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));
1.1 misho 1619: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1620: }
1621:
1.1.1.2 ! misho 1622: static void do_utfreadtype8(compiler_common *common)
1.1 misho 1623: {
1.1.1.2 ! misho 1624: /* Fast decoding a UTF-8 character type. TMP2 contains the first byte
! 1625: of the character (>= 0xc0). Return value in TMP1. */
1.1 misho 1626: DEFINE_COMPILER;
1627: struct sljit_jump *jump;
1628: struct sljit_jump *compare;
1629:
1630: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1631:
1632: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
1633: jump = JUMP(SLJIT_C_NOT_ZERO);
1.1.1.2 ! misho 1634: /* Two byte sequence. */
! 1635: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
! 1636: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1637: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);
1638: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1639: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
1640: OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
1641: compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
1642: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1643: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1644:
1645: JUMPHERE(compare);
1646: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1647: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1648: JUMPHERE(jump);
1649:
1650: /* We only have types for characters less than 256. */
1.1.1.2 ! misho 1651: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(utf8_table4) - 0xc0);
1.1 misho 1652: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1653: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1654: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1655: }
1656:
1.1.1.2 ! misho 1657: #else /* COMPILE_PCRE8 */
! 1658:
! 1659: #ifdef COMPILE_PCRE16
! 1660: static void do_utfreadchar(compiler_common *common)
! 1661: {
! 1662: /* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char
! 1663: of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */
! 1664: DEFINE_COMPILER;
! 1665: struct sljit_jump *jump;
! 1666:
! 1667: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
! 1668: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);
! 1669: /* Do nothing, only return. */
! 1670: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
! 1671:
! 1672: JUMPHERE(jump);
! 1673: /* Combine two 16 bit characters. */
! 1674: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
! 1675: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
! 1676: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff);
! 1677: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10);
! 1678: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3ff);
! 1679: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
! 1680: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
! 1681: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
! 1682: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
! 1683: }
! 1684: #endif /* COMPILE_PCRE16 */
! 1685:
! 1686: #endif /* COMPILE_PCRE8 */
! 1687:
! 1688: #endif /* SUPPORT_UTF */
1.1 misho 1689:
1690: #ifdef SUPPORT_UCP
1691:
1692: /* UCD_BLOCK_SIZE must be 128 (see the assert below). */
1693: #define UCD_BLOCK_MASK 127
1694: #define UCD_BLOCK_SHIFT 7
1695:
1696: static void do_getucd(compiler_common *common)
1697: {
1698: /* Search the UCD record for the character comes in TMP1.
1699: Returns chartype in TMP1 and UCD offset in TMP2. */
1700: DEFINE_COMPILER;
1701:
1702: SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
1703:
1704: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1705: OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1.1.1.2 ! misho 1706: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(ucd_stage1));
1.1 misho 1707: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
1708: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1709: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 ! misho 1710: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_stage2));
1.1 misho 1711: OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
1.1.1.2 ! misho 1712: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
1.1 misho 1713: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
1714: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1715: }
1716: #endif
1717:
1718: static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline)
1719: {
1720: DEFINE_COMPILER;
1721: struct sljit_label *mainloop;
1722: struct sljit_label *newlinelabel = NULL;
1723: struct sljit_jump *start;
1724: struct sljit_jump *end = NULL;
1725: struct sljit_jump *nl = NULL;
1.1.1.2 ! misho 1726: #ifdef SUPPORT_UTF
! 1727: struct sljit_jump *singlechar;
1.1 misho 1728: #endif
1729: jump_list *newline = NULL;
1730: BOOL newlinecheck = FALSE;
1.1.1.2 ! misho 1731: BOOL readuchar = FALSE;
1.1 misho 1732:
1733: if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY ||
1734: common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
1735: newlinecheck = TRUE;
1736:
1737: if (firstline)
1738: {
1739: /* Search for the end of the first line. */
1740: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0);
1741: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_END, 0);
1742:
1743: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
1744: {
1745: mainloop = LABEL();
1.1.1.2 ! misho 1746: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1747: end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 ! misho 1748: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
! 1749: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1.1 misho 1750: CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
1751: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
1.1.1.2 ! misho 1752: OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1753: }
1754: else
1755: {
1756: end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1757: mainloop = LABEL();
1758: /* Continual stores does not cause data dependency. */
1759: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);
1760: read_char(common);
1761: check_newlinechar(common, common->nltype, &newline, TRUE);
1762: CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
1763: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);
1764: set_jumps(newline, LABEL());
1765: }
1766:
1767: JUMPHERE(end);
1768: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
1769: }
1770:
1771: start = JUMP(SLJIT_JUMP);
1772:
1773: if (newlinecheck)
1774: {
1775: newlinelabel = LABEL();
1.1.1.2 ! misho 1776: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1777: end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 ! misho 1778: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 1779: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
1780: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1.1.1.2 ! misho 1781: #ifdef COMPILE_PCRE16
! 1782: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
! 1783: #endif
1.1 misho 1784: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1785: nl = JUMP(SLJIT_JUMP);
1786: }
1787:
1788: mainloop = LABEL();
1789:
1790: /* Increasing the STR_PTR here requires one less jump in the most common case. */
1.1.1.2 ! misho 1791: #ifdef SUPPORT_UTF
! 1792: if (common->utf) readuchar = TRUE;
1.1 misho 1793: #endif
1.1.1.2 ! misho 1794: if (newlinecheck) readuchar = TRUE;
1.1 misho 1795:
1.1.1.2 ! misho 1796: if (readuchar)
! 1797: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 1798:
1799: if (newlinecheck)
1800: CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);
1801:
1.1.1.2 ! misho 1802: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
! 1803: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
! 1804: if (common->utf)
1.1 misho 1805: {
1.1.1.2 ! misho 1806: singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
! 1807: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
1.1 misho 1808: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1.1.1.2 ! misho 1809: JUMPHERE(singlechar);
! 1810: }
! 1811: #endif
! 1812: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
! 1813: if (common->utf)
! 1814: {
! 1815: singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
! 1816: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
! 1817: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
! 1818: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
! 1819: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
! 1820: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
! 1821: JUMPHERE(singlechar);
1.1 misho 1822: }
1823: #endif
1824: JUMPHERE(start);
1825:
1826: if (newlinecheck)
1827: {
1828: JUMPHERE(end);
1829: JUMPHERE(nl);
1830: }
1831:
1832: return mainloop;
1833: }
1834:
1.1.1.2 ! misho 1835: static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline)
1.1 misho 1836: {
1837: DEFINE_COMPILER;
1838: struct sljit_label *start;
1839: struct sljit_jump *leave;
1840: struct sljit_jump *found;
1.1.1.2 ! misho 1841: pcre_uchar oc, bit;
1.1 misho 1842:
1843: if (firstline)
1844: {
1845: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1846: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1847: }
1848:
1849: start = LABEL();
1850: leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 ! misho 1851: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 1852:
1.1.1.2 ! misho 1853: oc = first_char;
! 1854: if (caseless)
! 1855: {
! 1856: oc = TABLE_GET(first_char, common->fcc, first_char);
! 1857: #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
! 1858: if (first_char > 127 && common->utf)
! 1859: oc = UCD_OTHERCASE(first_char);
! 1860: #endif
! 1861: }
! 1862: if (first_char == oc)
! 1863: found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, first_char);
1.1 misho 1864: else
1865: {
1.1.1.2 ! misho 1866: bit = first_char ^ oc;
1.1 misho 1867: if (ispowerof2(bit))
1868: {
1869: OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit);
1.1.1.2 ! misho 1870: found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit);
1.1 misho 1871: }
1872: else
1873: {
1.1.1.2 ! misho 1874: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char);
1.1 misho 1875: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
1876: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
1877: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
1878: found = JUMP(SLJIT_C_NOT_ZERO);
1879: }
1880: }
1881:
1.1.1.2 ! misho 1882: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
! 1883: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
! 1884: if (common->utf)
1.1 misho 1885: {
1886: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start);
1.1.1.2 ! misho 1887: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
! 1888: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
! 1889: }
! 1890: #endif
! 1891: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
! 1892: if (common->utf)
! 1893: {
! 1894: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
! 1895: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
! 1896: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
! 1897: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
! 1898: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1.1 misho 1899: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1900: }
1901: #endif
1902: JUMPTO(SLJIT_JUMP, start);
1903: JUMPHERE(found);
1904: JUMPHERE(leave);
1905:
1906: if (firstline)
1907: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1908: }
1909:
1910: static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline)
1911: {
1912: DEFINE_COMPILER;
1913: struct sljit_label *loop;
1914: struct sljit_jump *lastchar;
1915: struct sljit_jump *firstchar;
1916: struct sljit_jump *leave;
1917: struct sljit_jump *foundcr = NULL;
1918: struct sljit_jump *notfoundnl;
1919: jump_list *newline = NULL;
1920:
1921: if (firstline)
1922: {
1923: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1924: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1925: }
1926:
1927: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
1928: {
1929: lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1930: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1931: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1932: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
1933: firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
1934:
1.1.1.2 ! misho 1935: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));
1.1 misho 1936: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
1937: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL);
1.1.1.2 ! misho 1938: #ifdef COMPILE_PCRE16
! 1939: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
! 1940: #endif
1.1 misho 1941: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1942:
1943: loop = LABEL();
1.1.1.2 ! misho 1944: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1945: leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 ! misho 1946: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
! 1947: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
1.1 misho 1948: CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);
1949: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);
1950:
1951: JUMPHERE(leave);
1952: JUMPHERE(firstchar);
1953: JUMPHERE(lastchar);
1954:
1955: if (firstline)
1956: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1957: return;
1958: }
1959:
1960: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1961: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1962: firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
1963: skip_char_back(common);
1964:
1965: loop = LABEL();
1966: read_char(common);
1967: lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1968: if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
1969: foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
1970: check_newlinechar(common, common->nltype, &newline, FALSE);
1971: set_jumps(newline, loop);
1972:
1973: if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
1974: {
1975: leave = JUMP(SLJIT_JUMP);
1976: JUMPHERE(foundcr);
1977: notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 ! misho 1978: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 1979: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
1980: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1.1.1.2 ! misho 1981: #ifdef COMPILE_PCRE16
! 1982: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
! 1983: #endif
1.1 misho 1984: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1985: JUMPHERE(notfoundnl);
1986: JUMPHERE(leave);
1987: }
1988: JUMPHERE(lastchar);
1989: JUMPHERE(firstchar);
1990:
1991: if (firstline)
1992: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1993: }
1994:
1995: static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline)
1996: {
1997: DEFINE_COMPILER;
1998: struct sljit_label *start;
1999: struct sljit_jump *leave;
2000: struct sljit_jump *found;
1.1.1.2 ! misho 2001: #ifndef COMPILE_PCRE8
! 2002: struct sljit_jump *jump;
! 2003: #endif
1.1 misho 2004:
2005: if (firstline)
2006: {
2007: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
2008: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
2009: }
2010:
2011: start = LABEL();
2012: leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 ! misho 2013: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
! 2014: #ifdef SUPPORT_UTF
! 2015: if (common->utf)
1.1 misho 2016: OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
2017: #endif
1.1.1.2 ! misho 2018: #ifndef COMPILE_PCRE8
! 2019: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255);
! 2020: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255);
! 2021: JUMPHERE(jump);
! 2022: #endif
1.1 misho 2023: OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
2024: OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
2025: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits);
2026: OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
2027: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
2028: found = JUMP(SLJIT_C_NOT_ZERO);
2029:
1.1.1.2 ! misho 2030: #ifdef SUPPORT_UTF
! 2031: if (common->utf)
1.1 misho 2032: OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2033: #endif
1.1.1.2 ! misho 2034: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
! 2035: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
! 2036: if (common->utf)
1.1 misho 2037: {
2038: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start);
1.1.1.2 ! misho 2039: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
! 2040: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
! 2041: }
! 2042: #endif
! 2043: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
! 2044: if (common->utf)
! 2045: {
! 2046: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
! 2047: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
! 2048: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
! 2049: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
! 2050: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1.1 misho 2051: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2052: }
2053: #endif
2054: JUMPTO(SLJIT_JUMP, start);
2055: JUMPHERE(found);
2056: JUMPHERE(leave);
2057:
2058: if (firstline)
2059: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
2060: }
2061:
1.1.1.2 ! misho 2062: static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar)
1.1 misho 2063: {
2064: DEFINE_COMPILER;
2065: struct sljit_label *loop;
2066: struct sljit_jump *toolong;
2067: struct sljit_jump *alreadyfound;
2068: struct sljit_jump *found;
2069: struct sljit_jump *foundoc = NULL;
2070: struct sljit_jump *notfound;
1.1.1.2 ! misho 2071: pcre_uchar oc, bit;
1.1 misho 2072:
1.1.1.2 ! misho 2073: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR);
1.1 misho 2074: OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);
2075: toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0);
2076: alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0);
2077:
1.1.1.2 ! misho 2078: if (has_firstchar)
! 2079: OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2080: else
2081: OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);
2082:
2083: loop = LABEL();
2084: notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0);
2085:
1.1.1.2 ! misho 2086: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0);
! 2087: oc = req_char;
! 2088: if (caseless)
! 2089: {
! 2090: oc = TABLE_GET(req_char, common->fcc, req_char);
! 2091: #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
! 2092: if (req_char > 127 && common->utf)
! 2093: oc = UCD_OTHERCASE(req_char);
! 2094: #endif
! 2095: }
! 2096: if (req_char == oc)
! 2097: found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char);
1.1 misho 2098: else
2099: {
1.1.1.2 ! misho 2100: bit = req_char ^ oc;
1.1 misho 2101: if (ispowerof2(bit))
2102: {
2103: OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);
1.1.1.2 ! misho 2104: found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit);
1.1 misho 2105: }
2106: else
2107: {
1.1.1.2 ! misho 2108: found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char);
1.1 misho 2109: foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc);
2110: }
2111: }
1.1.1.2 ! misho 2112: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2113: JUMPTO(SLJIT_JUMP, loop);
2114:
2115: JUMPHERE(found);
2116: if (foundoc)
2117: JUMPHERE(foundoc);
1.1.1.2 ! misho 2118: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, TMP1, 0);
1.1 misho 2119: JUMPHERE(alreadyfound);
2120: JUMPHERE(toolong);
2121: return notfound;
2122: }
2123:
2124: static void do_revertframes(compiler_common *common)
2125: {
2126: DEFINE_COMPILER;
2127: struct sljit_jump *jump;
2128: struct sljit_label *mainloop;
2129:
2130: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2131: OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0);
2132:
2133: /* Drop frames until we reach STACK_TOP. */
2134: mainloop = LABEL();
2135: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
2136: jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
2137: OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_LOCALS_REG, 0);
2138: OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
2139: OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w));
2140: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w));
2141: JUMPTO(SLJIT_JUMP, mainloop);
2142:
2143: JUMPHERE(jump);
2144: jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
2145: /* End of dropping frames. */
2146: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2147:
2148: JUMPHERE(jump);
2149: jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin);
2150: /* Set string begin. */
2151: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
2152: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2153: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
2154: JUMPTO(SLJIT_JUMP, mainloop);
2155:
2156: JUMPHERE(jump);
2157: /* Unknown command. */
2158: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2159: JUMPTO(SLJIT_JUMP, mainloop);
2160: }
2161:
2162: static void check_wordboundary(compiler_common *common)
2163: {
2164: DEFINE_COMPILER;
2165: struct sljit_jump *beginend;
1.1.1.2 ! misho 2166: #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF
1.1 misho 2167: struct sljit_jump *jump;
2168: #endif
2169:
2170: SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);
2171:
2172: sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize);
2173: /* Get type of the previous char, and put it to LOCALS1. */
2174: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2175: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
2176: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0);
2177: beginend = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
2178: skip_char_back(common);
2179: read_char(common);
2180:
2181: /* Testing char type. */
2182: #ifdef SUPPORT_UCP
1.1.1.2 ! misho 2183: if (common->use_ucp)
1.1 misho 2184: {
2185: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
2186: jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
2187: add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2188: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
2189: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2190: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2191: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
2192: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2193: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2194: JUMPHERE(jump);
2195: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
2196: }
2197: else
2198: #endif
2199: {
1.1.1.2 ! misho 2200: #ifndef COMPILE_PCRE8
! 2201: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
! 2202: #elif defined SUPPORT_UTF
1.1 misho 2203: /* Here LOCALS1 has already been zeroed. */
2204: jump = NULL;
1.1.1.2 ! misho 2205: if (common->utf)
1.1 misho 2206: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
1.1.1.2 ! misho 2207: #endif /* COMPILE_PCRE8 */
1.1 misho 2208: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
2209: OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);
2210: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2211: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
1.1.1.2 ! misho 2212: #ifndef COMPILE_PCRE8
! 2213: JUMPHERE(jump);
! 2214: #elif defined SUPPORT_UTF
1.1 misho 2215: if (jump != NULL)
2216: JUMPHERE(jump);
1.1.1.2 ! misho 2217: #endif /* COMPILE_PCRE8 */
1.1 misho 2218: }
2219: JUMPHERE(beginend);
2220:
2221: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2222: beginend = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2223: peek_char(common);
2224:
2225: /* Testing char type. This is a code duplication. */
2226: #ifdef SUPPORT_UCP
1.1.1.2 ! misho 2227: if (common->use_ucp)
1.1 misho 2228: {
2229: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
2230: jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
2231: add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2232: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
2233: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2234: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2235: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
2236: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2237: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2238: JUMPHERE(jump);
2239: }
2240: else
2241: #endif
2242: {
1.1.1.2 ! misho 2243: #ifndef COMPILE_PCRE8
! 2244: /* TMP2 may be destroyed by peek_char. */
! 2245: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
! 2246: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
! 2247: #elif defined SUPPORT_UTF
1.1 misho 2248: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2249: jump = NULL;
1.1.1.2 ! misho 2250: if (common->utf)
1.1 misho 2251: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2252: #endif
2253: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
2254: OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);
2255: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
1.1.1.2 ! misho 2256: #ifndef COMPILE_PCRE8
! 2257: JUMPHERE(jump);
! 2258: #elif defined SUPPORT_UTF
1.1 misho 2259: if (jump != NULL)
2260: JUMPHERE(jump);
1.1.1.2 ! misho 2261: #endif /* COMPILE_PCRE8 */
1.1 misho 2262: }
2263: JUMPHERE(beginend);
2264:
2265: OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2266: sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2267: }
2268:
2269: static void check_anynewline(compiler_common *common)
2270: {
2271: /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2272: DEFINE_COMPILER;
2273:
2274: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2275:
2276: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
2277: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
2278: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2279: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
1.1.1.2 ! misho 2280: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
! 2281: #ifdef COMPILE_PCRE8
! 2282: if (common->utf)
1.1 misho 2283: {
1.1.1.2 ! misho 2284: #endif
1.1 misho 2285: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2286: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
2287: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
1.1.1.2 ! misho 2288: #ifdef COMPILE_PCRE8
1.1 misho 2289: }
2290: #endif
1.1.1.2 ! misho 2291: #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
1.1 misho 2292: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2293: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2294: }
2295:
2296: static void check_hspace(compiler_common *common)
2297: {
2298: /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2299: DEFINE_COMPILER;
2300:
2301: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2302:
2303: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
2304: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2305: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
2306: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2307: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
1.1.1.2 ! misho 2308: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
! 2309: #ifdef COMPILE_PCRE8
! 2310: if (common->utf)
1.1 misho 2311: {
1.1.1.2 ! misho 2312: #endif
1.1 misho 2313: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2314: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
2315: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2316: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
2317: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2318: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
2319: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
2320: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2321: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
2322: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2323: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
2324: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2325: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
1.1.1.2 ! misho 2326: #ifdef COMPILE_PCRE8
1.1 misho 2327: }
2328: #endif
1.1.1.2 ! misho 2329: #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
1.1 misho 2330: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2331:
2332: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2333: }
2334:
2335: static void check_vspace(compiler_common *common)
2336: {
2337: /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2338: DEFINE_COMPILER;
2339:
2340: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2341:
2342: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
2343: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
2344: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2345: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
1.1.1.2 ! misho 2346: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
! 2347: #ifdef COMPILE_PCRE8
! 2348: if (common->utf)
1.1 misho 2349: {
1.1.1.2 ! misho 2350: #endif
1.1 misho 2351: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2352: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
2353: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
1.1.1.2 ! misho 2354: #ifdef COMPILE_PCRE8
1.1 misho 2355: }
2356: #endif
1.1.1.2 ! misho 2357: #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
1.1 misho 2358: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2359:
2360: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2361: }
2362:
2363: #define CHAR1 STR_END
2364: #define CHAR2 STACK_TOP
2365:
2366: static void do_casefulcmp(compiler_common *common)
2367: {
2368: DEFINE_COMPILER;
2369: struct sljit_jump *jump;
2370: struct sljit_label *label;
2371:
2372: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2373: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2374: OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
2375: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0);
1.1.1.2 ! misho 2376: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
! 2377: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2378:
2379: label = LABEL();
1.1.1.2 ! misho 2380: OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
! 2381: OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1 misho 2382: jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
1.1.1.2 ! misho 2383: OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2384: JUMPTO(SLJIT_C_NOT_ZERO, label);
2385:
2386: JUMPHERE(jump);
1.1.1.2 ! misho 2387: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2388: OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0);
2389: OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2390: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2391: }
2392:
2393: #define LCC_TABLE STACK_LIMIT
2394:
2395: static void do_caselesscmp(compiler_common *common)
2396: {
2397: DEFINE_COMPILER;
2398: struct sljit_jump *jump;
2399: struct sljit_label *label;
2400:
2401: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2402: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2403:
2404: OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);
2405: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0);
2406: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0);
2407: OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc);
1.1.1.2 ! misho 2408: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
! 2409: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2410:
2411: label = LABEL();
1.1.1.2 ! misho 2412: OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
! 2413: OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
! 2414: #ifndef COMPILE_PCRE8
! 2415: jump = CMP(SLJIT_C_GREATER, CHAR1, 0, SLJIT_IMM, 255);
! 2416: #endif
1.1 misho 2417: OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
1.1.1.2 ! misho 2418: #ifndef COMPILE_PCRE8
! 2419: JUMPHERE(jump);
! 2420: jump = CMP(SLJIT_C_GREATER, CHAR2, 0, SLJIT_IMM, 255);
! 2421: #endif
1.1 misho 2422: OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
1.1.1.2 ! misho 2423: #ifndef COMPILE_PCRE8
! 2424: JUMPHERE(jump);
! 2425: #endif
1.1 misho 2426: jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
1.1.1.2 ! misho 2427: OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2428: JUMPTO(SLJIT_C_NOT_ZERO, label);
2429:
2430: JUMPHERE(jump);
1.1.1.2 ! misho 2431: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2432: OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0);
2433: OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2434: OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2435: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2436: }
2437:
2438: #undef LCC_TABLE
2439: #undef CHAR1
2440: #undef CHAR2
2441:
1.1.1.2 ! misho 2442: #if defined SUPPORT_UTF && defined SUPPORT_UCP
1.1 misho 2443:
1.1.1.2 ! misho 2444: static const pcre_uchar *SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1)
1.1 misho 2445: {
2446: /* This function would be ineffective to do in JIT level. */
2447: int c1, c2;
1.1.1.2 ! misho 2448: const pcre_uchar *src2 = args->ptr;
! 2449: const pcre_uchar *end2 = args->end;
1.1 misho 2450:
2451: while (src1 < end1)
2452: {
2453: if (src2 >= end2)
2454: return 0;
2455: GETCHARINC(c1, src1);
2456: GETCHARINC(c2, src2);
2457: if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return 0;
2458: }
2459: return src2;
2460: }
2461:
1.1.1.2 ! misho 2462: #endif /* SUPPORT_UTF && SUPPORT_UCP */
1.1 misho 2463:
1.1.1.2 ! misho 2464: static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc,
1.1 misho 2465: compare_context* context, jump_list **fallbacks)
2466: {
2467: DEFINE_COMPILER;
2468: unsigned int othercasebit = 0;
1.1.1.2 ! misho 2469: pcre_uchar *othercasechar = NULL;
! 2470: #ifdef SUPPORT_UTF
! 2471: int utflength;
1.1 misho 2472: #endif
2473:
2474: if (caseless && char_has_othercase(common, cc))
2475: {
2476: othercasebit = char_get_othercase_bit(common, cc);
2477: SLJIT_ASSERT(othercasebit);
2478: /* Extracting bit difference info. */
1.1.1.2 ! misho 2479: #ifdef COMPILE_PCRE8
! 2480: othercasechar = cc + (othercasebit >> 8);
1.1 misho 2481: othercasebit &= 0xff;
1.1.1.2 ! misho 2482: #else
! 2483: #ifdef COMPILE_PCRE16
! 2484: othercasechar = cc + (othercasebit >> 9);
! 2485: if ((othercasebit & 0x100) != 0)
! 2486: othercasebit = (othercasebit & 0xff) << 8;
! 2487: else
! 2488: othercasebit &= 0xff;
! 2489: #endif
! 2490: #endif
1.1 misho 2491: }
2492:
2493: if (context->sourcereg == -1)
2494: {
1.1.1.2 ! misho 2495: #ifdef COMPILE_PCRE8
1.1 misho 2496: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2497: if (context->length >= 4)
2498: OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2499: else if (context->length >= 2)
1.1.1.2 ! misho 2500: OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1 misho 2501: else
2502: #endif
2503: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1.1.2 ! misho 2504: #else
! 2505: #ifdef COMPILE_PCRE16
! 2506: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
! 2507: if (context->length >= 4)
! 2508: OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
! 2509: else
! 2510: #endif
! 2511: OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
! 2512: #endif
! 2513: #endif /* COMPILE_PCRE8 */
1.1 misho 2514: context->sourcereg = TMP2;
2515: }
2516:
1.1.1.2 ! misho 2517: #ifdef SUPPORT_UTF
! 2518: utflength = 1;
! 2519: if (common->utf && HAS_EXTRALEN(*cc))
! 2520: utflength += GET_EXTRALEN(*cc);
1.1 misho 2521:
2522: do
2523: {
2524: #endif
2525:
1.1.1.2 ! misho 2526: context->length -= IN_UCHARS(1);
1.1 misho 2527: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2528:
2529: /* Unaligned read is supported. */
1.1.1.2 ! misho 2530: if (othercasebit != 0 && othercasechar == cc)
1.1 misho 2531: {
1.1.1.2 ! misho 2532: context->c.asuchars[context->ucharptr] = *cc | othercasebit;
! 2533: context->oc.asuchars[context->ucharptr] = othercasebit;
1.1 misho 2534: }
2535: else
2536: {
1.1.1.2 ! misho 2537: context->c.asuchars[context->ucharptr] = *cc;
! 2538: context->oc.asuchars[context->ucharptr] = 0;
1.1 misho 2539: }
1.1.1.2 ! misho 2540: context->ucharptr++;
1.1 misho 2541:
1.1.1.2 ! misho 2542: #ifdef COMPILE_PCRE8
! 2543: if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1))
! 2544: #else
! 2545: if (context->ucharptr >= 2 || context->length == 0)
! 2546: #endif
1.1 misho 2547: {
2548: if (context->length >= 4)
2549: OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1.1.2 ! misho 2550: #ifdef COMPILE_PCRE8
1.1 misho 2551: else if (context->length >= 2)
1.1.1.2 ! misho 2552: OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1 misho 2553: else if (context->length >= 1)
2554: OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1.1.2 ! misho 2555: #else
! 2556: else if (context->length >= 2)
! 2557: OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
! 2558: #endif
1.1 misho 2559: context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
2560:
1.1.1.2 ! misho 2561: switch(context->ucharptr)
1.1 misho 2562: {
1.1.1.2 ! misho 2563: case 4 / sizeof(pcre_uchar):
1.1 misho 2564: if (context->oc.asint != 0)
2565: OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);
2566: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));
2567: break;
2568:
1.1.1.2 ! misho 2569: case 2 / sizeof(pcre_uchar):
! 2570: if (context->oc.asushort != 0)
! 2571: OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);
! 2572: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));
1.1 misho 2573: break;
2574:
1.1.1.2 ! misho 2575: #ifdef COMPILE_PCRE8
1.1 misho 2576: case 1:
2577: if (context->oc.asbyte != 0)
2578: OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);
2579: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));
2580: break;
1.1.1.2 ! misho 2581: #endif
1.1 misho 2582:
2583: default:
2584: SLJIT_ASSERT_STOP();
2585: break;
2586: }
1.1.1.2 ! misho 2587: context->ucharptr = 0;
1.1 misho 2588: }
2589:
2590: #else
2591:
2592: /* Unaligned read is unsupported. */
1.1.1.2 ! misho 2593: #ifdef COMPILE_PCRE8
1.1 misho 2594: if (context->length > 0)
2595: OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1.1.2 ! misho 2596: #else
! 2597: if (context->length > 0)
! 2598: OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
! 2599: #endif
1.1 misho 2600: context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
2601:
1.1.1.2 ! misho 2602: if (othercasebit != 0 && othercasechar == cc)
1.1 misho 2603: {
2604: OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);
2605: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));
2606: }
2607: else
2608: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));
2609:
2610: #endif
2611:
2612: cc++;
1.1.1.2 ! misho 2613: #ifdef SUPPORT_UTF
! 2614: utflength--;
1.1 misho 2615: }
1.1.1.2 ! misho 2616: while (utflength > 0);
1.1 misho 2617: #endif
2618:
2619: return cc;
2620: }
2621:
1.1.1.2 ! misho 2622: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1 misho 2623:
2624: #define SET_TYPE_OFFSET(value) \
2625: if ((value) != typeoffset) \
2626: { \
2627: if ((value) > typeoffset) \
2628: OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
2629: else \
2630: OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
2631: } \
2632: typeoffset = (value);
2633:
2634: #define SET_CHAR_OFFSET(value) \
2635: if ((value) != charoffset) \
2636: { \
2637: if ((value) > charoffset) \
2638: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
2639: else \
2640: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
2641: } \
2642: charoffset = (value);
2643:
1.1.1.2 ! misho 2644: static void compile_xclass_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks)
1.1 misho 2645: {
2646: DEFINE_COMPILER;
2647: jump_list *found = NULL;
2648: jump_list **list = (*cc & XCL_NOT) == 0 ? &found : fallbacks;
2649: unsigned int c;
2650: int compares;
2651: struct sljit_jump *jump = NULL;
1.1.1.2 ! misho 2652: pcre_uchar *ccbegin;
1.1 misho 2653: #ifdef SUPPORT_UCP
2654: BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
2655: BOOL charsaved = FALSE;
2656: int typereg = TMP1, scriptreg = TMP1;
2657: unsigned int typeoffset;
2658: #endif
2659: int invertcmp, numberofcmps;
2660: unsigned int charoffset;
2661:
1.1.1.2 ! misho 2662: /* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */
1.1 misho 2663: check_input_end(common, fallbacks);
2664: read_char(common);
2665:
2666: if ((*cc++ & XCL_MAP) != 0)
2667: {
2668: OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
1.1.1.2 ! misho 2669: #ifndef COMPILE_PCRE8
! 2670: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
! 2671: #elif defined SUPPORT_UTF
! 2672: if (common->utf)
1.1 misho 2673: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
1.1.1.2 ! misho 2674: #endif
1.1 misho 2675:
2676: OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
2677: OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
2678: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
2679: OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
2680: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
2681: add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO));
2682:
1.1.1.2 ! misho 2683: #ifndef COMPILE_PCRE8
! 2684: JUMPHERE(jump);
! 2685: #elif defined SUPPORT_UTF
! 2686: if (common->utf)
1.1 misho 2687: JUMPHERE(jump);
1.1.1.2 ! misho 2688: #endif
1.1 misho 2689: OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2690: #ifdef SUPPORT_UCP
2691: charsaved = TRUE;
2692: #endif
1.1.1.2 ! misho 2693: cc += 32 / sizeof(pcre_uchar);
1.1 misho 2694: }
2695:
2696: /* Scanning the necessary info. */
2697: ccbegin = cc;
2698: compares = 0;
2699: while (*cc != XCL_END)
2700: {
2701: compares++;
2702: if (*cc == XCL_SINGLE)
2703: {
2704: cc += 2;
1.1.1.2 ! misho 2705: #ifdef SUPPORT_UTF
! 2706: if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.1 misho 2707: #endif
2708: #ifdef SUPPORT_UCP
2709: needschar = TRUE;
2710: #endif
2711: }
2712: else if (*cc == XCL_RANGE)
2713: {
2714: cc += 2;
1.1.1.2 ! misho 2715: #ifdef SUPPORT_UTF
! 2716: if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.1 misho 2717: #endif
2718: cc++;
1.1.1.2 ! misho 2719: #ifdef SUPPORT_UTF
! 2720: if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.1 misho 2721: #endif
2722: #ifdef SUPPORT_UCP
2723: needschar = TRUE;
2724: #endif
2725: }
2726: #ifdef SUPPORT_UCP
2727: else
2728: {
2729: SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
2730: cc++;
2731: switch(*cc)
2732: {
2733: case PT_ANY:
2734: break;
2735:
2736: case PT_LAMP:
2737: case PT_GC:
2738: case PT_PC:
2739: case PT_ALNUM:
2740: needstype = TRUE;
2741: break;
2742:
2743: case PT_SC:
2744: needsscript = TRUE;
2745: break;
2746:
2747: case PT_SPACE:
2748: case PT_PXSPACE:
2749: case PT_WORD:
2750: needstype = TRUE;
2751: needschar = TRUE;
2752: break;
2753:
2754: default:
2755: SLJIT_ASSERT_STOP();
2756: break;
2757: }
2758: cc += 2;
2759: }
2760: #endif
2761: }
2762:
2763: #ifdef SUPPORT_UCP
2764: /* Simple register allocation. TMP1 is preferred if possible. */
2765: if (needstype || needsscript)
2766: {
2767: if (needschar && !charsaved)
2768: OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
2769: add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2770: if (needschar)
2771: {
2772: if (needstype)
2773: {
2774: OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
2775: typereg = RETURN_ADDR;
2776: }
2777:
2778: if (needsscript)
2779: scriptreg = TMP3;
2780: OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2781: }
2782: else if (needstype && needsscript)
2783: scriptreg = TMP3;
2784: /* In all other cases only one of them was specified, and that can goes to TMP1. */
2785:
2786: if (needsscript)
2787: {
2788: if (scriptreg == TMP1)
2789: {
1.1.1.2 ! misho 2790: OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
1.1 misho 2791: OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3);
2792: }
2793: else
2794: {
2795: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
1.1.1.2 ! misho 2796: OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
1.1 misho 2797: OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0);
2798: }
2799: }
2800: }
2801: #endif
2802:
2803: /* Generating code. */
2804: cc = ccbegin;
2805: charoffset = 0;
2806: numberofcmps = 0;
2807: #ifdef SUPPORT_UCP
2808: typeoffset = 0;
2809: #endif
2810:
2811: while (*cc != XCL_END)
2812: {
2813: compares--;
2814: invertcmp = (compares == 0 && list != fallbacks);
2815: jump = NULL;
2816:
2817: if (*cc == XCL_SINGLE)
2818: {
2819: cc ++;
1.1.1.2 ! misho 2820: #ifdef SUPPORT_UTF
! 2821: if (common->utf)
1.1 misho 2822: {
2823: GETCHARINC(c, cc);
2824: }
2825: else
2826: #endif
2827: c = *cc++;
2828:
2829: if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
2830: {
2831: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2832: COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2833: numberofcmps++;
2834: }
2835: else if (numberofcmps > 0)
2836: {
2837: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2838: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2839: jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2840: numberofcmps = 0;
2841: }
2842: else
2843: {
2844: jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
2845: numberofcmps = 0;
2846: }
2847: }
2848: else if (*cc == XCL_RANGE)
2849: {
2850: cc ++;
1.1.1.2 ! misho 2851: #ifdef SUPPORT_UTF
! 2852: if (common->utf)
1.1 misho 2853: {
2854: GETCHARINC(c, cc);
2855: }
2856: else
2857: #endif
2858: c = *cc++;
2859: SET_CHAR_OFFSET(c);
1.1.1.2 ! misho 2860: #ifdef SUPPORT_UTF
! 2861: if (common->utf)
1.1 misho 2862: {
2863: GETCHARINC(c, cc);
2864: }
2865: else
2866: #endif
2867: c = *cc++;
2868: if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
2869: {
2870: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2871: COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2872: numberofcmps++;
2873: }
2874: else if (numberofcmps > 0)
2875: {
2876: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2877: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2878: jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2879: numberofcmps = 0;
2880: }
2881: else
2882: {
2883: jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
2884: numberofcmps = 0;
2885: }
2886: }
2887: #ifdef SUPPORT_UCP
2888: else
2889: {
2890: if (*cc == XCL_NOTPROP)
2891: invertcmp ^= 0x1;
2892: cc++;
2893: switch(*cc)
2894: {
2895: case PT_ANY:
2896: if (list != fallbacks)
2897: {
2898: if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))
2899: continue;
2900: }
2901: else if (cc[-1] == XCL_NOTPROP)
2902: continue;
2903: jump = JUMP(SLJIT_JUMP);
2904: break;
2905:
2906: case PT_LAMP:
2907: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
2908: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2909: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
2910: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2911: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
2912: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2913: jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2914: break;
2915:
2916: case PT_GC:
1.1.1.2 ! misho 2917: c = PRIV(ucp_typerange)[(int)cc[1] * 2];
1.1 misho 2918: SET_TYPE_OFFSET(c);
1.1.1.2 ! misho 2919: jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c);
1.1 misho 2920: break;
2921:
2922: case PT_PC:
2923: jump = CMP(SLJIT_C_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset);
2924: break;
2925:
2926: case PT_SC:
2927: jump = CMP(SLJIT_C_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]);
2928: break;
2929:
2930: case PT_SPACE:
2931: case PT_PXSPACE:
2932: if (*cc == PT_SPACE)
2933: {
2934: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2935: jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 11 - charoffset);
2936: }
2937: SET_CHAR_OFFSET(9);
2938: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9);
2939: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2940: if (*cc == PT_SPACE)
2941: JUMPHERE(jump);
2942:
2943: SET_TYPE_OFFSET(ucp_Zl);
2944: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
2945: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2946: jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2947: break;
2948:
2949: case PT_WORD:
2950: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset);
2951: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2952: /* ... fall through */
2953:
2954: case PT_ALNUM:
2955: SET_TYPE_OFFSET(ucp_Ll);
2956: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2957: COND_VALUE((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2958: SET_TYPE_OFFSET(ucp_Nd);
2959: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2960: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2961: jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2962: break;
2963: }
2964: cc += 2;
2965: }
2966: #endif
2967:
2968: if (jump != NULL)
2969: add_jump(compiler, compares > 0 ? list : fallbacks, jump);
2970: }
2971:
2972: if (found != NULL)
2973: set_jumps(found, LABEL());
2974: }
2975:
2976: #undef SET_TYPE_OFFSET
2977: #undef SET_CHAR_OFFSET
2978:
2979: #endif
2980:
1.1.1.2 ! misho 2981: static pcre_uchar *compile_char1_hotpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **fallbacks)
1.1 misho 2982: {
2983: DEFINE_COMPILER;
2984: int length;
2985: unsigned int c, oc, bit;
2986: compare_context context;
2987: struct sljit_jump *jump[4];
1.1.1.2 ! misho 2988: #ifdef SUPPORT_UTF
1.1 misho 2989: struct sljit_label *label;
2990: #ifdef SUPPORT_UCP
1.1.1.2 ! misho 2991: pcre_uchar propdata[5];
1.1 misho 2992: #endif
2993: #endif
2994:
2995: switch(type)
2996: {
2997: case OP_SOD:
2998: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2999: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
3000: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
3001: return cc;
3002:
3003: case OP_SOM:
3004: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
3005: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
3006: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
3007: return cc;
3008:
3009: case OP_NOT_WORD_BOUNDARY:
3010: case OP_WORD_BOUNDARY:
3011: add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
3012: add_jump(compiler, fallbacks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
3013: return cc;
3014:
3015: case OP_NOT_DIGIT:
3016: case OP_DIGIT:
3017: check_input_end(common, fallbacks);
3018: read_char8_type(common);
3019: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
3020: add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
3021: return cc;
3022:
3023: case OP_NOT_WHITESPACE:
3024: case OP_WHITESPACE:
3025: check_input_end(common, fallbacks);
3026: read_char8_type(common);
3027: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
3028: add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
3029: return cc;
3030:
3031: case OP_NOT_WORDCHAR:
3032: case OP_WORDCHAR:
3033: check_input_end(common, fallbacks);
3034: read_char8_type(common);
3035: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
3036: add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
3037: return cc;
3038:
3039: case OP_ANY:
3040: check_input_end(common, fallbacks);
3041: read_char(common);
3042: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3043: {
3044: jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
3045: jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 ! misho 3046: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 3047: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));
3048: JUMPHERE(jump[1]);
3049: JUMPHERE(jump[0]);
3050: }
3051: else
3052: check_newlinechar(common, common->nltype, fallbacks, TRUE);
3053: return cc;
3054:
3055: case OP_ALLANY:
3056: check_input_end(common, fallbacks);
1.1.1.2 ! misho 3057: #ifdef SUPPORT_UTF
! 3058: if (common->utf)
1.1 misho 3059: {
1.1.1.2 ! misho 3060: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
! 3061: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
! 3062: #ifdef COMPILE_PCRE8
1.1 misho 3063: jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.1.1.2 ! misho 3064: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
1.1 misho 3065: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1.1.1.2 ! misho 3066: #else /* COMPILE_PCRE8 */
! 3067: #ifdef COMPILE_PCRE16
! 3068: jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
! 3069: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
! 3070: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
! 3071: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
! 3072: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
! 3073: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
! 3074: #endif /* COMPILE_PCRE16 */
! 3075: #endif /* COMPILE_PCRE8 */
1.1 misho 3076: JUMPHERE(jump[0]);
3077: return cc;
3078: }
3079: #endif
1.1.1.2 ! misho 3080: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 3081: return cc;
3082:
3083: case OP_ANYBYTE:
3084: check_input_end(common, fallbacks);
1.1.1.2 ! misho 3085: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 3086: return cc;
3087:
1.1.1.2 ! misho 3088: #ifdef SUPPORT_UTF
1.1 misho 3089: #ifdef SUPPORT_UCP
3090: case OP_NOTPROP:
3091: case OP_PROP:
3092: propdata[0] = 0;
3093: propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;
3094: propdata[2] = cc[0];
3095: propdata[3] = cc[1];
3096: propdata[4] = XCL_END;
3097: compile_xclass_hotpath(common, propdata, fallbacks);
3098: return cc + 2;
3099: #endif
3100: #endif
3101:
3102: case OP_ANYNL:
3103: check_input_end(common, fallbacks);
3104: read_char(common);
3105: jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
3106: jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 ! misho 3107: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 3108: jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
1.1.1.2 ! misho 3109: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 3110: jump[3] = JUMP(SLJIT_JUMP);
3111: JUMPHERE(jump[0]);
3112: check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE);
3113: JUMPHERE(jump[1]);
3114: JUMPHERE(jump[2]);
3115: JUMPHERE(jump[3]);
3116: return cc;
3117:
3118: case OP_NOT_HSPACE:
3119: case OP_HSPACE:
3120: check_input_end(common, fallbacks);
3121: read_char(common);
3122: add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
3123: add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
3124: return cc;
3125:
3126: case OP_NOT_VSPACE:
3127: case OP_VSPACE:
3128: check_input_end(common, fallbacks);
3129: read_char(common);
3130: add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
3131: add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
3132: return cc;
3133:
3134: #ifdef SUPPORT_UCP
3135: case OP_EXTUNI:
3136: check_input_end(common, fallbacks);
3137: read_char(common);
3138: add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
3139: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
3140: add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc));
3141:
3142: label = LABEL();
3143: jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
3144: OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
3145: read_char(common);
3146: add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
3147: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
3148: CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc, label);
3149:
3150: OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
3151: JUMPHERE(jump[0]);
3152: return cc;
3153: #endif
3154:
3155: case OP_EODN:
3156: jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
3157: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3158: {
1.1.1.2 ! misho 3159: OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
! 3160: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1.1 misho 3161: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
1.1.1.2 ! misho 3162: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1 misho 3163: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
3164: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
3165: }
3166: else if (common->nltype == NLTYPE_FIXED)
3167: {
1.1.1.2 ! misho 3168: OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
! 3169: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1.1 misho 3170: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
3171: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
3172: }
3173: else
3174: {
1.1.1.2 ! misho 3175: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1.1 misho 3176: jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
1.1.1.2 ! misho 3177: OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
1.1 misho 3178: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
3179: jump[2] = JUMP(SLJIT_C_GREATER);
3180: add_jump(compiler, fallbacks, JUMP(SLJIT_C_LESS));
1.1.1.2 ! misho 3181: /* Equal. */
! 3182: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1 misho 3183: jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
3184: add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP));
3185:
3186: JUMPHERE(jump[1]);
3187: if (common->nltype == NLTYPE_ANYCRLF)
3188: {
1.1.1.2 ! misho 3189: OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 3190: add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0));
3191: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
3192: }
3193: else
3194: {
3195: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0);
3196: read_char(common);
3197: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
3198: add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
3199: add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
3200: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
3201: }
3202: JUMPHERE(jump[2]);
3203: JUMPHERE(jump[3]);
3204: }
3205: JUMPHERE(jump[0]);
3206: return cc;
3207:
3208: case OP_EOD:
3209: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
3210: return cc;
3211:
3212: case OP_CIRC:
3213: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3214: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
3215: add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0));
3216: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
3217: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3218: return cc;
3219:
3220: case OP_CIRCM:
3221: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3222: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
3223: jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0);
3224: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
3225: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3226: jump[0] = JUMP(SLJIT_JUMP);
3227: JUMPHERE(jump[1]);
3228:
1.1.1.2 ! misho 3229: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, STR_PTR, 0, STR_END, 0));
1.1 misho 3230: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3231: {
1.1.1.2 ! misho 3232: OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
1.1 misho 3233: add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0));
1.1.1.2 ! misho 3234: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
! 3235: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
1.1 misho 3236: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
3237: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
3238: }
3239: else
3240: {
3241: skip_char_back(common);
3242: read_char(common);
3243: check_newlinechar(common, common->nltype, fallbacks, FALSE);
3244: }
3245: JUMPHERE(jump[0]);
3246: return cc;
3247:
3248: case OP_DOLL:
3249: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3250: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
3251: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3252:
3253: if (!common->endonly)
3254: compile_char1_hotpath(common, OP_EODN, cc, fallbacks);
3255: else
3256: add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
3257: return cc;
3258:
3259: case OP_DOLLM:
3260: jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
3261: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3262: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
3263: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3264: jump[0] = JUMP(SLJIT_JUMP);
3265: JUMPHERE(jump[1]);
3266:
3267: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3268: {
1.1.1.2 ! misho 3269: OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
1.1 misho 3270: add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0));
1.1.1.2 ! misho 3271: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
! 3272: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1 misho 3273: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
3274: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
3275: }
3276: else
3277: {
3278: peek_char(common);
3279: check_newlinechar(common, common->nltype, fallbacks, FALSE);
3280: }
3281: JUMPHERE(jump[0]);
3282: return cc;
3283:
3284: case OP_CHAR:
3285: case OP_CHARI:
3286: length = 1;
1.1.1.2 ! misho 3287: #ifdef SUPPORT_UTF
! 3288: if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);
1.1 misho 3289: #endif
3290: if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)
3291: {
1.1.1.2 ! misho 3292: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
1.1 misho 3293: add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3294:
1.1.1.2 ! misho 3295: context.length = IN_UCHARS(length);
1.1 misho 3296: context.sourcereg = -1;
3297: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
1.1.1.2 ! misho 3298: context.ucharptr = 0;
1.1 misho 3299: #endif
3300: return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks);
3301: }
1.1.1.2 ! misho 3302: check_input_end(common, fallbacks);
1.1 misho 3303: read_char(common);
1.1.1.2 ! misho 3304: #ifdef SUPPORT_UTF
! 3305: if (common->utf)
1.1 misho 3306: {
3307: GETCHAR(c, cc);
3308: }
3309: else
3310: #endif
3311: c = *cc;
3312: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c);
3313: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3314: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c));
3315: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3316: add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
3317: return cc + length;
3318:
3319: case OP_NOT:
3320: case OP_NOTI:
1.1.1.2 ! misho 3321: check_input_end(common, fallbacks);
1.1 misho 3322: length = 1;
1.1.1.2 ! misho 3323: #ifdef SUPPORT_UTF
! 3324: if (common->utf)
1.1 misho 3325: {
1.1.1.2 ! misho 3326: #ifdef COMPILE_PCRE8
! 3327: c = *cc;
! 3328: if (c < 128)
1.1 misho 3329: {
3330: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
3331: if (type == OP_NOT || !char_has_othercase(common, cc))
3332: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3333: else
3334: {
3335: /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
3336: OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20);
3337: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20));
3338: }
3339: /* Skip the variable-length character. */
1.1.1.2 ! misho 3340: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 3341: jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.1.1.2 ! misho 3342: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
1.1 misho 3343: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
3344: JUMPHERE(jump[0]);
1.1.1.2 ! misho 3345: return cc + 1;
1.1 misho 3346: }
3347: else
1.1.1.2 ! misho 3348: #endif /* COMPILE_PCRE8 */
! 3349: {
! 3350: GETCHARLEN(c, cc, length);
1.1 misho 3351: read_char(common);
1.1.1.2 ! misho 3352: }
1.1 misho 3353: }
3354: else
1.1.1.2 ! misho 3355: #endif /* SUPPORT_UTF */
1.1 misho 3356: {
1.1.1.2 ! misho 3357: read_char(common);
1.1 misho 3358: c = *cc;
3359: }
3360:
3361: if (type == OP_NOT || !char_has_othercase(common, cc))
3362: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3363: else
3364: {
3365: oc = char_othercase(common, c);
3366: bit = c ^ oc;
3367: if (ispowerof2(bit))
3368: {
3369: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
3370: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
3371: }
3372: else
3373: {
3374: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3375: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc));
3376: }
3377: }
1.1.1.2 ! misho 3378: return cc + 1;
1.1 misho 3379:
3380: case OP_CLASS:
3381: case OP_NCLASS:
3382: check_input_end(common, fallbacks);
3383: read_char(common);
1.1.1.2 ! misho 3384: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1 misho 3385: jump[0] = NULL;
1.1.1.2 ! misho 3386: #ifdef COMPILE_PCRE8
! 3387: /* This check only affects 8 bit mode. In other modes, we
! 3388: always need to compare the value with 255. */
! 3389: if (common->utf)
! 3390: #endif /* COMPILE_PCRE8 */
1.1 misho 3391: {
3392: jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
3393: if (type == OP_CLASS)
3394: {
3395: add_jump(compiler, fallbacks, jump[0]);
3396: jump[0] = NULL;
3397: }
3398: }
1.1.1.2 ! misho 3399: #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
1.1 misho 3400: OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
3401: OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
3402: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
3403: OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
3404: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
3405: add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
1.1.1.2 ! misho 3406: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1 misho 3407: if (jump[0] != NULL)
3408: JUMPHERE(jump[0]);
1.1.1.2 ! misho 3409: #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
! 3410: return cc + 32 / sizeof(pcre_uchar);
1.1 misho 3411:
1.1.1.2 ! misho 3412: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
1.1 misho 3413: case OP_XCLASS:
3414: compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks);
3415: return cc + GET(cc, 0) - 1;
3416: #endif
3417:
3418: case OP_REVERSE:
3419: length = GET(cc, 0);
3420: SLJIT_ASSERT(length > 0);
3421: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1.1.1.2 ! misho 3422: #ifdef SUPPORT_UTF
! 3423: if (common->utf)
1.1 misho 3424: {
1.1.1.2 ! misho 3425: OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
1.1 misho 3426: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
3427: label = LABEL();
1.1.1.2 ! misho 3428: add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0));
1.1 misho 3429: skip_char_back(common);
3430: OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
3431: JUMPTO(SLJIT_C_NOT_ZERO, label);
3432: return cc + LINK_SIZE;
3433: }
3434: #endif
1.1.1.2 ! misho 3435: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
! 3436: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
1.1 misho 3437: add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0));
3438: return cc + LINK_SIZE;
3439: }
3440: SLJIT_ASSERT_STOP();
3441: return cc;
3442: }
3443:
1.1.1.2 ! misho 3444: static SLJIT_INLINE pcre_uchar *compile_charn_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **fallbacks)
1.1 misho 3445: {
3446: /* This function consumes at least one input character. */
3447: /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
3448: DEFINE_COMPILER;
1.1.1.2 ! misho 3449: pcre_uchar *ccbegin = cc;
1.1 misho 3450: compare_context context;
3451: int size;
3452:
3453: context.length = 0;
3454: do
3455: {
3456: if (cc >= ccend)
3457: break;
3458:
3459: if (*cc == OP_CHAR)
3460: {
3461: size = 1;
1.1.1.2 ! misho 3462: #ifdef SUPPORT_UTF
! 3463: if (common->utf && HAS_EXTRALEN(cc[1]))
! 3464: size += GET_EXTRALEN(cc[1]);
1.1 misho 3465: #endif
3466: }
3467: else if (*cc == OP_CHARI)
3468: {
3469: size = 1;
1.1.1.2 ! misho 3470: #ifdef SUPPORT_UTF
! 3471: if (common->utf)
1.1 misho 3472: {
3473: if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3474: size = 0;
1.1.1.2 ! misho 3475: else if (HAS_EXTRALEN(cc[1]))
! 3476: size += GET_EXTRALEN(cc[1]);
1.1 misho 3477: }
3478: else
3479: #endif
3480: if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3481: size = 0;
3482: }
3483: else
3484: size = 0;
3485:
3486: cc += 1 + size;
1.1.1.2 ! misho 3487: context.length += IN_UCHARS(size);
1.1 misho 3488: }
3489: while (size > 0 && context.length <= 128);
3490:
3491: cc = ccbegin;
3492: if (context.length > 0)
3493: {
3494: /* We have a fixed-length byte sequence. */
3495: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);
3496: add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3497:
3498: context.sourcereg = -1;
3499: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
1.1.1.2 ! misho 3500: context.ucharptr = 0;
1.1 misho 3501: #endif
3502: do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, fallbacks); while (context.length > 0);
3503: return cc;
3504: }
3505:
3506: /* A non-fixed length character will be checked if length == 0. */
3507: return compile_char1_hotpath(common, *cc, cc + 1, fallbacks);
3508: }
3509:
1.1.1.2 ! misho 3510: static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks)
1.1 misho 3511: {
3512: DEFINE_COMPILER;
3513: int offset = GET2(cc, 1) << 1;
3514:
3515: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
3516: if (!common->jscript_compat)
3517: {
3518: if (fallbacks == NULL)
3519: {
3520: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
3521: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3522: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3523: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3524: return JUMP(SLJIT_C_NOT_ZERO);
3525: }
3526: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
3527: }
3528: return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3529: }
3530:
3531: /* Forward definitions. */
1.1.1.2 ! misho 3532: static void compile_hotpath(compiler_common *, pcre_uchar *, pcre_uchar *, fallback_common *);
1.1 misho 3533: static void compile_fallbackpath(compiler_common *, struct fallback_common *);
3534:
3535: #define PUSH_FALLBACK(size, ccstart, error) \
3536: do \
3537: { \
3538: fallback = sljit_alloc_memory(compiler, (size)); \
3539: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3540: return error; \
3541: memset(fallback, 0, size); \
3542: fallback->prev = parent->top; \
3543: fallback->cc = (ccstart); \
3544: parent->top = fallback; \
3545: } \
3546: while (0)
3547:
3548: #define PUSH_FALLBACK_NOVALUE(size, ccstart) \
3549: do \
3550: { \
3551: fallback = sljit_alloc_memory(compiler, (size)); \
3552: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3553: return; \
3554: memset(fallback, 0, size); \
3555: fallback->prev = parent->top; \
3556: fallback->cc = (ccstart); \
3557: parent->top = fallback; \
3558: } \
3559: while (0)
3560:
3561: #define FALLBACK_AS(type) ((type*)fallback)
3562:
1.1.1.2 ! misho 3563: static pcre_uchar *compile_ref_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail)
1.1 misho 3564: {
3565: DEFINE_COMPILER;
3566: int offset = GET2(cc, 1) << 1;
3567: struct sljit_jump *jump = NULL;
3568:
3569: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
3570: if (withchecks && !common->jscript_compat)
3571: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
3572:
1.1.1.2 ! misho 3573: #if defined SUPPORT_UTF && defined SUPPORT_UCP
! 3574: if (common->utf && *cc == OP_REFI)
1.1 misho 3575: {
3576: SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3);
3577: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3578: if (withchecks)
3579: jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0);
3580:
3581: /* Needed to save important temporary registers. */
3582: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
3583: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);
3584: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, ptr), STR_PTR, 0);
1.1.1.2 ! misho 3585: sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));
1.1 misho 3586: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
3587: add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
3588: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
3589: }
3590: else
1.1.1.2 ! misho 3591: #endif /* SUPPORT_UTF && SUPPORT_UCP */
1.1 misho 3592: {
3593: OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
3594: if (withchecks)
3595: jump = JUMP(SLJIT_C_ZERO);
3596: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
3597:
3598: add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3599: add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
3600: add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3601: }
3602:
3603: if (jump != NULL)
3604: {
3605: if (emptyfail)
3606: add_jump(compiler, fallbacks, jump);
3607: else
3608: JUMPHERE(jump);
3609: }
1.1.1.2 ! misho 3610: return cc + 1 + IMM2_SIZE;
1.1 misho 3611: }
3612:
1.1.1.2 ! misho 3613: static SLJIT_INLINE pcre_uchar *compile_ref_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
1.1 misho 3614: {
3615: DEFINE_COMPILER;
3616: fallback_common *fallback;
1.1.1.2 ! misho 3617: pcre_uchar type;
1.1 misho 3618: struct sljit_label *label;
3619: struct sljit_jump *zerolength;
3620: struct sljit_jump *jump = NULL;
1.1.1.2 ! misho 3621: pcre_uchar *ccbegin = cc;
1.1 misho 3622: int min = 0, max = 0;
3623: BOOL minimize;
3624:
3625: PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL);
3626:
1.1.1.2 ! misho 3627: type = cc[1 + IMM2_SIZE];
1.1 misho 3628: minimize = (type & 0x1) != 0;
3629: switch(type)
3630: {
3631: case OP_CRSTAR:
3632: case OP_CRMINSTAR:
3633: min = 0;
3634: max = 0;
1.1.1.2 ! misho 3635: cc += 1 + IMM2_SIZE + 1;
1.1 misho 3636: break;
3637: case OP_CRPLUS:
3638: case OP_CRMINPLUS:
3639: min = 1;
3640: max = 0;
1.1.1.2 ! misho 3641: cc += 1 + IMM2_SIZE + 1;
1.1 misho 3642: break;
3643: case OP_CRQUERY:
3644: case OP_CRMINQUERY:
3645: min = 0;
3646: max = 1;
1.1.1.2 ! misho 3647: cc += 1 + IMM2_SIZE + 1;
1.1 misho 3648: break;
3649: case OP_CRRANGE:
3650: case OP_CRMINRANGE:
1.1.1.2 ! misho 3651: min = GET2(cc, 1 + IMM2_SIZE + 1);
! 3652: max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE);
! 3653: cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE;
1.1 misho 3654: break;
3655: default:
3656: SLJIT_ASSERT_STOP();
3657: break;
3658: }
3659:
3660: if (!minimize)
3661: {
3662: if (min == 0)
3663: {
3664: allocate_stack(common, 2);
3665: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3666: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
3667: /* Temporary release of STR_PTR. */
3668: OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3669: zerolength = compile_ref_checks(common, ccbegin, NULL);
3670: /* Restore if not zero length. */
3671: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3672: }
3673: else
3674: {
3675: allocate_stack(common, 1);
3676: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3677: zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);
3678: }
3679:
3680: if (min > 1 || max > 1)
3681: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
3682:
3683: label = LABEL();
3684: compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, FALSE, FALSE);
3685:
3686: if (min > 1 || max > 1)
3687: {
3688: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
3689: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
3690: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
3691: if (min > 1)
3692: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label);
3693: if (max > 1)
3694: {
3695: jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);
3696: allocate_stack(common, 1);
3697: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3698: JUMPTO(SLJIT_JUMP, label);
3699: JUMPHERE(jump);
3700: }
3701: }
3702:
3703: if (max == 0)
3704: {
3705: /* Includes min > 1 case as well. */
3706: allocate_stack(common, 1);
3707: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3708: JUMPTO(SLJIT_JUMP, label);
3709: }
3710:
3711: JUMPHERE(zerolength);
3712: FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
3713:
3714: decrease_call_count(common);
3715: return cc;
3716: }
3717:
3718: allocate_stack(common, 2);
3719: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3720: if (type != OP_CRMINSTAR)
3721: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
3722:
3723: if (min == 0)
3724: {
3725: zerolength = compile_ref_checks(common, ccbegin, NULL);
3726: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3727: jump = JUMP(SLJIT_JUMP);
3728: }
3729: else
3730: zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);
3731:
3732: FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
3733: if (max > 0)
3734: add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
3735:
3736: compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, TRUE, TRUE);
3737: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3738:
3739: if (min > 1)
3740: {
3741: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3742: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
3743: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
3744: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, FALLBACK_AS(iterator_fallback)->hotpath);
3745: }
3746: else if (max > 0)
3747: OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
3748:
3749: if (jump != NULL)
3750: JUMPHERE(jump);
3751: JUMPHERE(zerolength);
3752:
3753: decrease_call_count(common);
3754: return cc;
3755: }
3756:
1.1.1.2 ! misho 3757: static SLJIT_INLINE pcre_uchar *compile_recurse_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
1.1 misho 3758: {
3759: DEFINE_COMPILER;
3760: fallback_common *fallback;
3761: recurse_entry *entry = common->entries;
3762: recurse_entry *prev = NULL;
3763: int start = GET(cc, 1);
3764:
3765: PUSH_FALLBACK(sizeof(recurse_fallback), cc, NULL);
3766: while (entry != NULL)
3767: {
3768: if (entry->start == start)
3769: break;
3770: prev = entry;
3771: entry = entry->next;
3772: }
3773:
3774: if (entry == NULL)
3775: {
3776: entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));
3777: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3778: return NULL;
3779: entry->next = NULL;
3780: entry->entry = NULL;
3781: entry->calls = NULL;
3782: entry->start = start;
3783:
3784: if (prev != NULL)
3785: prev->next = entry;
3786: else
3787: common->entries = entry;
3788: }
3789:
3790: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
3791: allocate_stack(common, 1);
3792: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
3793:
3794: if (entry->entry == NULL)
3795: add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL));
3796: else
3797: JUMPTO(SLJIT_FAST_CALL, entry->entry);
3798: /* Leave if the match is failed. */
3799: add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0));
3800: return cc + 1 + LINK_SIZE;
3801: }
3802:
1.1.1.2 ! misho 3803: static pcre_uchar *compile_assert_hotpath(compiler_common *common, pcre_uchar *cc, assert_fallback *fallback, BOOL conditional)
1.1 misho 3804: {
3805: DEFINE_COMPILER;
3806: int framesize;
3807: int localptr;
3808: fallback_common altfallback;
1.1.1.2 ! misho 3809: pcre_uchar *ccbegin;
! 3810: pcre_uchar opcode;
! 3811: pcre_uchar bra = OP_BRA;
1.1 misho 3812: jump_list *tmp = NULL;
3813: jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks;
3814: jump_list **found;
3815: /* Saving previous accept variables. */
3816: struct sljit_label *save_acceptlabel = common->acceptlabel;
3817: struct sljit_jump *jump;
3818: struct sljit_jump *brajump = NULL;
3819: jump_list *save_accept = common->accept;
3820:
3821: if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
3822: {
3823: SLJIT_ASSERT(!conditional);
3824: bra = *cc;
3825: cc++;
3826: }
1.1.1.2 ! misho 3827: localptr = PRIV_DATA(cc);
1.1 misho 3828: SLJIT_ASSERT(localptr != 0);
3829: framesize = get_framesize(common, cc, FALSE);
3830: fallback->framesize = framesize;
3831: fallback->localptr = localptr;
3832: opcode = *cc;
3833: SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);
3834: found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;
3835: ccbegin = cc;
3836: cc += GET(cc, 1);
3837:
3838: if (bra == OP_BRAMINZERO)
3839: {
3840: /* This is a braminzero fallback path. */
3841: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3842: free_stack(common, 1);
3843: brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3844: }
3845:
3846: if (framesize < 0)
3847: {
3848: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
3849: allocate_stack(common, 1);
3850: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3851: }
3852: else
3853: {
3854: allocate_stack(common, framesize + 2);
3855: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3856: OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1));
3857: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
3858: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3859: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
3860: init_frame(common, ccbegin, framesize + 1, 2, FALSE);
3861: }
3862:
3863: memset(&altfallback, 0, sizeof(fallback_common));
3864: while (1)
3865: {
3866: common->acceptlabel = NULL;
3867: common->accept = NULL;
3868: altfallback.top = NULL;
3869: altfallback.topfallbacks = NULL;
3870:
3871: if (*ccbegin == OP_ALT)
3872: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3873:
3874: altfallback.cc = ccbegin;
3875: compile_hotpath(common, ccbegin + 1 + LINK_SIZE, cc, &altfallback);
3876: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3877: {
3878: common->acceptlabel = save_acceptlabel;
3879: common->accept = save_accept;
3880: return NULL;
3881: }
3882: common->acceptlabel = LABEL();
3883: if (common->accept != NULL)
3884: set_jumps(common->accept, common->acceptlabel);
3885:
3886: /* Reset stack. */
3887: if (framesize < 0)
3888: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3889: else {
3890: if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional)
3891: {
3892: /* We don't need to keep the STR_PTR, only the previous localptr. */
3893: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w));
3894: }
3895: else
3896: {
3897: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3898: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
3899: }
3900: }
3901:
3902: if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
3903: {
3904: /* We know that STR_PTR was stored on the top of the stack. */
3905: if (conditional)
3906: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3907: else if (bra == OP_BRAZERO)
3908: {
3909: if (framesize < 0)
3910: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3911: else
3912: {
3913: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3914: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w));
3915: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3916: }
3917: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3918: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3919: }
3920: else if (framesize >= 0)
3921: {
3922: /* For OP_BRA and OP_BRAMINZERO. */
3923: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3924: }
3925: }
3926: add_jump(compiler, found, JUMP(SLJIT_JUMP));
3927:
3928: compile_fallbackpath(common, altfallback.top);
3929: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3930: {
3931: common->acceptlabel = save_acceptlabel;
3932: common->accept = save_accept;
3933: return NULL;
3934: }
3935: set_jumps(altfallback.topfallbacks, LABEL());
3936:
3937: if (*cc != OP_ALT)
3938: break;
3939:
3940: ccbegin = cc;
3941: cc += GET(cc, 1);
3942: }
3943: /* None of them matched. */
3944:
3945: if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
3946: {
3947: /* Assert is failed. */
3948: if (conditional || bra == OP_BRAZERO)
3949: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3950:
3951: if (framesize < 0)
3952: {
3953: /* The topmost item should be 0. */
3954: if (bra == OP_BRAZERO)
3955: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3956: else
3957: free_stack(common, 1);
3958: }
3959: else
3960: {
3961: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3962: /* The topmost item should be 0. */
3963: if (bra == OP_BRAZERO)
3964: {
3965: free_stack(common, framesize + 1);
3966: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3967: }
3968: else
3969: free_stack(common, framesize + 2);
3970: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3971: }
3972: jump = JUMP(SLJIT_JUMP);
3973: if (bra != OP_BRAZERO)
3974: add_jump(compiler, target, jump);
3975:
3976: /* Assert is successful. */
3977: set_jumps(tmp, LABEL());
3978: if (framesize < 0)
3979: {
3980: /* We know that STR_PTR was stored on the top of the stack. */
3981: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3982: /* Keep the STR_PTR on the top of the stack. */
3983: if (bra == OP_BRAZERO)
3984: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3985: else if (bra == OP_BRAMINZERO)
3986: {
3987: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3988: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3989: }
3990: }
3991: else
3992: {
3993: if (bra == OP_BRA)
3994: {
3995: /* We don't need to keep the STR_PTR, only the previous localptr. */
3996: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w));
3997: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3998: }
3999: else
4000: {
4001: /* We don't need to keep the STR_PTR, only the previous localptr. */
4002: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_w));
4003: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4004: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0);
4005: }
4006: }
4007:
4008: if (bra == OP_BRAZERO)
4009: {
4010: fallback->hotpath = LABEL();
4011: sljit_set_label(jump, fallback->hotpath);
4012: }
4013: else if (bra == OP_BRAMINZERO)
4014: {
4015: JUMPTO(SLJIT_JUMP, fallback->hotpath);
4016: JUMPHERE(brajump);
4017: if (framesize >= 0)
4018: {
4019: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4020: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
4021: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
4022: }
4023: set_jumps(fallback->common.topfallbacks, LABEL());
4024: }
4025: }
4026: else
4027: {
4028: /* AssertNot is successful. */
4029: if (framesize < 0)
4030: {
4031: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4032: if (bra != OP_BRA)
4033: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4034: else
4035: free_stack(common, 1);
4036: }
4037: else
4038: {
4039: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4040: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
4041: /* The topmost item should be 0. */
4042: if (bra != OP_BRA)
4043: {
4044: free_stack(common, framesize + 1);
4045: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4046: }
4047: else
4048: free_stack(common, framesize + 2);
4049: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
4050: }
4051:
4052: if (bra == OP_BRAZERO)
4053: fallback->hotpath = LABEL();
4054: else if (bra == OP_BRAMINZERO)
4055: {
4056: JUMPTO(SLJIT_JUMP, fallback->hotpath);
4057: JUMPHERE(brajump);
4058: }
4059:
4060: if (bra != OP_BRA)
4061: {
4062: SLJIT_ASSERT(found == &fallback->common.topfallbacks);
4063: set_jumps(fallback->common.topfallbacks, LABEL());
4064: fallback->common.topfallbacks = NULL;
4065: }
4066: }
4067:
4068: common->acceptlabel = save_acceptlabel;
4069: common->accept = save_accept;
4070: return cc + 1 + LINK_SIZE;
4071: }
4072:
1.1.1.2 ! misho 4073: static sljit_w SLJIT_CALL do_searchovector(sljit_w refno, sljit_w* locals, pcre_uchar *name_table)
1.1 misho 4074: {
4075: int condition = FALSE;
1.1.1.2 ! misho 4076: pcre_uchar *slotA = name_table;
! 4077: pcre_uchar *slotB;
1.1 misho 4078: sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)];
4079: sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)];
4080: sljit_w no_capture;
4081: int i;
4082:
4083: locals += OVECTOR_START / sizeof(sljit_w);
4084: no_capture = locals[1];
4085:
4086: for (i = 0; i < name_count; i++)
4087: {
4088: if (GET2(slotA, 0) == refno) break;
4089: slotA += name_entry_size;
4090: }
4091:
4092: if (i < name_count)
4093: {
4094: /* Found a name for the number - there can be only one; duplicate names
4095: for different numbers are allowed, but not vice versa. First scan down
4096: for duplicates. */
4097:
4098: slotB = slotA;
4099: while (slotB > name_table)
4100: {
4101: slotB -= name_entry_size;
1.1.1.2 ! misho 4102: if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
1.1 misho 4103: {
4104: condition = locals[GET2(slotB, 0) << 1] != no_capture;
4105: if (condition) break;
4106: }
4107: else break;
4108: }
4109:
4110: /* Scan up for duplicates */
4111: if (!condition)
4112: {
4113: slotB = slotA;
4114: for (i++; i < name_count; i++)
4115: {
4116: slotB += name_entry_size;
1.1.1.2 ! misho 4117: if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
1.1 misho 4118: {
4119: condition = locals[GET2(slotB, 0) << 1] != no_capture;
4120: if (condition) break;
4121: }
4122: else break;
4123: }
4124: }
4125: }
4126: return condition;
4127: }
4128:
1.1.1.2 ! misho 4129: static sljit_w SLJIT_CALL do_searchgroups(sljit_w recno, sljit_w* locals, pcre_uchar *name_table)
1.1 misho 4130: {
4131: int condition = FALSE;
1.1.1.2 ! misho 4132: pcre_uchar *slotA = name_table;
! 4133: pcre_uchar *slotB;
1.1 misho 4134: sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)];
4135: sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)];
4136: sljit_w group_num = locals[POSSESSIVE0 / sizeof(sljit_w)];
4137: int i;
4138:
4139: for (i = 0; i < name_count; i++)
4140: {
4141: if (GET2(slotA, 0) == recno) break;
4142: slotA += name_entry_size;
4143: }
4144:
4145: if (i < name_count)
4146: {
4147: /* Found a name for the number - there can be only one; duplicate
4148: names for different numbers are allowed, but not vice versa. First
4149: scan down for duplicates. */
4150:
4151: slotB = slotA;
4152: while (slotB > name_table)
4153: {
4154: slotB -= name_entry_size;
1.1.1.2 ! misho 4155: if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
1.1 misho 4156: {
4157: condition = GET2(slotB, 0) == group_num;
4158: if (condition) break;
4159: }
4160: else break;
4161: }
4162:
4163: /* Scan up for duplicates */
4164: if (!condition)
4165: {
4166: slotB = slotA;
4167: for (i++; i < name_count; i++)
4168: {
4169: slotB += name_entry_size;
1.1.1.2 ! misho 4170: if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
1.1 misho 4171: {
4172: condition = GET2(slotB, 0) == group_num;
4173: if (condition) break;
4174: }
4175: else break;
4176: }
4177: }
4178: }
4179: return condition;
4180: }
4181:
4182: /*
4183: Handling bracketed expressions is probably the most complex part.
4184:
4185: Stack layout naming characters:
4186: S - Push the current STR_PTR
4187: 0 - Push a 0 (NULL)
4188: A - Push the current STR_PTR. Needed for restoring the STR_PTR
4189: before the next alternative. Not pushed if there are no alternatives.
4190: M - Any values pushed by the current alternative. Can be empty, or anything.
4191: C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.
4192: L - Push the previous local (pointed by localptr) to the stack
4193: () - opional values stored on the stack
4194: ()* - optonal, can be stored multiple times
4195:
4196: The following list shows the regular expression templates, their PCRE byte codes
4197: and stack layout supported by pcre-sljit.
4198:
4199: (?:) OP_BRA | OP_KET A M
4200: () OP_CBRA | OP_KET C M
4201: (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*
4202: OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*
4203: (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*
4204: OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*
4205: ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*
4206: OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*
4207: ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*
4208: OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*
4209: (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )
4210: (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )
4211: ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )
4212: ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )
4213: (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*
4214: OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*
4215: (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*
4216: OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*
4217: ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*
4218: OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*
4219: ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*
4220: OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*
4221:
4222:
4223: Stack layout naming characters:
4224: A - Push the alternative index (starting from 0) on the stack.
4225: Not pushed if there is no alternatives.
4226: M - Any values pushed by the current alternative. Can be empty, or anything.
4227:
4228: The next list shows the possible content of a bracket:
4229: (|) OP_*BRA | OP_ALT ... M A
4230: (?()|) OP_*COND | OP_ALT M A
4231: (?>|) OP_ONCE | OP_ALT ... [stack trace] M A
4232: (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A
4233: Or nothing, if trace is unnecessary
4234: */
4235:
1.1.1.2 ! misho 4236: static pcre_uchar *compile_bracket_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
1.1 misho 4237: {
4238: DEFINE_COMPILER;
4239: fallback_common *fallback;
1.1.1.2 ! misho 4240: pcre_uchar opcode;
1.1 misho 4241: int localptr = 0;
4242: int offset = 0;
4243: int stacksize;
1.1.1.2 ! misho 4244: pcre_uchar *ccbegin;
! 4245: pcre_uchar *hotpath;
! 4246: pcre_uchar bra = OP_BRA;
! 4247: pcre_uchar ket;
1.1 misho 4248: assert_fallback *assert;
4249: BOOL has_alternatives;
4250: struct sljit_jump *jump;
4251: struct sljit_jump *skip;
4252: struct sljit_label *rmaxlabel = NULL;
4253: struct sljit_jump *braminzerojump = NULL;
4254:
4255: PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL);
4256:
4257: if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
4258: {
4259: bra = *cc;
4260: cc++;
4261: opcode = *cc;
4262: }
4263:
4264: opcode = *cc;
4265: ccbegin = cc;
4266: hotpath = ccbegin + 1 + LINK_SIZE;
4267:
4268: if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
4269: {
4270: /* Drop this bracket_fallback. */
4271: parent->top = fallback->prev;
4272: return bracketend(cc);
4273: }
4274:
4275: ket = *(bracketend(cc) - 1 - LINK_SIZE);
4276: SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
4277: SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
4278: cc += GET(cc, 1);
4279:
4280: has_alternatives = *cc == OP_ALT;
4281: if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
4282: {
4283: has_alternatives = (*hotpath == OP_RREF) ? FALSE : TRUE;
4284: if (*hotpath == OP_NRREF)
4285: {
4286: stacksize = GET2(hotpath, 1);
4287: if (common->currententry == NULL || stacksize == RREF_ANY)
4288: has_alternatives = FALSE;
4289: else if (common->currententry->start == 0)
4290: has_alternatives = stacksize != 0;
4291: else
4292: has_alternatives = stacksize != GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
4293: }
4294: }
4295:
4296: if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
4297: opcode = OP_SCOND;
4298: if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
4299: opcode = OP_ONCE;
4300:
4301: if (opcode == OP_CBRA || opcode == OP_SCBRA)
4302: {
4303: /* Capturing brackets has a pre-allocated space. */
4304: offset = GET2(ccbegin, 1 + LINK_SIZE);
4305: localptr = OVECTOR_PRIV(offset);
4306: offset <<= 1;
4307: FALLBACK_AS(bracket_fallback)->localptr = localptr;
1.1.1.2 ! misho 4308: hotpath += IMM2_SIZE;
1.1 misho 4309: }
4310: else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
4311: {
4312: /* Other brackets simply allocate the next entry. */
1.1.1.2 ! misho 4313: localptr = PRIV_DATA(ccbegin);
1.1 misho 4314: SLJIT_ASSERT(localptr != 0);
4315: FALLBACK_AS(bracket_fallback)->localptr = localptr;
4316: if (opcode == OP_ONCE)
4317: FALLBACK_AS(bracket_fallback)->u.framesize = get_framesize(common, ccbegin, FALSE);
4318: }
4319:
4320: /* Instructions before the first alternative. */
4321: stacksize = 0;
4322: if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
4323: stacksize++;
4324: if (bra == OP_BRAZERO)
4325: stacksize++;
4326:
4327: if (stacksize > 0)
4328: allocate_stack(common, stacksize);
4329:
4330: stacksize = 0;
4331: if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
4332: {
4333: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4334: stacksize++;
4335: }
4336:
4337: if (bra == OP_BRAZERO)
4338: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
4339:
4340: if (bra == OP_BRAMINZERO)
4341: {
4342: /* This is a fallback path! (Since the hot-path of OP_BRAMINZERO matches to the empty string) */
4343: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4344: if (ket != OP_KETRMIN)
4345: {
4346: free_stack(common, 1);
4347: braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
4348: }
4349: else
4350: {
4351: if (opcode == OP_ONCE || opcode >= OP_SBRA)
4352: {
4353: jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
4354: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
4355: /* Nothing stored during the first run. */
4356: skip = JUMP(SLJIT_JUMP);
4357: JUMPHERE(jump);
4358: /* Checking zero-length iteration. */
4359: if (opcode != OP_ONCE || FALLBACK_AS(bracket_fallback)->u.framesize < 0)
4360: {
4361: /* When we come from outside, localptr contains the previous STR_PTR. */
4362: braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4363: }
4364: else
4365: {
4366: /* Except when the whole stack frame must be saved. */
4367: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4368: braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w));
4369: }
4370: JUMPHERE(skip);
4371: }
4372: else
4373: {
4374: jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
4375: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
4376: JUMPHERE(jump);
4377: }
4378: }
4379: }
4380:
4381: if (ket == OP_KETRMIN)
4382: FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();
4383:
4384: if (ket == OP_KETRMAX)
4385: {
4386: rmaxlabel = LABEL();
4387: if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)
4388: FALLBACK_AS(bracket_fallback)->althotpath = rmaxlabel;
4389: }
4390:
4391: /* Handling capturing brackets and alternatives. */
4392: if (opcode == OP_ONCE)
4393: {
4394: if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)
4395: {
4396: /* Neither capturing brackets nor recursions are not found in the block. */
4397: if (ket == OP_KETRMIN)
4398: {
4399: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4400: allocate_stack(common, 2);
4401: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4402: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4403: OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
4404: }
4405: else if (ket == OP_KETRMAX || has_alternatives)
4406: {
4407: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4408: allocate_stack(common, 1);
4409: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4410: }
4411: else
4412: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4413: }
4414: else
4415: {
4416: if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives)
4417: {
4418: allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 2);
4419: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4420: OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize + 1));
4421: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4422: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4423: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
4424: init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize + 1, 2, FALSE);
4425: }
4426: else
4427: {
4428: allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 1);
4429: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4430: OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize));
4431: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4432: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4433: init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize, 1, FALSE);
4434: }
4435: }
4436: }
4437: else if (opcode == OP_CBRA || opcode == OP_SCBRA)
4438: {
4439: /* Saving the previous values. */
4440: allocate_stack(common, 3);
4441: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
4442: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4443: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4444: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4445: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4446: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4447: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
4448: }
4449: else if (opcode == OP_SBRA || opcode == OP_SCOND)
4450: {
4451: /* Saving the previous value. */
4452: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4453: allocate_stack(common, 1);
4454: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4455: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
4456: }
4457: else if (has_alternatives)
4458: {
4459: /* Pushing the starting string pointer. */
4460: allocate_stack(common, 1);
4461: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4462: }
4463:
4464: /* Generating code for the first alternative. */
4465: if (opcode == OP_COND || opcode == OP_SCOND)
4466: {
4467: if (*hotpath == OP_CREF)
4468: {
4469: SLJIT_ASSERT(has_alternatives);
4470: add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed),
4471: CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(hotpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
1.1.1.2 ! misho 4472: hotpath += 1 + IMM2_SIZE;
1.1 misho 4473: }
4474: else if (*hotpath == OP_NCREF)
4475: {
4476: SLJIT_ASSERT(has_alternatives);
4477: stacksize = GET2(hotpath, 1);
4478: jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
4479:
4480: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);
4481: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);
4482: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);
4483: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize);
4484: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0);
4485: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);
4486: sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector));
4487: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
4488: add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));
4489:
4490: JUMPHERE(jump);
1.1.1.2 ! misho 4491: hotpath += 1 + IMM2_SIZE;
1.1 misho 4492: }
4493: else if (*hotpath == OP_RREF || *hotpath == OP_NRREF)
4494: {
4495: /* Never has other case. */
4496: FALLBACK_AS(bracket_fallback)->u.condfailed = NULL;
4497:
4498: stacksize = GET2(hotpath, 1);
4499: if (common->currententry == NULL)
4500: stacksize = 0;
4501: else if (stacksize == RREF_ANY)
4502: stacksize = 1;
4503: else if (common->currententry->start == 0)
4504: stacksize = stacksize == 0;
4505: else
4506: stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
4507:
4508: if (*hotpath == OP_RREF || stacksize || common->currententry == NULL)
4509: {
4510: SLJIT_ASSERT(!has_alternatives);
4511: if (stacksize != 0)
1.1.1.2 ! misho 4512: hotpath += 1 + IMM2_SIZE;
1.1 misho 4513: else
4514: {
4515: if (*cc == OP_ALT)
4516: {
4517: hotpath = cc + 1 + LINK_SIZE;
4518: cc += GET(cc, 1);
4519: }
4520: else
4521: hotpath = cc;
4522: }
4523: }
4524: else
4525: {
4526: SLJIT_ASSERT(has_alternatives);
4527:
4528: stacksize = GET2(hotpath, 1);
4529: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);
4530: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);
4531: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);
4532: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE));
4533: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize);
4534: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0);
4535: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);
4536: sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups));
4537: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
4538: add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));
1.1.1.2 ! misho 4539: hotpath += 1 + IMM2_SIZE;
1.1 misho 4540: }
4541: }
4542: else
4543: {
4544: SLJIT_ASSERT(has_alternatives && *hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT);
4545: /* Similar code as PUSH_FALLBACK macro. */
4546: assert = sljit_alloc_memory(compiler, sizeof(assert_fallback));
4547: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4548: return NULL;
4549: memset(assert, 0, sizeof(assert_fallback));
4550: assert->common.cc = hotpath;
4551: FALLBACK_AS(bracket_fallback)->u.assert = assert;
4552: hotpath = compile_assert_hotpath(common, hotpath, assert, TRUE);
4553: }
4554: }
4555:
4556: compile_hotpath(common, hotpath, cc, fallback);
4557: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4558: return NULL;
4559:
4560: if (opcode == OP_ONCE)
4561: {
4562: if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)
4563: {
4564: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4565: /* TMP2 which is set here used by OP_KETRMAX below. */
4566: if (ket == OP_KETRMAX)
4567: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
4568: else if (ket == OP_KETRMIN)
4569: {
4570: /* Move the STR_PTR to the localptr. */
4571: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
4572: }
4573: }
4574: else
4575: {
4576: stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1;
4577: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (FALLBACK_AS(bracket_fallback)->u.framesize + stacksize) * sizeof(sljit_w));
4578: if (ket == OP_KETRMAX)
4579: {
4580: /* TMP2 which is set here used by OP_KETRMAX below. */
4581: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4582: }
4583: }
4584: }
4585:
4586: stacksize = 0;
4587: if (ket != OP_KET || bra != OP_BRA)
4588: stacksize++;
4589: if (has_alternatives && opcode != OP_ONCE)
4590: stacksize++;
4591:
4592: if (stacksize > 0)
4593: allocate_stack(common, stacksize);
4594:
4595: stacksize = 0;
4596: if (ket != OP_KET)
4597: {
4598: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
4599: stacksize++;
4600: }
4601: else if (bra != OP_BRA)
4602: {
4603: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4604: stacksize++;
4605: }
4606:
4607: if (has_alternatives)
4608: {
4609: if (opcode != OP_ONCE)
4610: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4611: if (ket != OP_KETRMAX)
4612: FALLBACK_AS(bracket_fallback)->althotpath = LABEL();
4613: }
4614:
4615: /* Must be after the hotpath label. */
4616: if (offset != 0)
4617: {
4618: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4619: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
4620: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
4621: }
4622:
4623: if (ket == OP_KETRMAX)
4624: {
4625: if (opcode == OP_ONCE || opcode >= OP_SBRA)
4626: {
4627: if (has_alternatives)
4628: FALLBACK_AS(bracket_fallback)->althotpath = LABEL();
4629: /* Checking zero-length iteration. */
4630: if (opcode != OP_ONCE)
4631: CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel);
4632: else
4633: /* TMP2 must contain the starting STR_PTR. */
4634: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);
4635: }
4636: else
4637: JUMPTO(SLJIT_JUMP, rmaxlabel);
4638: FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();
4639: }
4640:
4641: if (bra == OP_BRAZERO)
4642: FALLBACK_AS(bracket_fallback)->zerohotpath = LABEL();
4643:
4644: if (bra == OP_BRAMINZERO)
4645: {
4646: /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */
4647: JUMPTO(SLJIT_JUMP, ((braminzero_fallback*)parent)->hotpath);
4648: if (braminzerojump != NULL)
4649: {
4650: JUMPHERE(braminzerojump);
4651: /* We need to release the end pointer to perform the
4652: fallback for the zero-length iteration. When
4653: framesize is < 0, OP_ONCE will do the release itself. */
4654: if (opcode == OP_ONCE && FALLBACK_AS(bracket_fallback)->u.framesize >= 0)
4655: {
4656: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4657: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
4658: }
4659: else if (ket == OP_KETRMIN && opcode != OP_ONCE)
4660: free_stack(common, 1);
4661: }
4662: /* Continue to the normal fallback. */
4663: }
4664:
4665: if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
4666: decrease_call_count(common);
4667:
4668: /* Skip the other alternatives. */
4669: while (*cc == OP_ALT)
4670: cc += GET(cc, 1);
4671: cc += 1 + LINK_SIZE;
4672: return cc;
4673: }
4674:
1.1.1.2 ! misho 4675: static pcre_uchar *compile_bracketpos_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
1.1 misho 4676: {
4677: DEFINE_COMPILER;
4678: fallback_common *fallback;
1.1.1.2 ! misho 4679: pcre_uchar opcode;
1.1 misho 4680: int localptr;
4681: int cbraprivptr = 0;
4682: int framesize;
4683: int stacksize;
4684: int offset = 0;
4685: BOOL zero = FALSE;
1.1.1.2 ! misho 4686: pcre_uchar *ccbegin = NULL;
1.1 misho 4687: int stack;
4688: struct sljit_label *loop = NULL;
4689: struct jump_list *emptymatch = NULL;
4690:
4691: PUSH_FALLBACK(sizeof(bracketpos_fallback), cc, NULL);
4692: if (*cc == OP_BRAPOSZERO)
4693: {
4694: zero = TRUE;
4695: cc++;
4696: }
4697:
4698: opcode = *cc;
1.1.1.2 ! misho 4699: localptr = PRIV_DATA(cc);
1.1 misho 4700: SLJIT_ASSERT(localptr != 0);
4701: FALLBACK_AS(bracketpos_fallback)->localptr = localptr;
4702: switch(opcode)
4703: {
4704: case OP_BRAPOS:
4705: case OP_SBRAPOS:
4706: ccbegin = cc + 1 + LINK_SIZE;
4707: break;
4708:
4709: case OP_CBRAPOS:
4710: case OP_SCBRAPOS:
4711: offset = GET2(cc, 1 + LINK_SIZE);
4712: cbraprivptr = OVECTOR_PRIV(offset);
4713: offset <<= 1;
1.1.1.2 ! misho 4714: ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 4715: break;
4716:
4717: default:
4718: SLJIT_ASSERT_STOP();
4719: break;
4720: }
4721:
4722: framesize = get_framesize(common, cc, FALSE);
4723: FALLBACK_AS(bracketpos_fallback)->framesize = framesize;
4724: if (framesize < 0)
4725: {
4726: stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1;
4727: if (!zero)
4728: stacksize++;
4729: FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;
4730: allocate_stack(common, stacksize);
4731: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4732:
4733: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4734: {
4735: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
4736: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4737: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4738: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4739: }
4740: else
4741: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4742:
4743: if (!zero)
4744: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 1);
4745: }
4746: else
4747: {
4748: stacksize = framesize + 1;
4749: if (!zero)
4750: stacksize++;
4751: if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
4752: stacksize++;
4753: FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;
4754: allocate_stack(common, stacksize);
4755:
4756: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4757: OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1));
4758: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4759: stack = 0;
4760: if (!zero)
4761: {
4762: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);
4763: stack++;
4764: }
4765: if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
4766: {
4767: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0);
4768: stack++;
4769: }
4770: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0);
4771: init_frame(common, cc, stacksize - 1, stacksize - framesize, FALSE);
4772: }
4773:
4774: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4775: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
4776:
4777: loop = LABEL();
4778: while (*cc != OP_KETRPOS)
4779: {
4780: fallback->top = NULL;
4781: fallback->topfallbacks = NULL;
4782: cc += GET(cc, 1);
4783:
4784: compile_hotpath(common, ccbegin, cc, fallback);
4785: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4786: return NULL;
4787:
4788: if (framesize < 0)
4789: {
4790: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4791:
4792: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4793: {
4794: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
4795: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
4796: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
4797: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
4798: }
4799: else
4800: {
4801: if (opcode == OP_SBRAPOS)
4802: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4803: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4804: }
4805:
4806: if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
4807: add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0));
4808:
4809: if (!zero)
4810: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
4811: }
4812: else
4813: {
4814: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4815: {
4816: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, stacksize * sizeof(sljit_w));
4817: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
4818: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
4819: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
4820: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
4821: }
4822: else
4823: {
4824: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4825: OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_w));
4826: if (opcode == OP_SBRAPOS)
4827: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w));
4828: OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w), STR_PTR, 0);
4829: }
4830:
4831: if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
4832: add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0));
4833:
4834: if (!zero)
4835: {
4836: if (framesize < 0)
4837: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
4838: else
4839: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4840: }
4841: }
4842: JUMPTO(SLJIT_JUMP, loop);
4843: flush_stubs(common);
4844:
4845: compile_fallbackpath(common, fallback->top);
4846: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4847: return NULL;
4848: set_jumps(fallback->topfallbacks, LABEL());
4849:
4850: if (framesize < 0)
4851: {
4852: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4853: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
4854: else
4855: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4856: }
4857: else
4858: {
4859: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4860: {
4861: /* Last alternative. */
4862: if (*cc == OP_KETRPOS)
4863: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4864: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
4865: }
4866: else
4867: {
4868: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4869: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w));
4870: }
4871: }
4872:
4873: if (*cc == OP_KETRPOS)
4874: break;
4875: ccbegin = cc + 1 + LINK_SIZE;
4876: }
4877:
4878: fallback->topfallbacks = NULL;
4879: if (!zero)
4880: {
4881: if (framesize < 0)
4882: add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));
4883: else /* TMP2 is set to [localptr] above. */
4884: add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0));
4885: }
4886:
4887: /* None of them matched. */
4888: set_jumps(emptymatch, LABEL());
4889: decrease_call_count(common);
4890: return cc + 1 + LINK_SIZE;
4891: }
4892:
1.1.1.2 ! misho 4893: static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, int *arg1, int *arg2, pcre_uchar **end)
1.1 misho 4894: {
4895: int class_len;
4896:
4897: *opcode = *cc;
4898: if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO)
4899: {
4900: cc++;
4901: *type = OP_CHAR;
4902: }
4903: else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI)
4904: {
4905: cc++;
4906: *type = OP_CHARI;
4907: *opcode -= OP_STARI - OP_STAR;
4908: }
4909: else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO)
4910: {
4911: cc++;
4912: *type = OP_NOT;
4913: *opcode -= OP_NOTSTAR - OP_STAR;
4914: }
4915: else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI)
4916: {
4917: cc++;
4918: *type = OP_NOTI;
4919: *opcode -= OP_NOTSTARI - OP_STAR;
4920: }
4921: else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO)
4922: {
4923: cc++;
4924: *opcode -= OP_TYPESTAR - OP_STAR;
4925: *type = 0;
4926: }
4927: else
4928: {
4929: SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS);
4930: *type = *opcode;
4931: cc++;
1.1.1.2 ! misho 4932: class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0);
1.1 misho 4933: *opcode = cc[class_len - 1];
4934: if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)
4935: {
4936: *opcode -= OP_CRSTAR - OP_STAR;
4937: if (end != NULL)
4938: *end = cc + class_len;
4939: }
4940: else
4941: {
4942: SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE);
1.1.1.2 ! misho 4943: *arg1 = GET2(cc, (class_len + IMM2_SIZE));
1.1 misho 4944: *arg2 = GET2(cc, class_len);
4945:
4946: if (*arg2 == 0)
4947: {
4948: SLJIT_ASSERT(*arg1 != 0);
4949: *opcode = (*opcode == OP_CRRANGE) ? OP_UPTO : OP_MINUPTO;
4950: }
4951: if (*arg1 == *arg2)
4952: *opcode = OP_EXACT;
4953:
4954: if (end != NULL)
1.1.1.2 ! misho 4955: *end = cc + class_len + 2 * IMM2_SIZE;
1.1 misho 4956: }
4957: return cc;
4958: }
4959:
4960: if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO)
4961: {
4962: *arg1 = GET2(cc, 0);
1.1.1.2 ! misho 4963: cc += IMM2_SIZE;
1.1 misho 4964: }
4965:
4966: if (*type == 0)
4967: {
4968: *type = *cc;
4969: if (end != NULL)
4970: *end = next_opcode(common, cc);
4971: cc++;
4972: return cc;
4973: }
4974:
4975: if (end != NULL)
4976: {
4977: *end = cc + 1;
1.1.1.2 ! misho 4978: #ifdef SUPPORT_UTF
! 4979: if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);
1.1 misho 4980: #endif
4981: }
4982: return cc;
4983: }
4984:
1.1.1.2 ! misho 4985: static pcre_uchar *compile_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
1.1 misho 4986: {
4987: DEFINE_COMPILER;
4988: fallback_common *fallback;
1.1.1.2 ! misho 4989: pcre_uchar opcode;
! 4990: pcre_uchar type;
1.1 misho 4991: int arg1 = -1, arg2 = -1;
1.1.1.2 ! misho 4992: pcre_uchar* end;
1.1 misho 4993: jump_list *nomatch = NULL;
4994: struct sljit_jump *jump = NULL;
4995: struct sljit_label *label;
4996:
4997: PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL);
4998:
4999: cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end);
5000:
5001: switch(opcode)
5002: {
5003: case OP_STAR:
5004: case OP_PLUS:
5005: case OP_UPTO:
5006: case OP_CRRANGE:
5007: if (type == OP_ANYNL || type == OP_EXTUNI)
5008: {
5009: if (opcode == OP_STAR || opcode == OP_UPTO)
5010: {
5011: allocate_stack(common, 2);
5012: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5013: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
5014: }
5015: else
5016: {
5017: allocate_stack(common, 1);
5018: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5019: }
5020: if (opcode == OP_UPTO || opcode == OP_CRRANGE)
5021: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
5022:
5023: label = LABEL();
5024: compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);
5025: if (opcode == OP_UPTO || opcode == OP_CRRANGE)
5026: {
5027: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
5028: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5029: if (opcode == OP_CRRANGE && arg2 > 0)
5030: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2, label);
5031: if (opcode == OP_UPTO || (opcode == OP_CRRANGE && arg1 > 0))
5032: jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, arg1);
5033: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
5034: }
5035:
5036: allocate_stack(common, 1);
5037: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5038: JUMPTO(SLJIT_JUMP, label);
5039: if (jump != NULL)
5040: JUMPHERE(jump);
5041: }
5042: else
5043: {
5044: allocate_stack(common, 2);
5045: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5046: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
5047: label = LABEL();
5048: compile_char1_hotpath(common, type, cc, &nomatch);
5049: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5050: if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0))
5051: {
5052: OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
5053: JUMPTO(SLJIT_JUMP, label);
5054: }
5055: else
5056: {
5057: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5058: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5059: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
5060: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
5061: }
5062: set_jumps(nomatch, LABEL());
5063: if (opcode == OP_PLUS || opcode == OP_CRRANGE)
5064: add_jump(compiler, &fallback->topfallbacks,
5065: CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, opcode == OP_PLUS ? 2 : arg2 + 1));
5066: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5067: }
5068: FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
5069: break;
5070:
5071: case OP_MINSTAR:
5072: case OP_MINPLUS:
5073: allocate_stack(common, 1);
5074: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5075: if (opcode == OP_MINPLUS)
5076: add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
5077: FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
5078: break;
5079:
5080: case OP_MINUPTO:
5081: case OP_CRMINRANGE:
5082: allocate_stack(common, 2);
5083: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5084: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
5085: if (opcode == OP_CRMINRANGE)
5086: add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
5087: FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
5088: break;
5089:
5090: case OP_QUERY:
5091: case OP_MINQUERY:
5092: allocate_stack(common, 1);
5093: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5094: if (opcode == OP_QUERY)
5095: compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);
5096: FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
5097: break;
5098:
5099: case OP_EXACT:
5100: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
5101: label = LABEL();
5102: compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);
5103: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
5104: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5105: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
5106: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
5107: break;
5108:
5109: case OP_POSSTAR:
5110: case OP_POSPLUS:
5111: case OP_POSUPTO:
5112: if (opcode != OP_POSSTAR)
5113: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
5114: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
5115: label = LABEL();
5116: compile_char1_hotpath(common, type, cc, &nomatch);
5117: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
5118: if (opcode != OP_POSUPTO)
5119: {
5120: if (opcode == OP_POSPLUS)
5121: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2);
5122: JUMPTO(SLJIT_JUMP, label);
5123: }
5124: else
5125: {
5126: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
5127: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5128: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
5129: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
5130: }
5131: set_jumps(nomatch, LABEL());
5132: if (opcode == OP_POSPLUS)
5133: add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2));
5134: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
5135: break;
5136:
5137: case OP_POSQUERY:
5138: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
5139: compile_char1_hotpath(common, type, cc, &nomatch);
5140: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
5141: set_jumps(nomatch, LABEL());
5142: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
5143: break;
5144:
5145: default:
5146: SLJIT_ASSERT_STOP();
5147: break;
5148: }
5149:
5150: decrease_call_count(common);
5151: return end;
5152: }
5153:
1.1.1.2 ! misho 5154: static SLJIT_INLINE pcre_uchar *compile_fail_accept_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
1.1 misho 5155: {
5156: DEFINE_COMPILER;
5157: fallback_common *fallback;
5158:
5159: PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL);
5160:
5161: if (*cc == OP_FAIL)
5162: {
5163: add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
5164: return cc + 1;
5165: }
5166:
5167: if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL)
5168: {
5169: /* No need to check notempty conditions. */
5170: if (common->acceptlabel == NULL)
5171: add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
5172: else
5173: JUMPTO(SLJIT_JUMP, common->acceptlabel);
5174: return cc + 1;
5175: }
5176:
5177: if (common->acceptlabel == NULL)
5178: add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)));
5179: else
5180: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel);
5181: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
5182: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
5183: add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
5184: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
5185: if (common->acceptlabel == NULL)
5186: add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0));
5187: else
5188: CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->acceptlabel);
5189: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
5190: if (common->acceptlabel == NULL)
5191: add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0));
5192: else
5193: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel);
5194: add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
5195: return cc + 1;
5196: }
5197:
1.1.1.2 ! misho 5198: static SLJIT_INLINE pcre_uchar *compile_close_hotpath(compiler_common *common, pcre_uchar *cc)
1.1 misho 5199: {
5200: DEFINE_COMPILER;
5201: int offset = GET2(cc, 1);
5202:
5203: /* Data will be discarded anyway... */
5204: if (common->currententry != NULL)
1.1.1.2 ! misho 5205: return cc + 1 + IMM2_SIZE;
1.1 misho 5206:
5207: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset));
5208: offset <<= 1;
5209: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
5210: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
1.1.1.2 ! misho 5211: return cc + 1 + IMM2_SIZE;
1.1 misho 5212: }
5213:
1.1.1.2 ! misho 5214: static void compile_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, fallback_common *parent)
1.1 misho 5215: {
5216: DEFINE_COMPILER;
5217: fallback_common *fallback;
5218:
5219: while (cc < ccend)
5220: {
5221: switch(*cc)
5222: {
5223: case OP_SOD:
5224: case OP_SOM:
5225: case OP_NOT_WORD_BOUNDARY:
5226: case OP_WORD_BOUNDARY:
5227: case OP_NOT_DIGIT:
5228: case OP_DIGIT:
5229: case OP_NOT_WHITESPACE:
5230: case OP_WHITESPACE:
5231: case OP_NOT_WORDCHAR:
5232: case OP_WORDCHAR:
5233: case OP_ANY:
5234: case OP_ALLANY:
5235: case OP_ANYBYTE:
5236: case OP_NOTPROP:
5237: case OP_PROP:
5238: case OP_ANYNL:
5239: case OP_NOT_HSPACE:
5240: case OP_HSPACE:
5241: case OP_NOT_VSPACE:
5242: case OP_VSPACE:
5243: case OP_EXTUNI:
5244: case OP_EODN:
5245: case OP_EOD:
5246: case OP_CIRC:
5247: case OP_CIRCM:
5248: case OP_DOLL:
5249: case OP_DOLLM:
5250: case OP_NOT:
5251: case OP_NOTI:
5252: case OP_REVERSE:
5253: cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
5254: break;
5255:
5256: case OP_SET_SOM:
5257: PUSH_FALLBACK_NOVALUE(sizeof(fallback_common), cc);
5258: allocate_stack(common, 1);
5259: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
5260: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
5261: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
5262: cc++;
5263: break;
5264:
5265: case OP_CHAR:
5266: case OP_CHARI:
5267: cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
5268: break;
5269:
5270: case OP_STAR:
5271: case OP_MINSTAR:
5272: case OP_PLUS:
5273: case OP_MINPLUS:
5274: case OP_QUERY:
5275: case OP_MINQUERY:
5276: case OP_UPTO:
5277: case OP_MINUPTO:
5278: case OP_EXACT:
5279: case OP_POSSTAR:
5280: case OP_POSPLUS:
5281: case OP_POSQUERY:
5282: case OP_POSUPTO:
5283: case OP_STARI:
5284: case OP_MINSTARI:
5285: case OP_PLUSI:
5286: case OP_MINPLUSI:
5287: case OP_QUERYI:
5288: case OP_MINQUERYI:
5289: case OP_UPTOI:
5290: case OP_MINUPTOI:
5291: case OP_EXACTI:
5292: case OP_POSSTARI:
5293: case OP_POSPLUSI:
5294: case OP_POSQUERYI:
5295: case OP_POSUPTOI:
5296: case OP_NOTSTAR:
5297: case OP_NOTMINSTAR:
5298: case OP_NOTPLUS:
5299: case OP_NOTMINPLUS:
5300: case OP_NOTQUERY:
5301: case OP_NOTMINQUERY:
5302: case OP_NOTUPTO:
5303: case OP_NOTMINUPTO:
5304: case OP_NOTEXACT:
5305: case OP_NOTPOSSTAR:
5306: case OP_NOTPOSPLUS:
5307: case OP_NOTPOSQUERY:
5308: case OP_NOTPOSUPTO:
5309: case OP_NOTSTARI:
5310: case OP_NOTMINSTARI:
5311: case OP_NOTPLUSI:
5312: case OP_NOTMINPLUSI:
5313: case OP_NOTQUERYI:
5314: case OP_NOTMINQUERYI:
5315: case OP_NOTUPTOI:
5316: case OP_NOTMINUPTOI:
5317: case OP_NOTEXACTI:
5318: case OP_NOTPOSSTARI:
5319: case OP_NOTPOSPLUSI:
5320: case OP_NOTPOSQUERYI:
5321: case OP_NOTPOSUPTOI:
5322: case OP_TYPESTAR:
5323: case OP_TYPEMINSTAR:
5324: case OP_TYPEPLUS:
5325: case OP_TYPEMINPLUS:
5326: case OP_TYPEQUERY:
5327: case OP_TYPEMINQUERY:
5328: case OP_TYPEUPTO:
5329: case OP_TYPEMINUPTO:
5330: case OP_TYPEEXACT:
5331: case OP_TYPEPOSSTAR:
5332: case OP_TYPEPOSPLUS:
5333: case OP_TYPEPOSQUERY:
5334: case OP_TYPEPOSUPTO:
5335: cc = compile_iterator_hotpath(common, cc, parent);
5336: break;
5337:
5338: case OP_CLASS:
5339: case OP_NCLASS:
1.1.1.2 ! misho 5340: if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRMINRANGE)
1.1 misho 5341: cc = compile_iterator_hotpath(common, cc, parent);
5342: else
5343: cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
5344: break;
5345:
1.1.1.2 ! misho 5346: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
1.1 misho 5347: case OP_XCLASS:
5348: if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE)
5349: cc = compile_iterator_hotpath(common, cc, parent);
5350: else
5351: cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
5352: break;
5353: #endif
5354:
5355: case OP_REF:
5356: case OP_REFI:
1.1.1.2 ! misho 5357: if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE)
1.1 misho 5358: cc = compile_ref_iterator_hotpath(common, cc, parent);
5359: else
5360: cc = compile_ref_hotpath(common, cc, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks, TRUE, FALSE);
5361: break;
5362:
5363: case OP_RECURSE:
5364: cc = compile_recurse_hotpath(common, cc, parent);
5365: break;
5366:
5367: case OP_ASSERT:
5368: case OP_ASSERT_NOT:
5369: case OP_ASSERTBACK:
5370: case OP_ASSERTBACK_NOT:
5371: PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc);
5372: cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE);
5373: break;
5374:
5375: case OP_BRAMINZERO:
5376: PUSH_FALLBACK_NOVALUE(sizeof(braminzero_fallback), cc);
5377: cc = bracketend(cc + 1);
5378: if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)
5379: {
5380: allocate_stack(common, 1);
5381: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5382: }
5383: else
5384: {
5385: allocate_stack(common, 2);
5386: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5387: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);
5388: }
5389: FALLBACK_AS(braminzero_fallback)->hotpath = LABEL();
5390: if (cc[1] > OP_ASSERTBACK_NOT)
5391: decrease_call_count(common);
5392: break;
5393:
5394: case OP_ONCE:
5395: case OP_ONCE_NC:
5396: case OP_BRA:
5397: case OP_CBRA:
5398: case OP_COND:
5399: case OP_SBRA:
5400: case OP_SCBRA:
5401: case OP_SCOND:
5402: cc = compile_bracket_hotpath(common, cc, parent);
5403: break;
5404:
5405: case OP_BRAZERO:
5406: if (cc[1] > OP_ASSERTBACK_NOT)
5407: cc = compile_bracket_hotpath(common, cc, parent);
5408: else
5409: {
5410: PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc);
5411: cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE);
5412: }
5413: break;
5414:
5415: case OP_BRAPOS:
5416: case OP_CBRAPOS:
5417: case OP_SBRAPOS:
5418: case OP_SCBRAPOS:
5419: case OP_BRAPOSZERO:
5420: cc = compile_bracketpos_hotpath(common, cc, parent);
5421: break;
5422:
5423: case OP_FAIL:
5424: case OP_ACCEPT:
5425: case OP_ASSERT_ACCEPT:
5426: cc = compile_fail_accept_hotpath(common, cc, parent);
5427: break;
5428:
5429: case OP_CLOSE:
5430: cc = compile_close_hotpath(common, cc);
5431: break;
5432:
5433: case OP_SKIPZERO:
5434: cc = bracketend(cc + 1);
5435: break;
5436:
5437: default:
5438: SLJIT_ASSERT_STOP();
5439: return;
5440: }
5441: if (cc == NULL)
5442: return;
5443: }
5444: SLJIT_ASSERT(cc == ccend);
5445: }
5446:
5447: #undef PUSH_FALLBACK
5448: #undef PUSH_FALLBACK_NOVALUE
5449: #undef FALLBACK_AS
5450:
5451: #define COMPILE_FALLBACKPATH(current) \
5452: do \
5453: { \
5454: compile_fallbackpath(common, (current)); \
5455: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
5456: return; \
5457: } \
5458: while (0)
5459:
5460: #define CURRENT_AS(type) ((type*)current)
5461:
5462: static void compile_iterator_fallbackpath(compiler_common *common, struct fallback_common *current)
5463: {
5464: DEFINE_COMPILER;
1.1.1.2 ! misho 5465: pcre_uchar *cc = current->cc;
! 5466: pcre_uchar opcode;
! 5467: pcre_uchar type;
1.1 misho 5468: int arg1 = -1, arg2 = -1;
5469: struct sljit_label *label = NULL;
5470: struct sljit_jump *jump = NULL;
5471:
5472: cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL);
5473:
5474: switch(opcode)
5475: {
5476: case OP_STAR:
5477: case OP_PLUS:
5478: case OP_UPTO:
5479: case OP_CRRANGE:
5480: if (type == OP_ANYNL || type == OP_EXTUNI)
5481: {
5482: set_jumps(current->topfallbacks, LABEL());
5483: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5484: free_stack(common, 1);
5485: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);
5486: }
5487: else
5488: {
5489: if (opcode == OP_STAR || opcode == OP_UPTO)
5490: arg2 = 0;
5491: else if (opcode == OP_PLUS)
5492: arg2 = 1;
5493: jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, arg2 + 1);
5494: OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
5495: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5496: skip_char_back(common);
5497: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5498: JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
5499: if (opcode == OP_PLUS || opcode == OP_CRRANGE)
5500: set_jumps(current->topfallbacks, LABEL());
5501: JUMPHERE(jump);
5502: free_stack(common, 2);
5503: }
5504: break;
5505:
5506: case OP_MINSTAR:
5507: case OP_MINPLUS:
5508: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5509: if (opcode == OP_MINPLUS)
5510: {
5511: set_jumps(current->topfallbacks, LABEL());
5512: current->topfallbacks = NULL;
5513: }
5514: compile_char1_hotpath(common, type, cc, ¤t->topfallbacks);
5515: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5516: JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
5517: set_jumps(current->topfallbacks, LABEL());
5518: free_stack(common, 1);
5519: break;
5520:
5521: case OP_MINUPTO:
5522: case OP_CRMINRANGE:
5523: if (opcode == OP_CRMINRANGE)
5524: {
5525: set_jumps(current->topfallbacks, LABEL());
5526: current->topfallbacks = NULL;
5527: label = LABEL();
5528: }
5529: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5530: compile_char1_hotpath(common, type, cc, ¤t->topfallbacks);
5531:
5532: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5533: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5534: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5535: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
5536:
5537: if (opcode == OP_CRMINRANGE)
5538: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label);
5539:
5540: if (opcode == OP_CRMINRANGE && arg1 == 0)
5541: JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
5542: else
5543: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_fallback)->hotpath);
5544:
5545: set_jumps(current->topfallbacks, LABEL());
5546: free_stack(common, 2);
5547: break;
5548:
5549: case OP_QUERY:
5550: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5551: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5552: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);
5553: jump = JUMP(SLJIT_JUMP);
5554: set_jumps(current->topfallbacks, LABEL());
5555: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5556: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5557: JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
5558: JUMPHERE(jump);
5559: free_stack(common, 1);
5560: break;
5561:
5562: case OP_MINQUERY:
5563: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5564: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5565: jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
5566: compile_char1_hotpath(common, type, cc, ¤t->topfallbacks);
5567: JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
5568: set_jumps(current->topfallbacks, LABEL());
5569: JUMPHERE(jump);
5570: free_stack(common, 1);
5571: break;
5572:
5573: case OP_EXACT:
5574: case OP_POSPLUS:
5575: set_jumps(current->topfallbacks, LABEL());
5576: break;
5577:
5578: case OP_POSSTAR:
5579: case OP_POSQUERY:
5580: case OP_POSUPTO:
5581: break;
5582:
5583: default:
5584: SLJIT_ASSERT_STOP();
5585: break;
5586: }
5587: }
5588:
5589: static void compile_ref_iterator_fallbackpath(compiler_common *common, struct fallback_common *current)
5590: {
5591: DEFINE_COMPILER;
1.1.1.2 ! misho 5592: pcre_uchar *cc = current->cc;
! 5593: pcre_uchar type;
1.1 misho 5594:
1.1.1.2 ! misho 5595: type = cc[1 + IMM2_SIZE];
1.1 misho 5596: if ((type & 0x1) == 0)
5597: {
5598: set_jumps(current->topfallbacks, LABEL());
5599: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5600: free_stack(common, 1);
5601: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);
5602: return;
5603: }
5604:
5605: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5606: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);
5607: set_jumps(current->topfallbacks, LABEL());
5608: free_stack(common, 2);
5609: }
5610:
5611: static void compile_recurse_fallbackpath(compiler_common *common, struct fallback_common *current)
5612: {
5613: DEFINE_COMPILER;
5614:
5615: set_jumps(current->topfallbacks, LABEL());
5616: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5617: free_stack(common, 1);
5618: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
5619: }
5620:
5621: static void compile_assert_fallbackpath(compiler_common *common, struct fallback_common *current)
5622: {
5623: DEFINE_COMPILER;
1.1.1.2 ! misho 5624: pcre_uchar *cc = current->cc;
! 5625: pcre_uchar bra = OP_BRA;
1.1 misho 5626: struct sljit_jump *brajump = NULL;
5627:
5628: SLJIT_ASSERT(*cc != OP_BRAMINZERO);
5629: if (*cc == OP_BRAZERO)
5630: {
5631: bra = *cc;
5632: cc++;
5633: }
5634:
5635: if (bra == OP_BRAZERO)
5636: {
5637: SLJIT_ASSERT(current->topfallbacks == NULL);
5638: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5639: }
5640:
5641: if (CURRENT_AS(assert_fallback)->framesize < 0)
5642: {
5643: set_jumps(current->topfallbacks, LABEL());
5644:
5645: if (bra == OP_BRAZERO)
5646: {
5647: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5648: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_fallback)->hotpath);
5649: free_stack(common, 1);
5650: }
5651: return;
5652: }
5653:
5654: if (bra == OP_BRAZERO)
5655: {
5656: if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)
5657: {
5658: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5659: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_fallback)->hotpath);
5660: free_stack(common, 1);
5661: return;
5662: }
5663: free_stack(common, 1);
5664: brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
5665: }
5666:
5667: if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)
5668: {
5669: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr);
5670: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5671: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_fallback)->framesize * sizeof(sljit_w));
5672:
5673: set_jumps(current->topfallbacks, LABEL());
5674: }
5675: else
5676: set_jumps(current->topfallbacks, LABEL());
5677:
5678: if (bra == OP_BRAZERO)
5679: {
5680: /* We know there is enough place on the stack. */
5681: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
5682: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5683: JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_fallback)->hotpath);
5684: JUMPHERE(brajump);
5685: }
5686: }
5687:
5688: static void compile_bracket_fallbackpath(compiler_common *common, struct fallback_common *current)
5689: {
5690: DEFINE_COMPILER;
5691: int opcode;
5692: int offset = 0;
5693: int localptr = CURRENT_AS(bracket_fallback)->localptr;
5694: int stacksize;
5695: int count;
1.1.1.2 ! misho 5696: pcre_uchar *cc = current->cc;
! 5697: pcre_uchar *ccbegin;
! 5698: pcre_uchar *ccprev;
1.1 misho 5699: jump_list *jumplist = NULL;
5700: jump_list *jumplistitem = NULL;
1.1.1.2 ! misho 5701: pcre_uchar bra = OP_BRA;
! 5702: pcre_uchar ket;
1.1 misho 5703: assert_fallback *assert;
5704: BOOL has_alternatives;
5705: struct sljit_jump *brazero = NULL;
5706: struct sljit_jump *once = NULL;
5707: struct sljit_jump *cond = NULL;
5708: struct sljit_label *rminlabel = NULL;
5709:
5710: if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
5711: {
5712: bra = *cc;
5713: cc++;
5714: }
5715:
5716: opcode = *cc;
5717: ccbegin = cc;
5718: ket = *(bracketend(ccbegin) - 1 - LINK_SIZE);
5719: cc += GET(cc, 1);
5720: has_alternatives = *cc == OP_ALT;
5721: if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
5722: has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_fallback)->u.condfailed != NULL;
5723: if (opcode == OP_CBRA || opcode == OP_SCBRA)
5724: offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;
5725: if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
5726: opcode = OP_SCOND;
5727: if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
5728: opcode = OP_ONCE;
5729:
5730: if (ket == OP_KETRMAX)
5731: {
5732: if (bra != OP_BRAZERO)
5733: free_stack(common, 1);
5734: else
5735: {
5736: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5737: free_stack(common, 1);
5738: brazero = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0);
5739: }
5740: }
5741: else if (ket == OP_KETRMIN)
5742: {
5743: if (bra != OP_BRAMINZERO)
5744: {
5745: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5746: if (opcode >= OP_SBRA || opcode == OP_ONCE)
5747: {
5748: /* Checking zero-length iteration. */
5749: if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize < 0)
5750: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_fallback)->recursivehotpath);
5751: else
5752: {
5753: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5754: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_fallback)->recursivehotpath);
5755: }
5756: if (opcode != OP_ONCE)
5757: free_stack(common, 1);
5758: }
5759: else
5760: JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->recursivehotpath);
5761: }
5762: rminlabel = LABEL();
5763: }
5764: else if (bra == OP_BRAZERO)
5765: {
5766: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5767: free_stack(common, 1);
5768: brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
5769: }
5770:
5771: if (SLJIT_UNLIKELY(opcode == OP_ONCE))
5772: {
5773: if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)
5774: {
5775: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5776: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5777: }
5778: once = JUMP(SLJIT_JUMP);
5779: }
5780: else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
5781: {
5782: if (has_alternatives)
5783: {
5784: /* Always exactly one alternative. */
5785: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5786: free_stack(common, 1);
5787:
5788: jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
5789: if (SLJIT_UNLIKELY(!jumplistitem))
5790: return;
5791: jumplist = jumplistitem;
5792: jumplistitem->next = NULL;
5793: jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 1);
5794: }
5795: }
5796: else if (*cc == OP_ALT)
5797: {
5798: /* Build a jump list. Get the last successfully matched branch index. */
5799: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5800: free_stack(common, 1);
5801: count = 1;
5802: do
5803: {
5804: /* Append as the last item. */
5805: if (jumplist != NULL)
5806: {
5807: jumplistitem->next = sljit_alloc_memory(compiler, sizeof(jump_list));
5808: jumplistitem = jumplistitem->next;
5809: }
5810: else
5811: {
5812: jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
5813: jumplist = jumplistitem;
5814: }
5815:
5816: if (SLJIT_UNLIKELY(!jumplistitem))
5817: return;
5818:
5819: jumplistitem->next = NULL;
5820: jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, count++);
5821: cc += GET(cc, 1);
5822: }
5823: while (*cc == OP_ALT);
5824:
5825: cc = ccbegin + GET(ccbegin, 1);
5826: }
5827:
5828: COMPILE_FALLBACKPATH(current->top);
5829: if (current->topfallbacks)
5830: set_jumps(current->topfallbacks, LABEL());
5831:
5832: if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
5833: {
5834: /* Conditional block always has at most one alternative. */
5835: if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)
5836: {
5837: SLJIT_ASSERT(has_alternatives);
5838: assert = CURRENT_AS(bracket_fallback)->u.assert;
5839: if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))
5840: {
5841: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr);
5842: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5843: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
5844: }
5845: cond = JUMP(SLJIT_JUMP);
5846: set_jumps(CURRENT_AS(bracket_fallback)->u.assert->condfailed, LABEL());
5847: }
5848: else if (CURRENT_AS(bracket_fallback)->u.condfailed != NULL)
5849: {
5850: SLJIT_ASSERT(has_alternatives);
5851: cond = JUMP(SLJIT_JUMP);
5852: set_jumps(CURRENT_AS(bracket_fallback)->u.condfailed, LABEL());
5853: }
5854: else
5855: SLJIT_ASSERT(!has_alternatives);
5856: }
5857:
5858: if (has_alternatives)
5859: {
5860: count = 1;
5861: do
5862: {
5863: current->top = NULL;
5864: current->topfallbacks = NULL;
5865: current->nextfallbacks = NULL;
5866: if (*cc == OP_ALT)
5867: {
5868: ccprev = cc + 1 + LINK_SIZE;
5869: cc += GET(cc, 1);
5870: if (opcode != OP_COND && opcode != OP_SCOND)
5871: {
5872: if (localptr != 0 && opcode != OP_ONCE)
5873: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5874: else
5875: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5876: }
5877: compile_hotpath(common, ccprev, cc, current);
5878: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
5879: return;
5880: }
5881:
5882: /* Instructions after the current alternative is succesfully matched. */
5883: /* There is a similar code in compile_bracket_hotpath. */
5884: if (opcode == OP_ONCE)
5885: {
5886: if (CURRENT_AS(bracket_fallback)->u.framesize < 0)
5887: {
5888: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5889: /* TMP2 which is set here used by OP_KETRMAX below. */
5890: if (ket == OP_KETRMAX)
5891: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
5892: else if (ket == OP_KETRMIN)
5893: {
5894: /* Move the STR_PTR to the localptr. */
5895: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
5896: }
5897: }
5898: else
5899: {
5900: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (CURRENT_AS(bracket_fallback)->u.framesize + 2) * sizeof(sljit_w));
5901: if (ket == OP_KETRMAX)
5902: {
5903: /* TMP2 which is set here used by OP_KETRMAX below. */
5904: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5905: }
5906: }
5907: }
5908:
5909: stacksize = 0;
5910: if (opcode != OP_ONCE)
5911: stacksize++;
5912: if (ket != OP_KET || bra != OP_BRA)
5913: stacksize++;
5914:
5915: if (stacksize > 0) {
5916: if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize >= 0)
5917: allocate_stack(common, stacksize);
5918: else
5919: {
5920: /* We know we have place at least for one item on the top of the stack. */
5921: SLJIT_ASSERT(stacksize == 1);
5922: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
5923: }
5924: }
5925:
5926: stacksize = 0;
5927: if (ket != OP_KET || bra != OP_BRA)
5928: {
5929: if (ket != OP_KET)
5930: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
5931: else
5932: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
5933: stacksize++;
5934: }
5935:
5936: if (opcode != OP_ONCE)
5937: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++);
5938:
5939: if (offset != 0)
5940: {
5941: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5942: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
5943: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
5944: }
5945:
5946: JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->althotpath);
5947:
5948: if (opcode != OP_ONCE)
5949: {
5950: SLJIT_ASSERT(jumplist);
5951: JUMPHERE(jumplist->jump);
5952: jumplist = jumplist->next;
5953: }
5954:
5955: COMPILE_FALLBACKPATH(current->top);
5956: if (current->topfallbacks)
5957: set_jumps(current->topfallbacks, LABEL());
5958: SLJIT_ASSERT(!current->nextfallbacks);
5959: }
5960: while (*cc == OP_ALT);
5961: SLJIT_ASSERT(!jumplist);
5962:
5963: if (cond != NULL)
5964: {
5965: SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);
5966: assert = CURRENT_AS(bracket_fallback)->u.assert;
5967: if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0)
5968:
5969: {
5970: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr);
5971: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5972: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
5973: }
5974: JUMPHERE(cond);
5975: }
5976:
5977: /* Free the STR_PTR. */
5978: if (localptr == 0)
5979: free_stack(common, 1);
5980: }
5981:
5982: if (offset != 0)
5983: {
5984: /* Using both tmp register is better for instruction scheduling. */
5985: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5986: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5987: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
5988: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
5989: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(2));
5990: free_stack(common, 3);
5991: }
5992: else if (opcode == OP_SBRA || opcode == OP_SCOND)
5993: {
5994: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(0));
5995: free_stack(common, 1);
5996: }
5997: else if (opcode == OP_ONCE)
5998: {
5999: cc = ccbegin + GET(ccbegin, 1);
6000: if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)
6001: {
6002: /* Reset head and drop saved frame. */
6003: stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1;
6004: free_stack(common, CURRENT_AS(bracket_fallback)->u.framesize + stacksize);
6005: }
6006: else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))
6007: {
6008: /* The STR_PTR must be released. */
6009: free_stack(common, 1);
6010: }
6011:
6012: JUMPHERE(once);
6013: /* Restore previous localptr */
6014: if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)
6015: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_fallback)->u.framesize * sizeof(sljit_w));
6016: else if (ket == OP_KETRMIN)
6017: {
6018: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
6019: /* See the comment below. */
6020: free_stack(common, 2);
6021: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
6022: }
6023: }
6024:
6025: if (ket == OP_KETRMAX)
6026: {
6027: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6028: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_fallback)->recursivehotpath);
6029: if (bra == OP_BRAZERO)
6030: {
6031: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
6032: JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath);
6033: JUMPHERE(brazero);
6034: }
6035: free_stack(common, 1);
6036: }
6037: else if (ket == OP_KETRMIN)
6038: {
6039: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6040:
6041: /* OP_ONCE removes everything in case of a fallback, so we don't
6042: need to explicitly release the STR_PTR. The extra release would
6043: affect badly the free_stack(2) above. */
6044: if (opcode != OP_ONCE)
6045: free_stack(common, 1);
6046: CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rminlabel);
6047: if (opcode == OP_ONCE)
6048: free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);
6049: else if (bra == OP_BRAMINZERO)
6050: free_stack(common, 1);
6051: }
6052: else if (bra == OP_BRAZERO)
6053: {
6054: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6055: JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath);
6056: JUMPHERE(brazero);
6057: }
6058: }
6059:
6060: static void compile_bracketpos_fallbackpath(compiler_common *common, struct fallback_common *current)
6061: {
6062: DEFINE_COMPILER;
6063: int offset;
6064: struct sljit_jump *jump;
6065:
6066: if (CURRENT_AS(bracketpos_fallback)->framesize < 0)
6067: {
6068: if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS)
6069: {
6070: offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1;
6071: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6072: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
6073: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
6074: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
6075: }
6076: set_jumps(current->topfallbacks, LABEL());
6077: free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize);
6078: return;
6079: }
6080:
6081: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr);
6082: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
6083:
6084: if (current->topfallbacks)
6085: {
6086: jump = JUMP(SLJIT_JUMP);
6087: set_jumps(current->topfallbacks, LABEL());
6088: /* Drop the stack frame. */
6089: free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize);
6090: JUMPHERE(jump);
6091: }
6092: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_fallback)->framesize * sizeof(sljit_w));
6093: }
6094:
6095: static void compile_braminzero_fallbackpath(compiler_common *common, struct fallback_common *current)
6096: {
6097: assert_fallback fallback;
6098:
6099: current->top = NULL;
6100: current->topfallbacks = NULL;
6101: current->nextfallbacks = NULL;
6102: if (current->cc[1] > OP_ASSERTBACK_NOT)
6103: {
6104: /* Manual call of compile_bracket_hotpath and compile_bracket_fallbackpath. */
6105: compile_bracket_hotpath(common, current->cc, current);
6106: compile_bracket_fallbackpath(common, current->top);
6107: }
6108: else
6109: {
6110: memset(&fallback, 0, sizeof(fallback));
6111: fallback.common.cc = current->cc;
6112: fallback.hotpath = CURRENT_AS(braminzero_fallback)->hotpath;
6113: /* Manual call of compile_assert_hotpath. */
6114: compile_assert_hotpath(common, current->cc, &fallback, FALSE);
6115: }
6116: SLJIT_ASSERT(!current->nextfallbacks && !current->topfallbacks);
6117: }
6118:
6119: static void compile_fallbackpath(compiler_common *common, struct fallback_common *current)
6120: {
6121: DEFINE_COMPILER;
6122:
6123: while (current)
6124: {
6125: if (current->nextfallbacks != NULL)
6126: set_jumps(current->nextfallbacks, LABEL());
6127: switch(*current->cc)
6128: {
6129: case OP_SET_SOM:
6130: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6131: free_stack(common, 1);
6132: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP1, 0);
6133: break;
6134:
6135: case OP_STAR:
6136: case OP_MINSTAR:
6137: case OP_PLUS:
6138: case OP_MINPLUS:
6139: case OP_QUERY:
6140: case OP_MINQUERY:
6141: case OP_UPTO:
6142: case OP_MINUPTO:
6143: case OP_EXACT:
6144: case OP_POSSTAR:
6145: case OP_POSPLUS:
6146: case OP_POSQUERY:
6147: case OP_POSUPTO:
6148: case OP_STARI:
6149: case OP_MINSTARI:
6150: case OP_PLUSI:
6151: case OP_MINPLUSI:
6152: case OP_QUERYI:
6153: case OP_MINQUERYI:
6154: case OP_UPTOI:
6155: case OP_MINUPTOI:
6156: case OP_EXACTI:
6157: case OP_POSSTARI:
6158: case OP_POSPLUSI:
6159: case OP_POSQUERYI:
6160: case OP_POSUPTOI:
6161: case OP_NOTSTAR:
6162: case OP_NOTMINSTAR:
6163: case OP_NOTPLUS:
6164: case OP_NOTMINPLUS:
6165: case OP_NOTQUERY:
6166: case OP_NOTMINQUERY:
6167: case OP_NOTUPTO:
6168: case OP_NOTMINUPTO:
6169: case OP_NOTEXACT:
6170: case OP_NOTPOSSTAR:
6171: case OP_NOTPOSPLUS:
6172: case OP_NOTPOSQUERY:
6173: case OP_NOTPOSUPTO:
6174: case OP_NOTSTARI:
6175: case OP_NOTMINSTARI:
6176: case OP_NOTPLUSI:
6177: case OP_NOTMINPLUSI:
6178: case OP_NOTQUERYI:
6179: case OP_NOTMINQUERYI:
6180: case OP_NOTUPTOI:
6181: case OP_NOTMINUPTOI:
6182: case OP_NOTEXACTI:
6183: case OP_NOTPOSSTARI:
6184: case OP_NOTPOSPLUSI:
6185: case OP_NOTPOSQUERYI:
6186: case OP_NOTPOSUPTOI:
6187: case OP_TYPESTAR:
6188: case OP_TYPEMINSTAR:
6189: case OP_TYPEPLUS:
6190: case OP_TYPEMINPLUS:
6191: case OP_TYPEQUERY:
6192: case OP_TYPEMINQUERY:
6193: case OP_TYPEUPTO:
6194: case OP_TYPEMINUPTO:
6195: case OP_TYPEEXACT:
6196: case OP_TYPEPOSSTAR:
6197: case OP_TYPEPOSPLUS:
6198: case OP_TYPEPOSQUERY:
6199: case OP_TYPEPOSUPTO:
6200: case OP_CLASS:
6201: case OP_NCLASS:
1.1.1.2 ! misho 6202: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1 misho 6203: case OP_XCLASS:
1.1.1.2 ! misho 6204: #endif
1.1 misho 6205: compile_iterator_fallbackpath(common, current);
6206: break;
6207:
6208: case OP_REF:
6209: case OP_REFI:
6210: compile_ref_iterator_fallbackpath(common, current);
6211: break;
6212:
6213: case OP_RECURSE:
6214: compile_recurse_fallbackpath(common, current);
6215: break;
6216:
6217: case OP_ASSERT:
6218: case OP_ASSERT_NOT:
6219: case OP_ASSERTBACK:
6220: case OP_ASSERTBACK_NOT:
6221: compile_assert_fallbackpath(common, current);
6222: break;
6223:
6224: case OP_ONCE:
6225: case OP_ONCE_NC:
6226: case OP_BRA:
6227: case OP_CBRA:
6228: case OP_COND:
6229: case OP_SBRA:
6230: case OP_SCBRA:
6231: case OP_SCOND:
6232: compile_bracket_fallbackpath(common, current);
6233: break;
6234:
6235: case OP_BRAZERO:
6236: if (current->cc[1] > OP_ASSERTBACK_NOT)
6237: compile_bracket_fallbackpath(common, current);
6238: else
6239: compile_assert_fallbackpath(common, current);
6240: break;
6241:
6242: case OP_BRAPOS:
6243: case OP_CBRAPOS:
6244: case OP_SBRAPOS:
6245: case OP_SCBRAPOS:
6246: case OP_BRAPOSZERO:
6247: compile_bracketpos_fallbackpath(common, current);
6248: break;
6249:
6250: case OP_BRAMINZERO:
6251: compile_braminzero_fallbackpath(common, current);
6252: break;
6253:
6254: case OP_FAIL:
6255: case OP_ACCEPT:
6256: case OP_ASSERT_ACCEPT:
6257: set_jumps(current->topfallbacks, LABEL());
6258: break;
6259:
6260: default:
6261: SLJIT_ASSERT_STOP();
6262: break;
6263: }
6264: current = current->prev;
6265: }
6266: }
6267:
6268: static SLJIT_INLINE void compile_recurse(compiler_common *common)
6269: {
6270: DEFINE_COMPILER;
1.1.1.2 ! misho 6271: pcre_uchar *cc = common->start + common->currententry->start;
! 6272: pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE);
! 6273: pcre_uchar *ccend = bracketend(cc);
1.1 misho 6274: int localsize = get_localsize(common, ccbegin, ccend);
6275: int framesize = get_framesize(common, cc, TRUE);
6276: int alternativesize;
6277: BOOL needsframe;
6278: fallback_common altfallback;
6279: struct sljit_jump *jump;
6280:
6281: SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);
6282: needsframe = framesize >= 0;
6283: if (!needsframe)
6284: framesize = 0;
6285: alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0;
6286:
6287: SLJIT_ASSERT(common->currententry->entry == NULL);
6288: common->currententry->entry = LABEL();
6289: set_jumps(common->currententry->calls, common->currententry->entry);
6290:
6291: sljit_emit_fast_enter(compiler, TMP2, 0, 1, 5, 5, common->localsize);
6292: allocate_stack(common, localsize + framesize + alternativesize);
6293: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(localsize + framesize + alternativesize - 1), TMP2, 0);
6294: copy_locals(common, ccbegin, ccend, TRUE, localsize + framesize + alternativesize, framesize + alternativesize);
6295: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD, STACK_TOP, 0);
6296: if (needsframe)
6297: init_frame(common, cc, framesize + alternativesize - 1, alternativesize, FALSE);
6298:
6299: if (alternativesize > 0)
6300: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
6301:
6302: memset(&altfallback, 0, sizeof(fallback_common));
6303: common->acceptlabel = NULL;
6304: common->accept = NULL;
6305: altfallback.cc = ccbegin;
6306: cc += GET(cc, 1);
6307: while (1)
6308: {
6309: altfallback.top = NULL;
6310: altfallback.topfallbacks = NULL;
6311:
6312: if (altfallback.cc != ccbegin)
6313: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6314:
6315: compile_hotpath(common, altfallback.cc, cc, &altfallback);
6316: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
6317: return;
6318:
6319: add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
6320:
6321: compile_fallbackpath(common, altfallback.top);
6322: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
6323: return;
6324: set_jumps(altfallback.topfallbacks, LABEL());
6325:
6326: if (*cc != OP_ALT)
6327: break;
6328:
6329: altfallback.cc = cc + 1 + LINK_SIZE;
6330: cc += GET(cc, 1);
6331: }
6332: /* None of them matched. */
6333: OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
6334: jump = JUMP(SLJIT_JUMP);
6335:
6336: set_jumps(common->accept, LABEL());
6337: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD);
6338: if (needsframe)
6339: {
6340: OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
6341: OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));
6342: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
6343: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));
6344: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP3, 0);
6345: }
6346: OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);
6347:
6348: JUMPHERE(jump);
6349: copy_locals(common, ccbegin, ccend, FALSE, localsize + framesize + alternativesize, framesize + alternativesize);
6350: free_stack(common, localsize + framesize + alternativesize);
6351: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_w));
6352: OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
6353: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD, TMP2, 0);
6354: sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);
6355: }
6356:
6357: #undef COMPILE_FALLBACKPATH
6358: #undef CURRENT_AS
6359:
6360: void
1.1.1.2 ! misho 6361: PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra)
1.1 misho 6362: {
6363: struct sljit_compiler *compiler;
6364: fallback_common rootfallback;
6365: compiler_common common_data;
6366: compiler_common *common = &common_data;
1.1.1.2 ! misho 6367: const pcre_uint8 *tables = re->tables;
1.1 misho 6368: pcre_study_data *study;
1.1.1.2 ! misho 6369: pcre_uchar *ccend;
1.1 misho 6370: executable_function *function;
6371: void *executable_func;
6372: sljit_uw executable_size;
6373: struct sljit_label *leave;
6374: struct sljit_label *mainloop = NULL;
6375: struct sljit_label *empty_match_found;
6376: struct sljit_label *empty_match_fallback;
6377: struct sljit_jump *alloc_error;
6378: struct sljit_jump *reqbyte_notfound = NULL;
6379: struct sljit_jump *empty_match;
6380:
6381: SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0);
6382: study = extra->study_data;
6383:
6384: if (!tables)
1.1.1.2 ! misho 6385: tables = PRIV(default_tables);
1.1 misho 6386:
6387: memset(&rootfallback, 0, sizeof(fallback_common));
1.1.1.2 ! misho 6388: rootfallback.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size;
1.1 misho 6389:
6390: common->compiler = NULL;
6391: common->start = rootfallback.cc;
6392: common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w);
6393: common->fcc = tables + fcc_offset;
6394: common->lcc = (sljit_w)(tables + lcc_offset);
6395: common->nltype = NLTYPE_FIXED;
6396: switch(re->options & PCRE_NEWLINE_BITS)
6397: {
6398: case 0:
6399: /* Compile-time default */
6400: switch (NEWLINE)
6401: {
6402: case -1: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
6403: case -2: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
6404: default: common->newline = NEWLINE; break;
6405: }
6406: break;
6407: case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break;
6408: case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break;
6409: case PCRE_NEWLINE_CR+
6410: PCRE_NEWLINE_LF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;
6411: case PCRE_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
6412: case PCRE_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
6413: default: return;
6414: }
6415: if ((re->options & PCRE_BSR_ANYCRLF) != 0)
6416: common->bsr_nltype = NLTYPE_ANYCRLF;
6417: else if ((re->options & PCRE_BSR_UNICODE) != 0)
6418: common->bsr_nltype = NLTYPE_ANY;
6419: else
6420: {
6421: #ifdef BSR_ANYCRLF
6422: common->bsr_nltype = NLTYPE_ANYCRLF;
6423: #else
6424: common->bsr_nltype = NLTYPE_ANY;
6425: #endif
6426: }
6427: common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
6428: common->ctypes = (sljit_w)(tables + ctypes_offset);
1.1.1.2 ! misho 6429: common->name_table = (sljit_w)((pcre_uchar *)re + re->name_table_offset);
1.1 misho 6430: common->name_count = re->name_count;
6431: common->name_entry_size = re->name_entry_size;
6432: common->acceptlabel = NULL;
6433: common->stubs = NULL;
6434: common->entries = NULL;
6435: common->currententry = NULL;
6436: common->accept = NULL;
6437: common->calllimit = NULL;
6438: common->stackalloc = NULL;
6439: common->revertframes = NULL;
6440: common->wordboundary = NULL;
6441: common->anynewline = NULL;
6442: common->hspace = NULL;
6443: common->vspace = NULL;
6444: common->casefulcmp = NULL;
6445: common->caselesscmp = NULL;
6446: common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
1.1.1.2 ! misho 6447: #ifdef SUPPORT_UTF
! 6448: /* PCRE_UTF16 has the same value as PCRE_UTF8. */
! 6449: common->utf = (re->options & PCRE_UTF8) != 0;
1.1 misho 6450: #ifdef SUPPORT_UCP
1.1.1.2 ! misho 6451: common->use_ucp = (re->options & PCRE_UCP) != 0;
1.1 misho 6452: #endif
1.1.1.2 ! misho 6453: common->utfreadchar = NULL;
! 6454: #ifdef COMPILE_PCRE8
! 6455: common->utfreadtype8 = NULL;
1.1 misho 6456: #endif
1.1.1.2 ! misho 6457: #endif /* SUPPORT_UTF */
1.1 misho 6458: #ifdef SUPPORT_UCP
6459: common->getucd = NULL;
6460: #endif
6461: ccend = bracketend(rootfallback.cc);
6462: SLJIT_ASSERT(*rootfallback.cc == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
6463: common->localsize = get_localspace(common, rootfallback.cc, ccend);
6464: if (common->localsize < 0)
6465: return;
6466: common->localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w);
6467: if (common->localsize > SLJIT_MAX_LOCAL_SIZE)
6468: return;
6469: common->localptrs = (int*)SLJIT_MALLOC((ccend - rootfallback.cc) * sizeof(int));
6470: if (!common->localptrs)
6471: return;
6472: memset(common->localptrs, 0, (ccend - rootfallback.cc) * sizeof(int));
6473: set_localptrs(common, common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w), ccend);
6474:
6475: compiler = sljit_create_compiler();
6476: if (!compiler)
6477: {
6478: SLJIT_FREE(common->localptrs);
6479: return;
6480: }
6481: common->compiler = compiler;
6482:
6483: /* Main pcre_jit_exec entry. */
6484: sljit_emit_enter(compiler, 1, 5, 5, common->localsize);
6485:
6486: /* Register init. */
6487: reset_ovector(common, (re->top_bracket + 1) * 2);
6488: if ((re->flags & PCRE_REQCHSET) != 0)
1.1.1.2 ! misho 6489: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, SLJIT_TEMPORARY_REG1, 0);
1.1 misho 6490:
1.1.1.2 ! misho 6491: OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0);
! 6492: OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1, 0);
1.1 misho 6493: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
6494: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
6495: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
6496: OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, calllimit));
6497: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
6498: OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
6499: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0);
6500:
6501: /* Main part of the matching */
6502: if ((re->options & PCRE_ANCHORED) == 0)
6503: {
6504: mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0);
6505: /* Forward search if possible. */
6506: if ((re->flags & PCRE_FIRSTSET) != 0)
1.1.1.2 ! misho 6507: fast_forward_first_char(common, re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0);
1.1 misho 6508: else if ((re->flags & PCRE_STARTLINE) != 0)
6509: fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0);
6510: else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
6511: fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);
6512: }
6513: if ((re->flags & PCRE_REQCHSET) != 0)
1.1.1.2 ! misho 6514: reqbyte_notfound = search_requested_char(common, re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0);
1.1 misho 6515:
6516: /* Store the current STR_PTR in OVECTOR(0). */
6517: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
6518: /* Copy the limit of allowed recursions. */
6519: OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT);
6520:
6521: compile_hotpath(common, rootfallback.cc, ccend, &rootfallback);
6522: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
6523: {
6524: sljit_free_compiler(compiler);
6525: SLJIT_FREE(common->localptrs);
6526: return;
6527: }
6528:
6529: empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
6530: empty_match_found = LABEL();
6531:
6532: common->acceptlabel = LABEL();
6533: if (common->accept != NULL)
6534: set_jumps(common->accept, common->acceptlabel);
6535:
6536: /* This means we have a match. Update the ovector. */
6537: copy_ovector(common, re->top_bracket + 1);
6538: leave = LABEL();
1.1.1.2 ! misho 6539: sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);
1.1 misho 6540:
6541: empty_match_fallback = LABEL();
6542: compile_fallbackpath(common, rootfallback.top);
6543: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
6544: {
6545: sljit_free_compiler(compiler);
6546: SLJIT_FREE(common->localptrs);
6547: return;
6548: }
6549:
6550: SLJIT_ASSERT(rootfallback.prev == NULL);
6551:
6552: /* Check we have remaining characters. */
6553: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
6554:
6555: if ((re->options & PCRE_ANCHORED) == 0)
6556: {
6557: if ((re->options & PCRE_FIRSTLINE) == 0)
6558: {
6559: if (study != NULL && study->minlength > 1)
6560: {
1.1.1.2 ! misho 6561: OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength));
1.1 misho 6562: CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop);
6563: }
6564: else
6565: CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
6566: }
6567: else
6568: {
6569: if (study != NULL && study->minlength > 1)
6570: {
1.1.1.2 ! misho 6571: OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength));
1.1 misho 6572: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
6573: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER);
6574: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
6575: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_GREATER_EQUAL);
6576: JUMPTO(SLJIT_C_ZERO, mainloop);
6577: }
6578: else
6579: CMPTO(SLJIT_C_LESS, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, mainloop);
6580: }
6581: }
6582:
6583: if (reqbyte_notfound != NULL)
6584: JUMPHERE(reqbyte_notfound);
6585: /* Copy OVECTOR(1) to OVECTOR(0) */
6586: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
6587: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
6588: JUMPTO(SLJIT_JUMP, leave);
6589:
6590: flush_stubs(common);
6591:
6592: JUMPHERE(empty_match);
6593: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
6594: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
6595: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_fallback);
6596: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
6597: CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found);
6598: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
6599: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found);
6600: JUMPTO(SLJIT_JUMP, empty_match_fallback);
6601:
6602: common->currententry = common->entries;
6603: while (common->currententry != NULL)
6604: {
6605: /* Might add new entries. */
6606: compile_recurse(common);
6607: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
6608: {
6609: sljit_free_compiler(compiler);
6610: SLJIT_FREE(common->localptrs);
6611: return;
6612: }
6613: flush_stubs(common);
6614: common->currententry = common->currententry->next;
6615: }
6616:
6617: /* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */
6618: /* This is a (really) rare case. */
6619: set_jumps(common->stackalloc, LABEL());
6620: /* RETURN_ADDR is not a saved register. */
6621: sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize);
6622: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
6623: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
6624: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
6625: OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0);
6626: OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
6627:
6628: sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
6629: alloc_error = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
6630: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
6631: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
6632: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top));
6633: OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit));
6634: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
6635: sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
6636:
6637: /* Allocation failed. */
6638: JUMPHERE(alloc_error);
6639: /* We break the return address cache here, but this is a really rare case. */
6640: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);
6641: JUMPTO(SLJIT_JUMP, leave);
6642:
6643: /* Call limit reached. */
6644: set_jumps(common->calllimit, LABEL());
6645: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
6646: JUMPTO(SLJIT_JUMP, leave);
6647:
6648: if (common->revertframes != NULL)
6649: {
6650: set_jumps(common->revertframes, LABEL());
6651: do_revertframes(common);
6652: }
6653: if (common->wordboundary != NULL)
6654: {
6655: set_jumps(common->wordboundary, LABEL());
6656: check_wordboundary(common);
6657: }
6658: if (common->anynewline != NULL)
6659: {
6660: set_jumps(common->anynewline, LABEL());
6661: check_anynewline(common);
6662: }
6663: if (common->hspace != NULL)
6664: {
6665: set_jumps(common->hspace, LABEL());
6666: check_hspace(common);
6667: }
6668: if (common->vspace != NULL)
6669: {
6670: set_jumps(common->vspace, LABEL());
6671: check_vspace(common);
6672: }
6673: if (common->casefulcmp != NULL)
6674: {
6675: set_jumps(common->casefulcmp, LABEL());
6676: do_casefulcmp(common);
6677: }
6678: if (common->caselesscmp != NULL)
6679: {
6680: set_jumps(common->caselesscmp, LABEL());
6681: do_caselesscmp(common);
6682: }
1.1.1.2 ! misho 6683: #ifdef SUPPORT_UTF
! 6684: if (common->utfreadchar != NULL)
1.1 misho 6685: {
1.1.1.2 ! misho 6686: set_jumps(common->utfreadchar, LABEL());
! 6687: do_utfreadchar(common);
1.1 misho 6688: }
1.1.1.2 ! misho 6689: #ifdef COMPILE_PCRE8
! 6690: if (common->utfreadtype8 != NULL)
1.1 misho 6691: {
1.1.1.2 ! misho 6692: set_jumps(common->utfreadtype8, LABEL());
! 6693: do_utfreadtype8(common);
1.1 misho 6694: }
6695: #endif
1.1.1.2 ! misho 6696: #endif /* COMPILE_PCRE8 */
1.1 misho 6697: #ifdef SUPPORT_UCP
6698: if (common->getucd != NULL)
6699: {
6700: set_jumps(common->getucd, LABEL());
6701: do_getucd(common);
6702: }
6703: #endif
6704:
6705: SLJIT_FREE(common->localptrs);
6706: executable_func = sljit_generate_code(compiler);
6707: executable_size = sljit_get_generated_code_size(compiler);
6708: sljit_free_compiler(compiler);
6709: if (executable_func == NULL)
6710: return;
6711:
6712: function = SLJIT_MALLOC(sizeof(executable_function));
6713: if (function == NULL)
6714: {
6715: /* This case is highly unlikely since we just recently
6716: freed a lot of memory. Although not impossible. */
6717: sljit_free_code(executable_func);
6718: return;
6719: }
6720:
6721: function->executable_func = executable_func;
6722: function->executable_size = executable_size;
6723: function->callback = NULL;
6724: function->userdata = NULL;
6725: extra->executable_jit = function;
6726: extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;
6727: }
6728:
6729: static int jit_machine_stack_exec(jit_arguments *arguments, executable_function *function)
6730: {
6731: union {
6732: void* executable_func;
6733: jit_function call_executable_func;
6734: } convert_executable_func;
1.1.1.2 ! misho 6735: pcre_uint8 local_area[LOCAL_SPACE_SIZE];
1.1 misho 6736: struct sljit_stack local_stack;
6737:
6738: local_stack.top = (sljit_w)&local_area;
6739: local_stack.base = local_stack.top;
6740: local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE;
6741: local_stack.max_limit = local_stack.limit;
6742: arguments->stack = &local_stack;
6743: convert_executable_func.executable_func = function->executable_func;
6744: return convert_executable_func.call_executable_func(arguments);
6745: }
6746:
6747: int
1.1.1.2 ! misho 6748: PRIV(jit_exec)(const REAL_PCRE *re, void *executable_func,
! 6749: const pcre_uchar *subject, int length, int start_offset, int options,
1.1 misho 6750: int match_limit, int *offsets, int offsetcount)
6751: {
6752: executable_function *function = (executable_function*)executable_func;
6753: union {
6754: void* executable_func;
6755: jit_function call_executable_func;
6756: } convert_executable_func;
6757: jit_arguments arguments;
6758: int maxoffsetcount;
6759: int retval;
6760:
6761: /* Sanity checks should be handled by pcre_exec. */
6762: arguments.stack = NULL;
6763: arguments.str = subject + start_offset;
6764: arguments.begin = subject;
6765: arguments.end = subject + length;
6766: arguments.calllimit = match_limit; /* JIT decreases this value less times. */
6767: arguments.notbol = (options & PCRE_NOTBOL) != 0;
6768: arguments.noteol = (options & PCRE_NOTEOL) != 0;
6769: arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
6770: arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
6771: arguments.offsets = offsets;
6772:
6773: /* pcre_exec() rounds offsetcount to a multiple of 3, and then uses only 2/3 of
6774: the output vector for storing captured strings, with the remainder used as
6775: workspace. We don't need the workspace here. For compatibility, we limit the
6776: number of captured strings in the same way as pcre_exec(), so that the user
6777: gets the same result with and without JIT. */
6778:
1.1.1.2 ! misho 6779: if (offsetcount != 2)
! 6780: offsetcount = ((offsetcount - (offsetcount % 3)) * 2) / 3;
1.1 misho 6781: maxoffsetcount = (re->top_bracket + 1) * 2;
6782: if (offsetcount > maxoffsetcount)
6783: offsetcount = maxoffsetcount;
6784: arguments.offsetcount = offsetcount;
6785:
6786: if (function->callback)
6787: arguments.stack = (struct sljit_stack*)function->callback(function->userdata);
6788: else
6789: arguments.stack = (struct sljit_stack*)function->userdata;
6790:
6791: if (arguments.stack == NULL)
6792: retval = jit_machine_stack_exec(&arguments, function);
6793: else
6794: {
6795: convert_executable_func.executable_func = function->executable_func;
6796: retval = convert_executable_func.call_executable_func(&arguments);
6797: }
6798:
6799: if (retval * 2 > offsetcount)
6800: retval = 0;
6801: return retval;
6802: }
6803:
6804: void
1.1.1.2 ! misho 6805: PRIV(jit_free)(void *executable_func)
1.1 misho 6806: {
6807: executable_function *function = (executable_function*)executable_func;
6808: sljit_free_code(function->executable_func);
6809: SLJIT_FREE(function);
6810: }
6811:
6812: int
1.1.1.2 ! misho 6813: PRIV(jit_get_size)(void *executable_func)
1.1 misho 6814: {
6815: return ((executable_function*)executable_func)->executable_size;
6816: }
6817:
1.1.1.2 ! misho 6818: const char*
! 6819: PRIV(jit_get_target)(void)
! 6820: {
! 6821: return sljit_get_platform_name();
! 6822: }
! 6823:
! 6824: #ifdef COMPILE_PCRE8
1.1 misho 6825: PCRE_EXP_DECL pcre_jit_stack *
6826: pcre_jit_stack_alloc(int startsize, int maxsize)
1.1.1.2 ! misho 6827: #else
! 6828: PCRE_EXP_DECL pcre16_jit_stack *
! 6829: pcre16_jit_stack_alloc(int startsize, int maxsize)
! 6830: #endif
1.1 misho 6831: {
6832: if (startsize < 1 || maxsize < 1)
6833: return NULL;
6834: if (startsize > maxsize)
6835: startsize = maxsize;
6836: startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
6837: maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
1.1.1.2 ! misho 6838: return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize);
1.1 misho 6839: }
6840:
1.1.1.2 ! misho 6841: #ifdef COMPILE_PCRE8
1.1 misho 6842: PCRE_EXP_DECL void
6843: pcre_jit_stack_free(pcre_jit_stack *stack)
1.1.1.2 ! misho 6844: #else
! 6845: PCRE_EXP_DECL void
! 6846: pcre16_jit_stack_free(pcre16_jit_stack *stack)
! 6847: #endif
1.1 misho 6848: {
6849: sljit_free_stack((struct sljit_stack*)stack);
6850: }
6851:
1.1.1.2 ! misho 6852: #ifdef COMPILE_PCRE8
1.1 misho 6853: PCRE_EXP_DECL void
6854: pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
1.1.1.2 ! misho 6855: #else
! 6856: PCRE_EXP_DECL void
! 6857: pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
! 6858: #endif
1.1 misho 6859: {
6860: executable_function *function;
6861: if (extra != NULL &&
6862: (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
6863: extra->executable_jit != NULL)
6864: {
6865: function = (executable_function*)extra->executable_jit;
6866: function->callback = callback;
6867: function->userdata = userdata;
6868: }
6869: }
6870:
6871: #else /* SUPPORT_JIT */
6872:
6873: /* These are dummy functions to avoid linking errors when JIT support is not
6874: being compiled. */
6875:
1.1.1.2 ! misho 6876: #ifdef COMPILE_PCRE8
1.1 misho 6877: PCRE_EXP_DECL pcre_jit_stack *
6878: pcre_jit_stack_alloc(int startsize, int maxsize)
1.1.1.2 ! misho 6879: #else
! 6880: PCRE_EXP_DECL pcre16_jit_stack *
! 6881: pcre16_jit_stack_alloc(int startsize, int maxsize)
! 6882: #endif
1.1 misho 6883: {
6884: (void)startsize;
6885: (void)maxsize;
6886: return NULL;
6887: }
6888:
1.1.1.2 ! misho 6889: #ifdef COMPILE_PCRE8
1.1 misho 6890: PCRE_EXP_DECL void
6891: pcre_jit_stack_free(pcre_jit_stack *stack)
1.1.1.2 ! misho 6892: #else
! 6893: PCRE_EXP_DECL void
! 6894: pcre16_jit_stack_free(pcre16_jit_stack *stack)
! 6895: #endif
1.1 misho 6896: {
6897: (void)stack;
6898: }
6899:
1.1.1.2 ! misho 6900: #ifdef COMPILE_PCRE8
1.1 misho 6901: PCRE_EXP_DECL void
6902: pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
1.1.1.2 ! misho 6903: #else
! 6904: PCRE_EXP_DECL void
! 6905: pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
! 6906: #endif
1.1 misho 6907: {
6908: (void)extra;
6909: (void)callback;
6910: (void)userdata;
6911: }
6912:
6913: #endif
6914:
6915: /* End of pcre_jit_compile.c */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>