Diff for /embedaddon/pcre/pcre_jit_compile.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2012/02/21 23:50:25 version 1.1.1.3, 2012/10/09 09:19:17
Line 82  The code generator follows the recursive nature of the Line 82  The code generator follows the recursive nature of the
 expressions. The basic blocks of regular expressions are condition checkers  expressions. The basic blocks of regular expressions are condition checkers
 whose execute different commands depending on the result of the condition check.  whose execute different commands depending on the result of the condition check.
 The relationship between the operators can be horizontal (concatenation) and  The relationship between the operators can be horizontal (concatenation) and
vertical (sub-expression) (See struct fallback_common for more details).vertical (sub-expression) (See struct backtrack_common for more details).
   
   'ab' - 'a' and 'b' regexps are concatenated    'ab' - 'a' and 'b' regexps are concatenated
   'a+' - 'a' is the sub-expression of the '+' operator    'a+' - 'a' is the sub-expression of the '+' operator
   
 The condition checkers are boolean (true/false) checkers. Machine code is generated  The condition checkers are boolean (true/false) checkers. Machine code is generated
 for the checker itself and for the actions depending on the result of the checker.  for the checker itself and for the actions depending on the result of the checker.
The 'true' case is called as the hot path (expected path), and the other is called asThe 'true' case is called as the try path (expected path), and the other is called as
the 'fallback' path. Branch instructions are expesive for all CPUs, so we avoid takenthe 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken
branches on the hot path.branches on the try path.
   
  Greedy star operator (*) :   Greedy star operator (*) :
   Hot path: match happens.   Try path: match happens.
   Fallback path: match failed.   Backtrack path: match failed.
  Non-greedy star operator (*?) :   Non-greedy star operator (*?) :
   Hot path: no need to perform a match.   Try path: no need to perform a match.
   Fallback path: match is required.   Backtrack path: match is required.
   
 The following example shows how the code generated for a capturing bracket  The following example shows how the code generated for a capturing bracket
 with two alternatives. Let A, B, C, D are arbirary regular expressions, and  with two alternatives. Let A, B, C, D are arbirary regular expressions, and
Line 108  we have the following regular expression: Line 108  we have the following regular expression:
   
 The generated code will be the following:  The generated code will be the following:
   
 A hot path A try path
 '(' hot path (pushing arguments to the stack) '(' try path (pushing arguments to the stack)
 B hot path B try path
 ')' hot path (pushing arguments to the stack) ')' try path (pushing arguments to the stack)
 D hot path D try path
  return with successful match   return with successful match
   
 D fallback path D backtrack path
 ')' fallback path (If we arrived from "C" jump to the fallback of "C") ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")
 B fallback path B backtrack path
  C expected path   C expected path
 jump to D hot path jump to D try path
 C fallback path C backtrack path
 A fallback path A backtrack path
   
 Notice, that the order of fallback code paths are the opposite of the fast Notice, that the order of backtrack code paths are the opposite of the fast
  code paths. In this way the topmost value on the stack is always belong   code paths. In this way the topmost value on the stack is always belong
 to the current fallback code path. The fallback code path must check to the current backtrack code path. The backtrack path must check
  whether there is a next alternative. If so, it needs to jump back to   whether there is a next alternative. If so, it needs to jump back to
 the hot path eventually. Otherwise it needs to clear out its own stack the try path eventually. Otherwise it needs to clear out its own stack
 frame and continue the execution on the fallback code paths. frame and continue the execution on the backtrack code paths.
 */  */
   
 /*  /*
 Saved stack frames:  Saved stack frames:
   
 Atomic blocks and asserts require reloading the values of local variables  Atomic blocks and asserts require reloading the values of local variables
when the fallback mechanism performed. Because of OP_RECURSE, the localswhen the backtrack mechanism performed. Because of OP_RECURSE, the locals
 are not necessarly known in compile time, thus we need a dynamic restore  are not necessarly known in compile time, thus we need a dynamic restore
 mechanism.  mechanism.
   
Line 152  typedef struct jit_arguments { Line 152  typedef struct jit_arguments {
   const pcre_uchar *begin;    const pcre_uchar *begin;
   const pcre_uchar *end;    const pcre_uchar *end;
   int *offsets;    int *offsets;
  pcre_uchar *ptr;  pcre_uchar *uchar_ptr;
   pcre_uchar *mark_ptr;
   /* Everything else after. */    /* Everything else after. */
   int offsetcount;    int offsetcount;
   int calllimit;    int calllimit;
Line 162  typedef struct jit_arguments { Line 163  typedef struct jit_arguments {
   pcre_uint8 notempty_atstart;    pcre_uint8 notempty_atstart;
 } jit_arguments;  } jit_arguments;
   
typedef struct executable_function {typedef struct executable_functions {
  void *executable_func;  void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES];
   PUBL(jit_callback) callback;    PUBL(jit_callback) callback;
   void *userdata;    void *userdata;
  sljit_uw executable_size;  sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];
} executable_function;} executable_functions;
   
 typedef struct jump_list {  typedef struct jump_list {
   struct sljit_jump *jump;    struct sljit_jump *jump;
Line 187  typedef struct stub_list { Line 188  typedef struct stub_list {
 typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);  typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);
   
 /* The following structure is the key data type for the recursive  /* The following structure is the key data type for the recursive
code generator. It is allocated by compile_hotpath, and containscode generator. It is allocated by compile_trypath, and contains
the aguments for compile_fallbackpath. Must be the first memberthe aguments for compile_backtrackpath. Must be the first member
 of its descendants. */  of its descendants. */
typedef struct fallback_common {typedef struct backtrack_common {
   /* Concatenation stack. */    /* Concatenation stack. */
  struct fallback_common *prev;  struct backtrack_common *prev;
  jump_list *nextfallbacks;  jump_list *nextbacktracks;
   /* Internal stack (for component operators). */    /* Internal stack (for component operators). */
  struct fallback_common *top;  struct backtrack_common *top;
  jump_list *topfallbacks;  jump_list *topbacktracks;
   /* Opcode pointer. */    /* Opcode pointer. */
   pcre_uchar *cc;    pcre_uchar *cc;
} fallback_common;} backtrack_common;
   
typedef struct assert_fallback {typedef struct assert_backtrack {
  fallback_common common;  backtrack_common common;
   jump_list *condfailed;    jump_list *condfailed;
   /* Less than 0 (-1) if a frame is not needed. */    /* Less than 0 (-1) if a frame is not needed. */
   int framesize;    int framesize;
   /* Points to our private memory word on the stack. */    /* Points to our private memory word on the stack. */
   int localptr;    int localptr;
   /* For iterators. */    /* For iterators. */
  struct sljit_label *hotpath;  struct sljit_label *trypath;
} assert_fallback;} assert_backtrack;
   
typedef struct bracket_fallback {typedef struct bracket_backtrack {
  fallback_common common;  backtrack_common common;
   /* Where to coninue if an alternative is successfully matched. */    /* Where to coninue if an alternative is successfully matched. */
  struct sljit_label *althotpath;  struct sljit_label *alttrypath;
   /* For rmin and rmax iterators. */    /* For rmin and rmax iterators. */
  struct sljit_label *recursivehotpath;  struct sljit_label *recursivetrypath;
   /* For greedy ? operator. */    /* For greedy ? operator. */
  struct sljit_label *zerohotpath;  struct sljit_label *zerotrypath;
   /* Contains the branches of a failed condition. */    /* Contains the branches of a failed condition. */
   union {    union {
     /* Both for OP_COND, OP_SCOND. */      /* Both for OP_COND, OP_SCOND. */
     jump_list *condfailed;      jump_list *condfailed;
    assert_fallback *assert;    assert_backtrack *assert;
     /* For OP_ONCE. -1 if not needed. */      /* For OP_ONCE. -1 if not needed. */
     int framesize;      int framesize;
   } u;    } u;
   /* Points to our private memory word on the stack. */    /* Points to our private memory word on the stack. */
   int localptr;    int localptr;
} bracket_fallback;} bracket_backtrack;
   
typedef struct bracketpos_fallback {typedef struct bracketpos_backtrack {
  fallback_common common;  backtrack_common common;
   /* Points to our private memory word on the stack. */    /* Points to our private memory word on the stack. */
   int localptr;    int localptr;
   /* Reverting stack is needed. */    /* Reverting stack is needed. */
   int framesize;    int framesize;
   /* Allocated stack size. */    /* Allocated stack size. */
   int stacksize;    int stacksize;
} bracketpos_fallback;} bracketpos_backtrack;
   
typedef struct braminzero_fallback {typedef struct braminzero_backtrack {
  fallback_common common;  backtrack_common common;
  struct sljit_label *hotpath;  struct sljit_label *trypath;
} braminzero_fallback;} braminzero_backtrack;
   
typedef struct iterator_fallback {typedef struct iterator_backtrack {
  fallback_common common;  backtrack_common common;
   /* Next iteration. */    /* Next iteration. */
  struct sljit_label *hotpath;  struct sljit_label *trypath;
} iterator_fallback;} iterator_backtrack;
   
 typedef struct recurse_entry {  typedef struct recurse_entry {
   struct recurse_entry *next;    struct recurse_entry *next;
Line 263  typedef struct recurse_entry { Line 264  typedef struct recurse_entry {
   int start;    int start;
 } recurse_entry;  } recurse_entry;
   
typedef struct recurse_fallback {typedef struct recurse_backtrack {
  fallback_common common;  backtrack_common common;
} recurse_fallback;} recurse_backtrack;
   
 typedef struct compiler_common {  typedef struct compiler_common {
   struct sljit_compiler *compiler;    struct sljit_compiler *compiler;
   pcre_uchar *start;    pcre_uchar *start;
  int localsize;
   /* Opcode local area direct map. */
   int *localptrs;    int *localptrs;
     int cbraptr;
     /* OVector starting point. Must be divisible by 2. */
     int ovector_start;
     /* Last known position of the requested byte. */
     int req_char_ptr;
     /* Head of the last recursion. */
     int recursive_head;
     /* First inspected character for partial matching. */
     int start_used_ptr;
     /* Starting pointer for partial soft matches. */
     int hit_start;
     /* End pointer of the first line. */
     int first_line_end;
     /* Points to the marked string. */
     int mark_ptr;
   
     /* Other  */
   const pcre_uint8 *fcc;    const pcre_uint8 *fcc;
   sljit_w lcc;    sljit_w lcc;
  int cbraptr;  int mode;
   int nltype;    int nltype;
   int newline;    int newline;
   int bsr_nltype;    int bsr_nltype;
   int endonly;    int endonly;
     BOOL has_set_som;
   sljit_w ctypes;    sljit_w ctypes;
   sljit_uw name_table;    sljit_uw name_table;
   sljit_w name_count;    sljit_w name_count;
   sljit_w name_entry_size;    sljit_w name_entry_size;
   
     /* Labels and jump lists. */
     struct sljit_label *partialmatchlabel;
     struct sljit_label *leavelabel;
   struct sljit_label *acceptlabel;    struct sljit_label *acceptlabel;
   stub_list *stubs;    stub_list *stubs;
   recurse_entry *entries;    recurse_entry *entries;
   recurse_entry *currententry;    recurse_entry *currententry;
     jump_list *partialmatch;
     jump_list *leave;
   jump_list *accept;    jump_list *accept;
   jump_list *calllimit;    jump_list *calllimit;
   jump_list *stackalloc;    jump_list *stackalloc;
Line 349  typedef struct compare_context { Line 375  typedef struct compare_context {
   
 enum {  enum {
   frame_end = 0,    frame_end = 0,
  frame_setstrbegin = -1  frame_setstrbegin = -1,
   frame_setmark = -2
 };  };
   
 /* Undefine sljit macros. */  /* Undefine sljit macros. */
Line 376  enum { Line 403  enum {
 /* Two local variables for possessive quantifiers (char1 cannot use them). */  /* Two local variables for possessive quantifiers (char1 cannot use them). */
 #define POSSESSIVE0      (2 * sizeof(sljit_w))  #define POSSESSIVE0      (2 * sizeof(sljit_w))
 #define POSSESSIVE1      (3 * sizeof(sljit_w))  #define POSSESSIVE1      (3 * sizeof(sljit_w))
 /* Head of the last recursion. */  
 #define RECURSIVE_HEAD   (4 * sizeof(sljit_w))  
 /* Max limit of recursions. */  /* Max limit of recursions. */
#define CALL_LIMIT       (5 * sizeof(sljit_w))#define CALL_LIMIT       (4 * sizeof(sljit_w))
/* Last known position of the requested byte. */ 
#define REQ_CHAR_PTR     (6 * sizeof(sljit_w)) 
/* End pointer of the first line. */ 
#define FIRSTLINE_END    (7 * sizeof(sljit_w)) 
 /* The output vector is stored on the stack, and contains pointers  /* The output vector is stored on the stack, and contains pointers
 to characters. The vector data is divided into two groups: the first  to characters. The vector data is divided into two groups: the first
 group contains the start / end character pointers, and the second is  group contains the start / end character pointers, and the second is
 the start pointers when the end of the capturing group has not yet reached. */  the start pointers when the end of the capturing group has not yet reached. */
#define OVECTOR_START    (8 * sizeof(sljit_w))#define OVECTOR_START    (common->ovector_start)
 #define OVECTOR(i)       (OVECTOR_START + (i) * sizeof(sljit_w))  #define OVECTOR(i)       (OVECTOR_START + (i) * sizeof(sljit_w))
 #define OVECTOR_PRIV(i)  (common->cbraptr + (i) * sizeof(sljit_w))  #define OVECTOR_PRIV(i)  (common->cbraptr + (i) * sizeof(sljit_w))
 #define PRIV_DATA(cc)    (common->localptrs[(cc) - common->start])  #define PRIV_DATA(cc)    (common->localptrs[(cc) - common->start])
Line 426  the start pointers when the end of the capturing group Line 447  the start pointers when the end of the capturing group
   sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))    sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
 #define COND_VALUE(op, dst, dstw, type) \  #define COND_VALUE(op, dst, dstw, type) \
   sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))    sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))
   #define GET_LOCAL_BASE(dst, dstw, offset) \
     sljit_get_local_base(compiler, (dst), (dstw), (offset))
   
 static pcre_uchar* bracketend(pcre_uchar* cc)  static pcre_uchar* bracketend(pcre_uchar* cc)
 {  {
Line 444  return cc; Line 467  return cc;
  init_frame   init_frame
  get_localsize   get_localsize
  copy_locals   copy_locals
 compile_hotpath compile_trypath
 compile_fallbackpath compile_backtrackpath
 */  */
   
 static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc)  static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc)
Line 497  switch(*cc) Line 520  switch(*cc)
   case OP_BRAZERO:    case OP_BRAZERO:
   case OP_BRAMINZERO:    case OP_BRAMINZERO:
   case OP_BRAPOSZERO:    case OP_BRAPOSZERO:
     case OP_COMMIT:
   case OP_FAIL:    case OP_FAIL:
   case OP_ACCEPT:    case OP_ACCEPT:
   case OP_ASSERT_ACCEPT:    case OP_ASSERT_ACCEPT:
Line 635  switch(*cc) Line 659  switch(*cc)
   case OP_SCBRAPOS:    case OP_SCBRAPOS:
   return cc + 1 + LINK_SIZE + IMM2_SIZE;    return cc + 1 + LINK_SIZE + IMM2_SIZE;
   
     case OP_MARK:
     return cc + 1 + 2 + cc[1];
   
   default:    default:
   return NULL;    return NULL;
   }    }
Line 649  while (cc < ccend) Line 676  while (cc < ccend)
   {    {
   switch(*cc)    switch(*cc)
     {      {
       case OP_SET_SOM:
       common->has_set_som = TRUE;
       cc += 1;
       break;
   
     case OP_ASSERT:      case OP_ASSERT:
     case OP_ASSERT_NOT:      case OP_ASSERT_NOT:
     case OP_ASSERTBACK:      case OP_ASSERTBACK:
Line 677  while (cc < ccend) Line 709  while (cc < ccend)
     cc += 1 + LINK_SIZE;      cc += 1 + LINK_SIZE;
     break;      break;
   
       case OP_RECURSE:
       /* Set its value only once. */
       if (common->recursive_head == 0)
         {
         common->recursive_head = common->ovector_start;
         common->ovector_start += sizeof(sljit_w);
         }
       cc += 1 + LINK_SIZE;
       break;
   
       case OP_MARK:
       if (common->mark_ptr == 0)
         {
         common->mark_ptr = common->ovector_start;
         common->ovector_start += sizeof(sljit_w);
         }
       cc += 1 + 2 + cc[1];
       break;
   
     default:      default:
     cc = next_opcode(common, cc);      cc = next_opcode(common, cc);
     if (cc == NULL)      if (cc == NULL)
Line 742  static int get_framesize(compiler_common *common, pcre Line 793  static int get_framesize(compiler_common *common, pcre
 pcre_uchar *ccend = bracketend(cc);  pcre_uchar *ccend = bracketend(cc);
 int length = 0;  int length = 0;
 BOOL possessive = FALSE;  BOOL possessive = FALSE;
BOOL setsom_found = FALSE;BOOL setsom_found = recursive;
 BOOL setmark_found = recursive;
   
 if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))  if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
   {    {
Line 756  while (cc < ccend) Line 808  while (cc < ccend)
   switch(*cc)    switch(*cc)
     {      {
     case OP_SET_SOM:      case OP_SET_SOM:
    case OP_RECURSE:    SLJIT_ASSERT(common->has_set_som);
     if (!setsom_found)      if (!setsom_found)
       {        {
       length += 2;        length += 2;
       setsom_found = TRUE;        setsom_found = TRUE;
       }        }
    cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;    cc += 1;
     break;      break;
   
       case OP_MARK:
       SLJIT_ASSERT(common->mark_ptr != 0);
       if (!setmark_found)
         {
         length += 2;
         setmark_found = TRUE;
         }
       cc += 1 + 2 + cc[1];
       break;
   
       case OP_RECURSE:
       if (common->has_set_som && !setsom_found)
         {
         length += 2;
         setsom_found = TRUE;
         }
       if (common->mark_ptr != 0 && !setmark_found)
         {
         length += 2;
         setmark_found = TRUE;
         }
       cc += 1 + LINK_SIZE;
       break;
   
     case OP_CBRA:      case OP_CBRA:
     case OP_CBRAPOS:      case OP_CBRAPOS:
     case OP_SCBRA:      case OP_SCBRA:
Line 792  static void init_frame(compiler_common *common, pcre_u Line 868  static void init_frame(compiler_common *common, pcre_u
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 pcre_uchar *ccend = bracketend(cc);  pcre_uchar *ccend = bracketend(cc);
BOOL setsom_found = FALSE;BOOL setsom_found = recursive;
 BOOL setmark_found = recursive;
 int offset;  int offset;
   
 /* >= 1 + shortest item size (2) */  /* >= 1 + shortest item size (2) */
Line 807  while (cc < ccend) Line 884  while (cc < ccend)
   switch(*cc)    switch(*cc)
     {      {
     case OP_SET_SOM:      case OP_SET_SOM:
    case OP_RECURSE:    SLJIT_ASSERT(common->has_set_som);
     if (!setsom_found)      if (!setsom_found)
       {        {
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
Line 817  while (cc < ccend) Line 894  while (cc < ccend)
       stackpos += (int)sizeof(sljit_w);        stackpos += (int)sizeof(sljit_w);
       setsom_found = TRUE;        setsom_found = TRUE;
       }        }
    cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;    cc += 1;
     break;      break;
   
       case OP_MARK:
       SLJIT_ASSERT(common->mark_ptr != 0);
       if (!setmark_found)
         {
         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark);
         stackpos += (int)sizeof(sljit_w);
         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
         stackpos += (int)sizeof(sljit_w);
         setmark_found = TRUE;
         }
       cc += 1 + 2 + cc[1];
       break;
   
       case OP_RECURSE:
       if (common->has_set_som && !setsom_found)
         {
         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin);
         stackpos += (int)sizeof(sljit_w);
         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
         stackpos += (int)sizeof(sljit_w);
         setsom_found = TRUE;
         }
       if (common->mark_ptr != 0 && !setmark_found)
         {
         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark);
         stackpos += (int)sizeof(sljit_w);
         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
         stackpos += (int)sizeof(sljit_w);
         setmark_found = TRUE;
         }
       cc += 1 + LINK_SIZE;
       break;
   
     case OP_CBRA:      case OP_CBRA:
     case OP_CBRAPOS:      case OP_CBRAPOS:
     case OP_SCBRA:      case OP_SCBRA:
Line 944  while (status != end) Line 1057  while (status != end)
   switch(status)    switch(status)
     {      {
     case start:      case start:
    SLJIT_ASSERT(save);    SLJIT_ASSERT(save && common->recursive_head != 0);
     count = 1;      count = 1;
    srcw[0] = RECURSIVE_HEAD;    srcw[0] = common->recursive_head;
     status = loop;      status = loop;
     break;      break;
   
Line 1213  if (length < 8) Line 1326  if (length < 8)
   }    }
 else  else
   {    {
  OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START - sizeof(sljit_w));  GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, OVECTOR_START - sizeof(sljit_w));
   OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length);    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length);
   loop = LABEL();    loop = LABEL();
   OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0);    OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0);
Line 1233  OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_L Line 1346  OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_L
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0);
   
 OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0);  OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0);
   if (common->mark_ptr != 0)
     OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
 OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));  OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));
   if (common->mark_ptr != 0)
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_TEMPORARY_REG3, 0);
 OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));  OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
 OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin));  OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin));
OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START);GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START);
 /* Unlikely, but possible */  /* Unlikely, but possible */
 earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0);  earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0);
 loop = LABEL();  loop = LABEL();
Line 1254  JUMPHERE(earlyexit); Line 1371  JUMPHERE(earlyexit);
 /* Calculate the return value, which is the maximum ovector value. */  /* Calculate the return value, which is the maximum ovector value. */
 if (topbracket > 1)  if (topbracket > 1)
   {    {
  OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w));  GET_LOCAL_BASE(SLJIT_TEMPORARY_REG1, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_w));
   OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1);    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1);
   
   /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */    /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */
Line 1268  else Line 1385  else
   OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);    OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
 }  }
   
   static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *leave)
   {
   DEFINE_COMPILER;
   
   SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2);
   SLJIT_ASSERT(common->start_used_ptr != 0 && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0));
   
   OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);
   OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL);
   OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsetcount));
   CMPTO(SLJIT_C_LESS, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 2, leave);
   
   /* Store match begin and end. */
   OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, begin));
   OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsets));
   OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start);
   OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0);
   #ifdef COMPILE_PCRE16
   OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1);
   #endif
   OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(int), SLJIT_SAVED_REG2, 0);
   
   OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG1, 0);
   #ifdef COMPILE_PCRE16
   OP2(SLJIT_ASHR, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1);
   #endif
   OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), 0, SLJIT_TEMPORARY_REG3, 0);
   
   JUMPTO(SLJIT_JUMP, leave);
   }
   
   static SLJIT_INLINE void check_start_used_ptr(compiler_common *common)
   {
   /* May destroy TMP1. */
   DEFINE_COMPILER;
   struct sljit_jump *jump;
   
   if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
     {
     /* The value of -1 must be kept for start_used_ptr! */
     OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, 1);
     /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting
     is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */
     jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_PTR, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
     JUMPHERE(jump);
     }
   else if (common->mode == JIT_PARTIAL_HARD_COMPILE)
     {
     jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
     JUMPHERE(jump);
     }
   }
   
 static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc)  static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc)
 {  {
 /* Detects if the character has an othercase. */  /* Detects if the character has an othercase. */
Line 1389  return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (b Line 1561  return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (b
 #endif /* COMPILE_PCRE8 */  #endif /* COMPILE_PCRE8 */
 }  }
   
static SLJIT_INLINE void check_input_end(compiler_common *common, jump_list **fallbacks)static void check_partial(compiler_common *common, BOOL force)
 {  {
   /* Checks whether a partial matching is occured. Does not modify registers. */
 DEFINE_COMPILER;  DEFINE_COMPILER;
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));struct sljit_jump *jump = NULL;
 
 SLJIT_ASSERT(!force || common->mode != JIT_COMPILE);
 
 if (common->mode == JIT_COMPILE)
   return;
 
 if (!force)
   jump = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
 else if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
   jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1);
 
 if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
 else
   {
   if (common->partialmatchlabel != NULL)
     JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
   else
     add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
   }
 
 if (jump != NULL)
   JUMPHERE(jump);
 }  }
   
   static struct sljit_jump *check_str_end(compiler_common *common)
   {
   /* Does not affect registers. Usually used in a tight spot. */
   DEFINE_COMPILER;
   struct sljit_jump *jump;
   struct sljit_jump *nohit;
   struct sljit_jump *return_value;
   
   if (common->mode == JIT_COMPILE)
     return CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
   
   jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
   if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
     {
     nohit = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
     JUMPHERE(nohit);
     return_value = JUMP(SLJIT_JUMP);
     }
   else
     {
     return_value = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
     if (common->partialmatchlabel != NULL)
       JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
     else
       add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
     }
   JUMPHERE(jump);
   return return_value;
   }
   
   static void detect_partial_match(compiler_common *common, jump_list **backtracks)
   {
   DEFINE_COMPILER;
   struct sljit_jump *jump;
   
   if (common->mode == JIT_COMPILE)
     {
     add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
     return;
     }
   
   /* Partial matching mode. */
   jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
   add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0));
   if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
     {
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
     add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
     }
   else
     {
     if (common->partialmatchlabel != NULL)
       JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
     else
       add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
     }
   JUMPHERE(jump);
   }
   
 static void read_char(compiler_common *common)  static void read_char(compiler_common *common)
 {  {
 /* Reads the character into TMP1, updates STR_PTR.  /* Reads the character into TMP1, updates STR_PTR.
Line 1533  if (common->utf) Line 1789  if (common->utf)
 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
 }  }
   
static void check_newlinechar(compiler_common *common, int nltype, jump_list **fallbacks, BOOL jumpiftrue)static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpiftrue)
 {  {
 /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */  /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
 DEFINE_COMPILER;  DEFINE_COMPILER;
Line 1541  DEFINE_COMPILER; Line 1797  DEFINE_COMPILER;
 if (nltype == NLTYPE_ANY)  if (nltype == NLTYPE_ANY)
   {    {
   add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));    add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
  add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));  add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
   }    }
 else if (nltype == NLTYPE_ANYCRLF)  else if (nltype == NLTYPE_ANYCRLF)
   {    {
Line 1549  else if (nltype == NLTYPE_ANYCRLF) Line 1805  else if (nltype == NLTYPE_ANYCRLF)
   COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);    COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
   OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
   COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);    COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
  add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));  add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
   }    }
 else  else
   {    {
   SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);    SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);
  add_jump(compiler, fallbacks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));  add_jump(compiler, backtracks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
   }    }
 }  }
   
Line 1568  of the character (>= 0xc0). Return char value in TMP1, Line 1824  of the character (>= 0xc0). Return char value in TMP1,
 DEFINE_COMPILER;  DEFINE_COMPILER;
 struct sljit_jump *jump;  struct sljit_jump *jump;
   
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
 /* Searching for the first zero. */  /* Searching for the first zero. */
 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
 jump = JUMP(SLJIT_C_NOT_ZERO);  jump = JUMP(SLJIT_C_NOT_ZERO);
Line 1627  DEFINE_COMPILER; Line 1883  DEFINE_COMPILER;
 struct sljit_jump *jump;  struct sljit_jump *jump;
 struct sljit_jump *compare;  struct sljit_jump *compare;
   
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
   
 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
 jump = JUMP(SLJIT_C_NOT_ZERO);  jump = JUMP(SLJIT_C_NOT_ZERO);
Line 1664  of the character (>= 0xd800). Return char value in TMP Line 1920  of the character (>= 0xd800). Return char value in TMP
 DEFINE_COMPILER;  DEFINE_COMPILER;
 struct sljit_jump *jump;  struct sljit_jump *jump;
   
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
 jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);  jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);
 /* Do nothing, only return. */  /* Do nothing, only return. */
 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);  sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
Line 1701  DEFINE_COMPILER; Line 1957  DEFINE_COMPILER;
   
 SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);  SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
   
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
 OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);  OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(ucd_stage1));  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(ucd_stage1));
 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
Line 1737  if (!(hascrorlf || firstline) && (common->nltype == NL Line 1993  if (!(hascrorlf || firstline) && (common->nltype == NL
 if (firstline)  if (firstline)
   {    {
   /* Search for the end of the first line. */    /* Search for the end of the first line. */
     SLJIT_ASSERT(common->first_line_end != 0);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_END, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_END, 0);
   
   if (common->nltype == NLTYPE_FIXED && common->newline > 255)    if (common->nltype == NLTYPE_FIXED && common->newline > 255)
     {      {
Line 1749  if (firstline) Line 2006  if (firstline)
     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));      OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
     CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);      CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
     CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);      CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
    OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));    OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
     }      }
   else    else
     {      {
     end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);      end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
     mainloop = LABEL();      mainloop = LABEL();
     /* Continual stores does not cause data dependency. */      /* Continual stores does not cause data dependency. */
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0);
     read_char(common);      read_char(common);
     check_newlinechar(common, common->nltype, &newline, TRUE);      check_newlinechar(common, common->nltype, &newline, TRUE);
     CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);      CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0);
     set_jumps(newline, LABEL());      set_jumps(newline, LABEL());
     }      }
   
Line 1843  pcre_uchar oc, bit; Line 2100  pcre_uchar oc, bit;
 if (firstline)  if (firstline)
   {    {
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
   }    }
   
 start = LABEL();  start = LABEL();
Line 1921  jump_list *newline = NULL; Line 2178  jump_list *newline = NULL;
 if (firstline)  if (firstline)
   {    {
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
   }    }
   
 if (common->nltype == NLTYPE_FIXED && common->newline > 255)  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
Line 2005  struct sljit_jump *jump; Line 2262  struct sljit_jump *jump;
 if (firstline)  if (firstline)
   {    {
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
   }    }
   
 start = LABEL();  start = LABEL();
Line 2070  struct sljit_jump *foundoc = NULL; Line 2327  struct sljit_jump *foundoc = NULL;
 struct sljit_jump *notfound;  struct sljit_jump *notfound;
 pcre_uchar oc, bit;  pcre_uchar oc, bit;
   
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR);SLJIT_ASSERT(common->req_char_ptr != 0);
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr);
 OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);  OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);
 toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0);  toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0);
 alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0);  alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0);
Line 2115  JUMPTO(SLJIT_JUMP, loop); Line 2373  JUMPTO(SLJIT_JUMP, loop);
 JUMPHERE(found);  JUMPHERE(found);
 if (foundoc)  if (foundoc)
   JUMPHERE(foundoc);    JUMPHERE(foundoc);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, TMP1, 0);OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, TMP1, 0);
 JUMPHERE(alreadyfound);  JUMPHERE(alreadyfound);
 JUMPHERE(toolong);  JUMPHERE(toolong);
 return notfound;  return notfound;
Line 2127  DEFINE_COMPILER; Line 2385  DEFINE_COMPILER;
 struct sljit_jump *jump;  struct sljit_jump *jump;
 struct sljit_label *mainloop;  struct sljit_label *mainloop;
   
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
 OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0);  OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0);
   GET_LOCAL_BASE(TMP3, 0, 0);
   
 /* Drop frames until we reach STACK_TOP. */  /* Drop frames until we reach STACK_TOP. */
 mainloop = LABEL();  mainloop = LABEL();
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
 jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);  jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_LOCALS_REG, 0);OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0);
 OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));  OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
 OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w));  OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w));
 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w));  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w));
Line 2154  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0 Line 2413  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0
 JUMPTO(SLJIT_JUMP, mainloop);  JUMPTO(SLJIT_JUMP, mainloop);
   
 JUMPHERE(jump);  JUMPHERE(jump);
   if (common->mark_ptr != 0)
     {
     jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setmark);
     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0);
     JUMPTO(SLJIT_JUMP, mainloop);
   
     JUMPHERE(jump);
     }
   
 /* Unknown command. */  /* Unknown command. */
 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
 JUMPTO(SLJIT_JUMP, mainloop);  JUMPTO(SLJIT_JUMP, mainloop);
Line 2162  JUMPTO(SLJIT_JUMP, mainloop); Line 2432  JUMPTO(SLJIT_JUMP, mainloop);
 static void check_wordboundary(compiler_common *common)  static void check_wordboundary(compiler_common *common)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
struct sljit_jump *beginend;struct sljit_jump *skipread;
 #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF  #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF
 struct sljit_jump *jump;  struct sljit_jump *jump;
 #endif  #endif
   
 SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);  SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);
   
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
 /* Get type of the previous char, and put it to LOCALS1. */  /* Get type of the previous char, and put it to LOCALS1. */
 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0);
beginend = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);skipread = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
 skip_char_back(common);  skip_char_back(common);
   check_start_used_ptr(common);
 read_char(common);  read_char(common);
   
 /* Testing char type. */  /* Testing char type. */
Line 2216  else Line 2487  else
     JUMPHERE(jump);      JUMPHERE(jump);
 #endif /* COMPILE_PCRE8 */  #endif /* COMPILE_PCRE8 */
   }    }
JUMPHERE(beginend);JUMPHERE(skipread);
   
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);  OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
beginend = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);skipread = check_str_end(common);
 peek_char(common);  peek_char(common);
   
 /* Testing char type. This is a code duplication. */  /* Testing char type. This is a code duplication. */
Line 2260  else Line 2531  else
     JUMPHERE(jump);      JUMPHERE(jump);
 #endif /* COMPILE_PCRE8 */  #endif /* COMPILE_PCRE8 */
   }    }
JUMPHERE(beginend);JUMPHERE(skipread);
   
 OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);  OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
 sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);  sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
Line 2271  static void check_anynewline(compiler_common *common) Line 2542  static void check_anynewline(compiler_common *common)
 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */  /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
 DEFINE_COMPILER;  DEFINE_COMPILER;
   
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
   
 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
Line 2298  static void check_hspace(compiler_common *common) Line 2569  static void check_hspace(compiler_common *common)
 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */  /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
 DEFINE_COMPILER;  DEFINE_COMPILER;
   
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
   
 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
Line 2337  static void check_vspace(compiler_common *common) Line 2608  static void check_vspace(compiler_common *common)
 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */  /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
 DEFINE_COMPILER;  DEFINE_COMPILER;
   
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
   
 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
Line 2369  DEFINE_COMPILER; Line 2640  DEFINE_COMPILER;
 struct sljit_jump *jump;  struct sljit_jump *jump;
 struct sljit_label *label;  struct sljit_label *label;
   
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
 OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);  OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0);
Line 2398  DEFINE_COMPILER; Line 2669  DEFINE_COMPILER;
 struct sljit_jump *jump;  struct sljit_jump *jump;
 struct sljit_label *label;  struct sljit_label *label;
   
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
   
 OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);  OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);
Line 2445  static const pcre_uchar *SLJIT_CALL do_utf_caselesscmp Line 2716  static const pcre_uchar *SLJIT_CALL do_utf_caselesscmp
 {  {
 /* This function would be ineffective to do in JIT level. */  /* This function would be ineffective to do in JIT level. */
 int c1, c2;  int c1, c2;
const pcre_uchar *src2 = args->ptr;const pcre_uchar *src2 = args->uchar_ptr;
 const pcre_uchar *end2 = args->end;  const pcre_uchar *end2 = args->end;
   
 while (src1 < end1)  while (src1 < end1)
   {    {
   if (src2 >= end2)    if (src2 >= end2)
    return 0;    return (pcre_uchar*)1;
   GETCHARINC(c1, src1);    GETCHARINC(c1, src1);
   GETCHARINC(c2, src2);    GETCHARINC(c2, src2);
  if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return 0;  if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return NULL;
   }    }
 return src2;  return src2;
 }  }
Line 2462  return src2; Line 2733  return src2;
 #endif /* SUPPORT_UTF && SUPPORT_UCP */  #endif /* SUPPORT_UTF && SUPPORT_UCP */
   
 static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc,  static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc,
    compare_context* context, jump_list **fallbacks)    compare_context* context, jump_list **backtracks)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 unsigned int othercasebit = 0;  unsigned int othercasebit = 0;
Line 2563  do Line 2834  do
       case 4 / sizeof(pcre_uchar):        case 4 / sizeof(pcre_uchar):
       if (context->oc.asint != 0)        if (context->oc.asint != 0)
         OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);          OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);
      add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));
       break;        break;
   
       case 2 / sizeof(pcre_uchar):        case 2 / sizeof(pcre_uchar):
       if (context->oc.asushort != 0)        if (context->oc.asushort != 0)
         OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);          OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);
      add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));
       break;        break;
   
 #ifdef COMPILE_PCRE8  #ifdef COMPILE_PCRE8
       case 1:        case 1:
       if (context->oc.asbyte != 0)        if (context->oc.asbyte != 0)
         OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);          OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);
      add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));
       break;        break;
 #endif  #endif
   
Line 2602  do Line 2873  do
   if (othercasebit != 0 && othercasechar == cc)    if (othercasebit != 0 && othercasechar == cc)
     {      {
     OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);      OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));
     }      }
   else    else
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));
   
 #endif  #endif
   
Line 2641  return cc; Line 2912  return cc;
     } \      } \
   charoffset = (value);    charoffset = (value);
   
static void compile_xclass_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks)static void compile_xclass_trypath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 jump_list *found = NULL;  jump_list *found = NULL;
jump_list **list = (*cc & XCL_NOT) == 0 ? &found : fallbacks;jump_list **list = (*cc & XCL_NOT) == 0 ? &found : backtracks;
 unsigned int c;  unsigned int c;
 int compares;  int compares;
 struct sljit_jump *jump = NULL;  struct sljit_jump *jump = NULL;
Line 2660  int invertcmp, numberofcmps; Line 2931  int invertcmp, numberofcmps;
 unsigned int charoffset;  unsigned int charoffset;
   
 /* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */  /* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */
check_input_end(common, fallbacks);detect_partial_match(common, backtracks);
 read_char(common);  read_char(common);
   
 if ((*cc++ & XCL_MAP) != 0)  if ((*cc++ & XCL_MAP) != 0)
Line 2811  typeoffset = 0; Line 3082  typeoffset = 0;
 while (*cc != XCL_END)  while (*cc != XCL_END)
   {    {
   compares--;    compares--;
  invertcmp = (compares == 0 && list != fallbacks);  invertcmp = (compares == 0 && list != backtracks);
   jump = NULL;    jump = NULL;
   
   if (*cc == XCL_SINGLE)    if (*cc == XCL_SINGLE)
Line 2893  while (*cc != XCL_END) Line 3164  while (*cc != XCL_END)
     switch(*cc)      switch(*cc)
       {        {
       case PT_ANY:        case PT_ANY:
      if (list != fallbacks)      if (list != backtracks)
         {          {
         if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))          if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))
           continue;            continue;
Line 2966  while (*cc != XCL_END) Line 3237  while (*cc != XCL_END)
 #endif  #endif
   
   if (jump != NULL)    if (jump != NULL)
    add_jump(compiler, compares > 0 ? list : fallbacks, jump);    add_jump(compiler, compares > 0 ? list : backtracks, jump);
   }    }
   
 if (found != NULL)  if (found != NULL)
Line 2978  if (found != NULL) Line 3249  if (found != NULL)
   
 #endif  #endif
   
static pcre_uchar *compile_char1_hotpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **fallbacks)static pcre_uchar *compile_char1_trypath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 int length;  int length;
Line 2997  switch(type) Line 3268  switch(type)
   case OP_SOD:    case OP_SOD:
   OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);    OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
  add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
   return cc;    return cc;
   
   case OP_SOM:    case OP_SOM:
   OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);    OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
  add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
   return cc;    return cc;
   
   case OP_NOT_WORD_BOUNDARY:    case OP_NOT_WORD_BOUNDARY:
   case OP_WORD_BOUNDARY:    case OP_WORD_BOUNDARY:
   add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));    add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
  add_jump(compiler, fallbacks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));  add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
   return cc;    return cc;
   
   case OP_NOT_DIGIT:    case OP_NOT_DIGIT:
   case OP_DIGIT:    case OP_DIGIT:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   read_char8_type(common);    read_char8_type(common);
   OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);    OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
  add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));  add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
   return cc;    return cc;
   
   case OP_NOT_WHITESPACE:    case OP_NOT_WHITESPACE:
   case OP_WHITESPACE:    case OP_WHITESPACE:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   read_char8_type(common);    read_char8_type(common);
   OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);    OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
  add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));  add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
   return cc;    return cc;
   
   case OP_NOT_WORDCHAR:    case OP_NOT_WORDCHAR:
   case OP_WORDCHAR:    case OP_WORDCHAR:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   read_char8_type(common);    read_char8_type(common);
   OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);    OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
  add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));  add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
   return cc;    return cc;
   
   case OP_ANY:    case OP_ANY:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   read_char(common);    read_char(common);
   if (common->nltype == NLTYPE_FIXED && common->newline > 255)    if (common->nltype == NLTYPE_FIXED && common->newline > 255)
     {      {
     jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);      jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
    jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);    if (common->mode != JIT_PARTIAL_HARD_COMPILE)
       jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
     else
       jump[1] = check_str_end(common);
 
     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
    add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));    add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));
    JUMPHERE(jump[1]);    if (jump[1] != NULL)
       JUMPHERE(jump[1]);
     JUMPHERE(jump[0]);      JUMPHERE(jump[0]);
     }      }
   else    else
    check_newlinechar(common, common->nltype, fallbacks, TRUE);    check_newlinechar(common, common->nltype, backtracks, TRUE);
   return cc;    return cc;
   
   case OP_ALLANY:    case OP_ALLANY:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
   if (common->utf)    if (common->utf)
     {      {
Line 3081  switch(type) Line 3357  switch(type)
   return cc;    return cc;
   
   case OP_ANYBYTE:    case OP_ANYBYTE:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
   return cc;    return cc;
   
Line 3094  switch(type) Line 3370  switch(type)
   propdata[2] = cc[0];    propdata[2] = cc[0];
   propdata[3] = cc[1];    propdata[3] = cc[1];
   propdata[4] = XCL_END;    propdata[4] = XCL_END;
  compile_xclass_hotpath(common, propdata, fallbacks);  compile_xclass_trypath(common, propdata, backtracks);
   return cc + 2;    return cc + 2;
 #endif  #endif
 #endif  #endif
   
   case OP_ANYNL:    case OP_ANYNL:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   read_char(common);    read_char(common);
   jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);    jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
  jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);  /* We don't need to handle soft partial matching case. */
   if (common->mode != JIT_PARTIAL_HARD_COMPILE)
     jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
   else
     jump[1] = check_str_end(common);
   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
   jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);    jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
   jump[3] = JUMP(SLJIT_JUMP);    jump[3] = JUMP(SLJIT_JUMP);
   JUMPHERE(jump[0]);    JUMPHERE(jump[0]);
  check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE);  check_newlinechar(common, common->bsr_nltype, backtracks, FALSE);
   JUMPHERE(jump[1]);    JUMPHERE(jump[1]);
   JUMPHERE(jump[2]);    JUMPHERE(jump[2]);
   JUMPHERE(jump[3]);    JUMPHERE(jump[3]);
Line 3117  switch(type) Line 3397  switch(type)
   
   case OP_NOT_HSPACE:    case OP_NOT_HSPACE:
   case OP_HSPACE:    case OP_HSPACE:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   read_char(common);    read_char(common);
   add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));    add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
  add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));  add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
   return cc;    return cc;
   
   case OP_NOT_VSPACE:    case OP_NOT_VSPACE:
   case OP_VSPACE:    case OP_VSPACE:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   read_char(common);    read_char(common);
   add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));    add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
  add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));  add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
   return cc;    return cc;
   
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
   case OP_EXTUNI:    case OP_EXTUNI:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   read_char(common);    read_char(common);
   add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));    add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);    OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
  add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc));  add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc));
   
   label = LABEL();    label = LABEL();
   jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);    jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
Line 3149  switch(type) Line 3429  switch(type)
   
   OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);    OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
   JUMPHERE(jump[0]);    JUMPHERE(jump[0]);
     if (common->mode == JIT_PARTIAL_HARD_COMPILE)
       {
       jump[0] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
       /* Since we successfully read a char above, partial matching must occure. */
       check_partial(common, TRUE);
       JUMPHERE(jump[0]);
       }
   return cc;    return cc;
 #endif  #endif
   
   case OP_EODN:    case OP_EODN:
     /* Requires rather complex checks. */
   jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);    jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
   if (common->nltype == NLTYPE_FIXED && common->newline > 255)    if (common->nltype == NLTYPE_FIXED && common->newline > 255)
     {      {
     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));      OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));    if (common->mode == JIT_COMPILE)
       add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
     else
       {
       jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0);
       OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
       COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS);
       OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
       COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_NOT_EQUAL);
       add_jump(compiler, backtracks, JUMP(SLJIT_C_NOT_EQUAL));
       check_partial(common, TRUE);
       add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
       JUMPHERE(jump[1]);
       }
     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));      OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
     }      }
   else if (common->nltype == NLTYPE_FIXED)    else if (common->nltype == NLTYPE_FIXED)
     {      {
     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));      OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
     }      }
   else    else
     {      {
Line 3177  switch(type) Line 3478  switch(type)
     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));      OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
     jump[2] = JUMP(SLJIT_C_GREATER);      jump[2] = JUMP(SLJIT_C_GREATER);
    add_jump(compiler, fallbacks, JUMP(SLJIT_C_LESS));    add_jump(compiler, backtracks, JUMP(SLJIT_C_LESS));
     /* Equal. */      /* Equal. */
     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
     jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);      jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
    add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP));    add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
   
     JUMPHERE(jump[1]);      JUMPHERE(jump[1]);
     if (common->nltype == NLTYPE_ANYCRLF)      if (common->nltype == NLTYPE_ANYCRLF)
       {        {
       OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));        OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
      add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0));      add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0));
      add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
       }        }
     else      else
       {        {
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0);
       read_char(common);        read_char(common);
      add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
       add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));        add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
      add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));      add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
       }        }
     JUMPHERE(jump[2]);      JUMPHERE(jump[2]);
     JUMPHERE(jump[3]);      JUMPHERE(jump[3]);
     }      }
   JUMPHERE(jump[0]);    JUMPHERE(jump[0]);
     check_partial(common, FALSE);
   return cc;    return cc;
   
   case OP_EOD:    case OP_EOD:
  add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
   check_partial(common, FALSE);
   return cc;    return cc;
   
   case OP_CIRC:    case OP_CIRC:
   OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);    OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
  add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0));
   OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));    OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
  add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
   return cc;    return cc;
   
   case OP_CIRCM:    case OP_CIRCM:
Line 3222  switch(type) Line 3525  switch(type)
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
   jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0);    jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0);
   OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));    OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
  add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
   jump[0] = JUMP(SLJIT_JUMP);    jump[0] = JUMP(SLJIT_JUMP);
   JUMPHERE(jump[1]);    JUMPHERE(jump[1]);
   
  add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, STR_PTR, 0, STR_END, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
   if (common->nltype == NLTYPE_FIXED && common->newline > 255)    if (common->nltype == NLTYPE_FIXED && common->newline > 255)
     {      {
     OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));      OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0));    add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0));
     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));      OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
     }      }
   else    else
     {      {
     skip_char_back(common);      skip_char_back(common);
     read_char(common);      read_char(common);
    check_newlinechar(common, common->nltype, fallbacks, FALSE);    check_newlinechar(common, common->nltype, backtracks, FALSE);
     }      }
   JUMPHERE(jump[0]);    JUMPHERE(jump[0]);
   return cc;    return cc;
Line 3248  switch(type) Line 3551  switch(type)
   case OP_DOLL:    case OP_DOLL:
   OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);    OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
   OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));    OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
  add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
   
   if (!common->endonly)    if (!common->endonly)
    compile_char1_hotpath(common, OP_EODN, cc, fallbacks);    compile_char1_trypath(common, OP_EODN, cc, backtracks);
   else    else
    add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));    {
     add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
     check_partial(common, FALSE);
     }
   return cc;    return cc;
   
   case OP_DOLLM:    case OP_DOLLM:
   jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);    jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
   OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);    OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
   OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));    OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
  add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
   check_partial(common, FALSE);
   jump[0] = JUMP(SLJIT_JUMP);    jump[0] = JUMP(SLJIT_JUMP);
   JUMPHERE(jump[1]);    JUMPHERE(jump[1]);
   
   if (common->nltype == NLTYPE_FIXED && common->newline > 255)    if (common->nltype == NLTYPE_FIXED && common->newline > 255)
     {      {
     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));      OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0));  
     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
       if (common->mode == JIT_COMPILE)
         add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0));
       else
         {
         jump[1] = CMP(SLJIT_C_LESS_EQUAL, TMP2, 0, STR_END, 0);
         /* STR_PTR = STR_END - IN_UCHARS(1) */
         add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
         check_partial(common, TRUE);
         add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
         JUMPHERE(jump[1]);
         }
   
     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));      OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
     }      }
   else    else
     {      {
     peek_char(common);      peek_char(common);
    check_newlinechar(common, common->nltype, fallbacks, FALSE);    check_newlinechar(common, common->nltype, backtracks, FALSE);
     }      }
   JUMPHERE(jump[0]);    JUMPHERE(jump[0]);
   return cc;    return cc;
Line 3287  switch(type) Line 3605  switch(type)
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
   if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);    if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);
 #endif  #endif
  if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)  if (common->mode == JIT_COMPILE && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0))
     {      {
     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));      OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
    add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));    add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
   
     context.length = IN_UCHARS(length);      context.length = IN_UCHARS(length);
     context.sourcereg = -1;      context.sourcereg = -1;
 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED  #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
     context.ucharptr = 0;      context.ucharptr = 0;
 #endif  #endif
    return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks);    return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);
     }      }
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   read_char(common);    read_char(common);
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
   if (common->utf)    if (common->utf)
Line 3309  switch(type) Line 3627  switch(type)
   else    else
 #endif  #endif
     c = *cc;      c = *cc;
     if (type == OP_CHAR || !char_has_othercase(common, cc))
       {
       add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c));
       return cc + length;
       }
     oc = char_othercase(common, c);
     bit = c ^ oc;
     if (ispowerof2(bit))
       {
       OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
       add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
       return cc + length;
       }
   OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c);    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c);
   COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);    COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
   OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c));    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c));
   COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);    COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
  add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));  add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
   return cc + length;    return cc + length;
   
   case OP_NOT:    case OP_NOT:
   case OP_NOTI:    case OP_NOTI:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   length = 1;    length = 1;
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
   if (common->utf)    if (common->utf)
Line 3329  switch(type) Line 3660  switch(type)
       {        {
       OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);        OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
       if (type == OP_NOT || !char_has_othercase(common, cc))        if (type == OP_NOT || !char_has_othercase(common, cc))
        add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));        add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
       else        else
         {          {
         /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */          /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
         OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20);          OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20);
        add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20));        add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20));
         }          }
       /* Skip the variable-length character. */        /* Skip the variable-length character. */
       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));        OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
Line 3359  switch(type) Line 3690  switch(type)
     }      }
   
   if (type == OP_NOT || !char_has_othercase(common, cc))    if (type == OP_NOT || !char_has_othercase(common, cc))
    add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));    add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
   else    else
     {      {
     oc = char_othercase(common, c);      oc = char_othercase(common, c);
Line 3367  switch(type) Line 3698  switch(type)
     if (ispowerof2(bit))      if (ispowerof2(bit))
       {        {
       OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);        OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
      add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));      add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
       }        }
     else      else
       {        {
      add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));      add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
      add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc));      add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc));
       }        }
     }      }
  return cc + 1;  return cc + length;
   
   case OP_CLASS:    case OP_CLASS:
   case OP_NCLASS:    case OP_NCLASS:
  check_input_end(common, fallbacks);  detect_partial_match(common, backtracks);
   read_char(common);    read_char(common);
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8  #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
   jump[0] = NULL;    jump[0] = NULL;
Line 3392  switch(type) Line 3723  switch(type)
     jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);      jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
     if (type == OP_CLASS)      if (type == OP_CLASS)
       {        {
      add_jump(compiler, fallbacks, jump[0]);      add_jump(compiler, backtracks, jump[0]);
       jump[0] = NULL;        jump[0] = NULL;
       }        }
     }      }
Line 3402  switch(type) Line 3733  switch(type)
   OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);    OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
   OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);    OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
   OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);    OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
  add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));  add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8  #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
   if (jump[0] != NULL)    if (jump[0] != NULL)
     JUMPHERE(jump[0]);      JUMPHERE(jump[0]);
Line 3411  switch(type) Line 3742  switch(type)
   
 #if defined SUPPORT_UTF || defined COMPILE_PCRE16  #if defined SUPPORT_UTF || defined COMPILE_PCRE16
   case OP_XCLASS:    case OP_XCLASS:
  compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks);  compile_xclass_trypath(common, cc + LINK_SIZE, backtracks);
   return cc + GET(cc, 0) - 1;    return cc + GET(cc, 0) - 1;
 #endif  #endif
   
   case OP_REVERSE:    case OP_REVERSE:
   length = GET(cc, 0);    length = GET(cc, 0);
  SLJIT_ASSERT(length > 0);  if (length == 0)
     return cc + LINK_SIZE;
   OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);    OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
   if (common->utf)    if (common->utf)
Line 3425  switch(type) Line 3757  switch(type)
     OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));      OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);      OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
     label = LABEL();      label = LABEL();
    add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0));    add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0));
     skip_char_back(common);      skip_char_back(common);
     OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);      OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
     JUMPTO(SLJIT_C_NOT_ZERO, label);      JUMPTO(SLJIT_C_NOT_ZERO, label);
     return cc + LINK_SIZE;  
     }      }
     else
 #endif  #endif
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));    {
  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
  add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0));    OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
     add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0));
     }
   check_start_used_ptr(common);
   return cc + LINK_SIZE;    return cc + LINK_SIZE;
   }    }
 SLJIT_ASSERT_STOP();  SLJIT_ASSERT_STOP();
 return cc;  return cc;
 }  }
   
static SLJIT_INLINE pcre_uchar *compile_charn_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **fallbacks)static SLJIT_INLINE pcre_uchar *compile_charn_trypath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **backtracks)
 {  {
 /* This function consumes at least one input character. */  /* This function consumes at least one input character. */
 /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */  /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
Line 3493  if (context.length > 0) Line 3828  if (context.length > 0)
   {    {
   /* We have a fixed-length byte sequence. */    /* We have a fixed-length byte sequence. */
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);
  add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
   
   context.sourcereg = -1;    context.sourcereg = -1;
 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED  #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
   context.ucharptr = 0;    context.ucharptr = 0;
 #endif  #endif
  do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, fallbacks); while (context.length > 0);  do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0);
   return cc;    return cc;
   }    }
   
 /* A non-fixed length character will be checked if length == 0. */  /* A non-fixed length character will be checked if length == 0. */
return compile_char1_hotpath(common, *cc, cc + 1, fallbacks);return compile_char1_trypath(common, *cc, cc + 1, backtracks);
 }  }
   
static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks)static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 int offset = GET2(cc, 1) << 1;  int offset = GET2(cc, 1) << 1;
Line 3515  int offset = GET2(cc, 1) << 1; Line 3850  int offset = GET2(cc, 1) << 1;
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
 if (!common->jscript_compat)  if (!common->jscript_compat)
   {    {
  if (fallbacks == NULL)  if (backtracks == NULL)
     {      {
       /* OVECTOR(1) contains the "string begin - 1" constant. */
     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);      COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);      COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
     return JUMP(SLJIT_C_NOT_ZERO);      return JUMP(SLJIT_C_NOT_ZERO);
     }      }
  add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));  add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
   }    }
 return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));  return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
 }  }
   
 /* Forward definitions. */  /* Forward definitions. */
static void compile_hotpath(compiler_common *, pcre_uchar *, pcre_uchar *, fallback_common *);static void compile_trypath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *);
static void compile_fallbackpath(compiler_common *, struct fallback_common *);static void compile_backtrackpath(compiler_common *, struct backtrack_common *);
   
#define PUSH_FALLBACK(size, ccstart, error) \#define PUSH_BACKTRACK(size, ccstart, error) \
   do \    do \
     { \      { \
    fallback = sljit_alloc_memory(compiler, (size)); \    backtrack = sljit_alloc_memory(compiler, (size)); \
     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \      if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
       return error; \        return error; \
    memset(fallback, 0, size); \    memset(backtrack, 0, size); \
    fallback->prev = parent->top; \    backtrack->prev = parent->top; \
    fallback->cc = (ccstart); \    backtrack->cc = (ccstart); \
    parent->top = fallback; \    parent->top = backtrack; \
     } \      } \
   while (0)    while (0)
   
#define PUSH_FALLBACK_NOVALUE(size, ccstart) \#define PUSH_BACKTRACK_NOVALUE(size, ccstart) \
   do \    do \
     { \      { \
    fallback = sljit_alloc_memory(compiler, (size)); \    backtrack = sljit_alloc_memory(compiler, (size)); \
     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \      if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
       return; \        return; \
    memset(fallback, 0, size); \    memset(backtrack, 0, size); \
    fallback->prev = parent->top; \    backtrack->prev = parent->top; \
    fallback->cc = (ccstart); \    backtrack->cc = (ccstart); \
    parent->top = fallback; \    parent->top = backtrack; \
     } \      } \
   while (0)    while (0)
   
#define FALLBACK_AS(type) ((type*)fallback)#define BACKTRACK_AS(type) ((type *)backtrack)
   
static pcre_uchar *compile_ref_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail)static pcre_uchar *compile_ref_trypath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 int offset = GET2(cc, 1) << 1;  int offset = GET2(cc, 1) << 1;
 struct sljit_jump *jump = NULL;  struct sljit_jump *jump = NULL;
   struct sljit_jump *partial;
   struct sljit_jump *nopartial;
   
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
   /* OVECTOR(1) contains the "string begin - 1" constant. */
 if (withchecks && !common->jscript_compat)  if (withchecks && !common->jscript_compat)
  add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));  add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
   
 #if defined SUPPORT_UTF && defined SUPPORT_UCP  #if defined SUPPORT_UTF && defined SUPPORT_UCP
 if (common->utf && *cc == OP_REFI)  if (common->utf && *cc == OP_REFI)
Line 3581  if (common->utf && *cc == OP_REFI) Line 3920  if (common->utf && *cc == OP_REFI)
   /* Needed to save important temporary registers. */    /* Needed to save important temporary registers. */
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
   OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, ptr), STR_PTR, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0);
   sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));    sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));
   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
  add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));  if (common->mode == JIT_COMPILE)
     add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1));
   else
     {
     add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
     nopartial = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
     check_partial(common, FALSE);
     add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
     JUMPHERE(nopartial);
     }
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
   }    }
 else  else
Line 3593  else Line 3941  else
   OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);    OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
   if (withchecks)    if (withchecks)
     jump = JUMP(SLJIT_C_ZERO);      jump = JUMP(SLJIT_C_ZERO);
   
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
     partial = CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0);
     if (common->mode == JIT_COMPILE)
       add_jump(compiler, backtracks, partial);
   
   add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));  
   add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));    add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
  add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
 
   if (common->mode != JIT_COMPILE)
     {
     nopartial = JUMP(SLJIT_JUMP);
     JUMPHERE(partial);
     /* TMP2 -= STR_END - STR_PTR */
     OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0);
     OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0);
     partial = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0);
     OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
     add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
     add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
     JUMPHERE(partial);
     check_partial(common, FALSE);
     add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
     JUMPHERE(nopartial);
     }
   }    }
   
 if (jump != NULL)  if (jump != NULL)
   {    {
   if (emptyfail)    if (emptyfail)
    add_jump(compiler, fallbacks, jump);    add_jump(compiler, backtracks, jump);
   else    else
     JUMPHERE(jump);      JUMPHERE(jump);
   }    }
 return cc + 1 + IMM2_SIZE;  return cc + 1 + IMM2_SIZE;
 }  }
   
static SLJIT_INLINE pcre_uchar *compile_ref_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)static SLJIT_INLINE pcre_uchar *compile_ref_iterator_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
fallback_common *fallback;backtrack_common *backtrack;
 pcre_uchar type;  pcre_uchar type;
 struct sljit_label *label;  struct sljit_label *label;
 struct sljit_jump *zerolength;  struct sljit_jump *zerolength;
Line 3622  pcre_uchar *ccbegin = cc; Line 3990  pcre_uchar *ccbegin = cc;
 int min = 0, max = 0;  int min = 0, max = 0;
 BOOL minimize;  BOOL minimize;
   
PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL);PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);
   
 type = cc[1 + IMM2_SIZE];  type = cc[1 + IMM2_SIZE];
 minimize = (type & 0x1) != 0;  minimize = (type & 0x1) != 0;
Line 3674  if (!minimize) Line 4042  if (!minimize)
     {      {
     allocate_stack(common, 1);      allocate_stack(common, 1);
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
    zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);    zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks);
     }      }
   
   if (min > 1 || max > 1)    if (min > 1 || max > 1)
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
   
   label = LABEL();    label = LABEL();
  compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, FALSE, FALSE);  compile_ref_trypath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE);
   
   if (min > 1 || max > 1)    if (min > 1 || max > 1)
     {      {
Line 3709  if (!minimize) Line 4077  if (!minimize)
     }      }
   
   JUMPHERE(zerolength);    JUMPHERE(zerolength);
  FALLBACK_AS(iterator_fallback)->hotpath = LABEL();  BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
   
   decrease_call_count(common);    decrease_call_count(common);
   return cc;    return cc;
Line 3727  if (min == 0) Line 4095  if (min == 0)
   jump = JUMP(SLJIT_JUMP);    jump = JUMP(SLJIT_JUMP);
   }    }
 else  else
  zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);  zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks);
   
FALLBACK_AS(iterator_fallback)->hotpath = LABEL();BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
 if (max > 0)  if (max > 0)
  add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));  add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
   
compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, TRUE, TRUE);compile_ref_trypath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE);
 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
   
 if (min > 1)  if (min > 1)
Line 3741  if (min > 1) Line 4109  if (min > 1)
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
   OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);    OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
  CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, FALLBACK_AS(iterator_fallback)->hotpath);  CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(iterator_backtrack)->trypath);
   }    }
 else if (max > 0)  else if (max > 0)
   OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);    OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
Line 3754  decrease_call_count(common); Line 4122  decrease_call_count(common);
 return cc;  return cc;
 }  }
   
static SLJIT_INLINE pcre_uchar *compile_recurse_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)static SLJIT_INLINE pcre_uchar *compile_recurse_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
fallback_common *fallback;backtrack_common *backtrack;
 recurse_entry *entry = common->entries;  recurse_entry *entry = common->entries;
 recurse_entry *prev = NULL;  recurse_entry *prev = NULL;
 int start = GET(cc, 1);  int start = GET(cc, 1);
   
PUSH_FALLBACK(sizeof(recurse_fallback), cc, NULL);PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL);
 while (entry != NULL)  while (entry != NULL)
   {    {
   if (entry->start == start)    if (entry->start == start)
Line 3787  if (entry == NULL) Line 4155  if (entry == NULL)
     common->entries = entry;      common->entries = entry;
   }    }
   
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));if (common->has_set_som && common->mark_ptr != 0)
allocate_stack(common, 1);  {
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
   allocate_stack(common, 2);
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
   }
 else if (common->has_set_som || common->mark_ptr != 0)
   {
   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr);
   allocate_stack(common, 1);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
   }
   
 if (entry->entry == NULL)  if (entry->entry == NULL)
   add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL));    add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL));
 else  else
   JUMPTO(SLJIT_FAST_CALL, entry->entry);    JUMPTO(SLJIT_FAST_CALL, entry->entry);
 /* Leave if the match is failed. */  /* Leave if the match is failed. */
add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0));add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0));
 return cc + 1 + LINK_SIZE;  return cc + 1 + LINK_SIZE;
 }  }
   
static pcre_uchar *compile_assert_hotpath(compiler_common *common, pcre_uchar *cc, assert_fallback *fallback, BOOL conditional)static pcre_uchar *compile_assert_trypath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 int framesize;  int framesize;
 int localptr;  int localptr;
fallback_common altfallback;backtrack_common altbacktrack;
 pcre_uchar *ccbegin;  pcre_uchar *ccbegin;
 pcre_uchar opcode;  pcre_uchar opcode;
 pcre_uchar bra = OP_BRA;  pcre_uchar bra = OP_BRA;
 jump_list *tmp = NULL;  jump_list *tmp = NULL;
jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks;jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;
 jump_list **found;  jump_list **found;
 /* Saving previous accept variables. */  /* Saving previous accept variables. */
   struct sljit_label *save_leavelabel = common->leavelabel;
 struct sljit_label *save_acceptlabel = common->acceptlabel;  struct sljit_label *save_acceptlabel = common->acceptlabel;
   jump_list *save_leave = common->leave;
   jump_list *save_accept = common->accept;
 struct sljit_jump *jump;  struct sljit_jump *jump;
 struct sljit_jump *brajump = NULL;  struct sljit_jump *brajump = NULL;
 jump_list *save_accept = common->accept;  
   
 if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
   {    {
Line 3827  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) Line 4208  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
 localptr = PRIV_DATA(cc);  localptr = PRIV_DATA(cc);
 SLJIT_ASSERT(localptr != 0);  SLJIT_ASSERT(localptr != 0);
 framesize = get_framesize(common, cc, FALSE);  framesize = get_framesize(common, cc, FALSE);
fallback->framesize = framesize;backtrack->framesize = framesize;
fallback->localptr = localptr;backtrack->localptr = localptr;
 opcode = *cc;  opcode = *cc;
 SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);  SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);
 found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;  found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;
Line 3837  cc += GET(cc, 1); Line 4218  cc += GET(cc, 1);
   
 if (bra == OP_BRAMINZERO)  if (bra == OP_BRAMINZERO)
   {    {
  /* This is a braminzero fallback path. */  /* This is a braminzero backtrack path. */
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   free_stack(common, 1);    free_stack(common, 1);
   brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);    brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
Line 3860  else Line 4241  else
   init_frame(common, ccbegin, framesize + 1, 2, FALSE);    init_frame(common, ccbegin, framesize + 1, 2, FALSE);
   }    }
   
memset(&altfallback, 0, sizeof(fallback_common));memset(&altbacktrack, 0, sizeof(backtrack_common));
 common->leavelabel = NULL;
 common->leave = NULL;
 while (1)  while (1)
   {    {
   common->acceptlabel = NULL;    common->acceptlabel = NULL;
   common->accept = NULL;    common->accept = NULL;
  altfallback.top = NULL;  altbacktrack.top = NULL;
  altfallback.topfallbacks = NULL;  altbacktrack.topbacktracks = NULL;
   
   if (*ccbegin == OP_ALT)    if (*ccbegin == OP_ALT)
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   
  altfallback.cc = ccbegin;  altbacktrack.cc = ccbegin;
  compile_hotpath(common, ccbegin + 1 + LINK_SIZE, cc, &altfallback);  compile_trypath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);
   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
     {      {
       common->leavelabel = save_leavelabel;
     common->acceptlabel = save_acceptlabel;      common->acceptlabel = save_acceptlabel;
       common->leave = save_leave;
     common->accept = save_accept;      common->accept = save_accept;
     return NULL;      return NULL;
     }      }
Line 3925  while (1) Line 4310  while (1)
     }      }
   add_jump(compiler, found, JUMP(SLJIT_JUMP));    add_jump(compiler, found, JUMP(SLJIT_JUMP));
   
  compile_fallbackpath(common, altfallback.top);  compile_backtrackpath(common, altbacktrack.top);
   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
     {      {
       common->leavelabel = save_leavelabel;
     common->acceptlabel = save_acceptlabel;      common->acceptlabel = save_acceptlabel;
       common->leave = save_leave;
     common->accept = save_accept;      common->accept = save_accept;
     return NULL;      return NULL;
     }      }
  set_jumps(altfallback.topfallbacks, LABEL());  set_jumps(altbacktrack.topbacktracks, LABEL());
   
   if (*cc != OP_ALT)    if (*cc != OP_ALT)
     break;      break;
Line 3941  while (1) Line 4328  while (1)
   cc += GET(cc, 1);    cc += GET(cc, 1);
   }    }
 /* None of them matched. */  /* None of them matched. */
   if (common->leave != NULL)
     set_jumps(common->leave, LABEL());
   
 if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)  if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
   {    {
Line 4007  if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) Line 4396  if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
   
   if (bra == OP_BRAZERO)    if (bra == OP_BRAZERO)
     {      {
    fallback->hotpath = LABEL();    backtrack->trypath = LABEL();
    sljit_set_label(jump, fallback->hotpath);    sljit_set_label(jump, backtrack->trypath);
     }      }
   else if (bra == OP_BRAMINZERO)    else if (bra == OP_BRAMINZERO)
     {      {
    JUMPTO(SLJIT_JUMP, fallback->hotpath);    JUMPTO(SLJIT_JUMP, backtrack->trypath);
     JUMPHERE(brajump);      JUMPHERE(brajump);
     if (framesize >= 0)      if (framesize >= 0)
       {        {
Line 4020  if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) Line 4409  if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));        add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
       }        }
    set_jumps(fallback->common.topfallbacks, LABEL());    set_jumps(backtrack->common.topbacktracks, LABEL());
     }      }
   }    }
 else  else
Line 4050  else Line 4439  else
     }      }
   
   if (bra == OP_BRAZERO)    if (bra == OP_BRAZERO)
    fallback->hotpath = LABEL();    backtrack->trypath = LABEL();
   else if (bra == OP_BRAMINZERO)    else if (bra == OP_BRAMINZERO)
     {      {
    JUMPTO(SLJIT_JUMP, fallback->hotpath);    JUMPTO(SLJIT_JUMP, backtrack->trypath);
     JUMPHERE(brajump);      JUMPHERE(brajump);
     }      }
   
   if (bra != OP_BRA)    if (bra != OP_BRA)
     {      {
    SLJIT_ASSERT(found == &fallback->common.topfallbacks);    SLJIT_ASSERT(found == &backtrack->common.topbacktracks);
    set_jumps(fallback->common.topfallbacks, LABEL());    set_jumps(backtrack->common.topbacktracks, LABEL());
    fallback->common.topfallbacks = NULL;    backtrack->common.topbacktracks = NULL;
     }      }
   }    }
   
   common->leavelabel = save_leavelabel;
 common->acceptlabel = save_acceptlabel;  common->acceptlabel = save_acceptlabel;
   common->leave = save_leave;
 common->accept = save_accept;  common->accept = save_accept;
 return cc + 1 + LINK_SIZE;  return cc + 1 + LINK_SIZE;
 }  }
Line 4080  sljit_w name_entry_size = locals[LOCALS1 / sizeof(slji Line 4471  sljit_w name_entry_size = locals[LOCALS1 / sizeof(slji
 sljit_w no_capture;  sljit_w no_capture;
 int i;  int i;
   
locals += OVECTOR_START / sizeof(sljit_w);locals += refno & 0xff;
 refno >>= 8;
 no_capture = locals[1];  no_capture = locals[1];
   
 for (i = 0; i < name_count; i++)  for (i = 0; i < name_count; i++)
Line 4233  return condition; Line 4625  return condition;
                                           Or nothing, if trace is unnecessary                                            Or nothing, if trace is unnecessary
 */  */
   
static pcre_uchar *compile_bracket_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)static pcre_uchar *compile_bracket_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
fallback_common *fallback;backtrack_common *backtrack;
 pcre_uchar opcode;  pcre_uchar opcode;
 int localptr = 0;  int localptr = 0;
 int offset = 0;  int offset = 0;
 int stacksize;  int stacksize;
 pcre_uchar *ccbegin;  pcre_uchar *ccbegin;
pcre_uchar *hotpath;pcre_uchar *trypath;
 pcre_uchar bra = OP_BRA;  pcre_uchar bra = OP_BRA;
 pcre_uchar ket;  pcre_uchar ket;
assert_fallback *assert;assert_backtrack *assert;
 BOOL has_alternatives;  BOOL has_alternatives;
 struct sljit_jump *jump;  struct sljit_jump *jump;
 struct sljit_jump *skip;  struct sljit_jump *skip;
 struct sljit_label *rmaxlabel = NULL;  struct sljit_label *rmaxlabel = NULL;
 struct sljit_jump *braminzerojump = NULL;  struct sljit_jump *braminzerojump = NULL;
   
PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL);PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);
   
 if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
   {    {
Line 4263  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) Line 4655  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
   
 opcode = *cc;  opcode = *cc;
 ccbegin = cc;  ccbegin = cc;
hotpath = ccbegin + 1 + LINK_SIZE;trypath = ccbegin + 1 + LINK_SIZE;
   
 if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)  if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
   {    {
  /* Drop this bracket_fallback. */  /* Drop this bracket_backtrack. */
  parent->top = fallback->prev;  parent->top = backtrack->prev;
   return bracketend(cc);    return bracketend(cc);
   }    }
   
Line 4280  cc += GET(cc, 1); Line 4672  cc += GET(cc, 1);
 has_alternatives = *cc == OP_ALT;  has_alternatives = *cc == OP_ALT;
 if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
   {    {
  has_alternatives = (*hotpath == OP_RREF) ? FALSE : TRUE;  has_alternatives = (*trypath == OP_RREF) ? FALSE : TRUE;
  if (*hotpath == OP_NRREF)  if (*trypath == OP_NRREF)
     {      {
    stacksize = GET2(hotpath, 1);    stacksize = GET2(trypath, 1);
     if (common->currententry == NULL || stacksize == RREF_ANY)      if (common->currententry == NULL || stacksize == RREF_ANY)
       has_alternatives = FALSE;        has_alternatives = FALSE;
     else if (common->currententry->start == 0)      else if (common->currententry->start == 0)
Line 4304  if (opcode == OP_CBRA || opcode == OP_SCBRA) Line 4696  if (opcode == OP_CBRA || opcode == OP_SCBRA)
   offset = GET2(ccbegin, 1 + LINK_SIZE);    offset = GET2(ccbegin, 1 + LINK_SIZE);
   localptr = OVECTOR_PRIV(offset);    localptr = OVECTOR_PRIV(offset);
   offset <<= 1;    offset <<= 1;
  FALLBACK_AS(bracket_fallback)->localptr = localptr;  BACKTRACK_AS(bracket_backtrack)->localptr = localptr;
  hotpath += IMM2_SIZE;  trypath += IMM2_SIZE;
   }    }
 else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)  else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
   {    {
   /* Other brackets simply allocate the next entry. */    /* Other brackets simply allocate the next entry. */
   localptr = PRIV_DATA(ccbegin);    localptr = PRIV_DATA(ccbegin);
   SLJIT_ASSERT(localptr != 0);    SLJIT_ASSERT(localptr != 0);
  FALLBACK_AS(bracket_fallback)->localptr = localptr;  BACKTRACK_AS(bracket_backtrack)->localptr = localptr;
   if (opcode == OP_ONCE)    if (opcode == OP_ONCE)
    FALLBACK_AS(bracket_fallback)->u.framesize = get_framesize(common, ccbegin, FALSE);    BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, FALSE);
   }    }
   
 /* Instructions before the first alternative. */  /* Instructions before the first alternative. */
Line 4339  if (bra == OP_BRAZERO) Line 4731  if (bra == OP_BRAZERO)
   
 if (bra == OP_BRAMINZERO)  if (bra == OP_BRAMINZERO)
   {    {
  /* This is a fallback path! (Since the hot-path of OP_BRAMINZERO matches to the empty string) */  /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   if (ket != OP_KETRMIN)    if (ket != OP_KETRMIN)
     {      {
Line 4356  if (bra == OP_BRAMINZERO) Line 4748  if (bra == OP_BRAMINZERO)
       skip = JUMP(SLJIT_JUMP);        skip = JUMP(SLJIT_JUMP);
       JUMPHERE(jump);        JUMPHERE(jump);
       /* Checking zero-length iteration. */        /* Checking zero-length iteration. */
      if (opcode != OP_ONCE || FALLBACK_AS(bracket_fallback)->u.framesize < 0)      if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
         {          {
         /* When we come from outside, localptr contains the previous STR_PTR. */          /* When we come from outside, localptr contains the previous STR_PTR. */
         braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);          braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
Line 4365  if (bra == OP_BRAMINZERO) Line 4757  if (bra == OP_BRAMINZERO)
         {          {
         /* Except when the whole stack frame must be saved. */          /* Except when the whole stack frame must be saved. */
         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
        braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w));        braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_w));
         }          }
       JUMPHERE(skip);        JUMPHERE(skip);
       }        }
Line 4379  if (bra == OP_BRAMINZERO) Line 4771  if (bra == OP_BRAMINZERO)
   }    }
   
 if (ket == OP_KETRMIN)  if (ket == OP_KETRMIN)
  FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();  BACKTRACK_AS(bracket_backtrack)->recursivetrypath = LABEL();
   
 if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
   {    {
   rmaxlabel = LABEL();    rmaxlabel = LABEL();
   if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)    if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)
    FALLBACK_AS(bracket_fallback)->althotpath = rmaxlabel;    BACKTRACK_AS(bracket_backtrack)->alttrypath = rmaxlabel;
   }    }
   
 /* Handling capturing brackets and alternatives. */  /* Handling capturing brackets and alternatives. */
 if (opcode == OP_ONCE)  if (opcode == OP_ONCE)
   {    {
  if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)  if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
     {      {
     /* Neither capturing brackets nor recursions are not found in the block. */      /* Neither capturing brackets nor recursions are not found in the block. */
     if (ket == OP_KETRMIN)      if (ket == OP_KETRMIN)
Line 4415  if (opcode == OP_ONCE) Line 4807  if (opcode == OP_ONCE)
     {      {
     if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives)      if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives)
       {        {
      allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 2);      allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 2);
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize + 1));      OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize + 1));
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
      init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize + 1, 2, FALSE);      init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1, 2, FALSE);
       }        }
     else      else
       {        {
      allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 1);      allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1);
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize));      OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize));
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
      init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize, 1, FALSE);      init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize, 1, FALSE);
       }        }
     }      }
   }    }
Line 4464  else if (has_alternatives) Line 4856  else if (has_alternatives)
 /* Generating code for the first alternative. */  /* Generating code for the first alternative. */
 if (opcode == OP_COND || opcode == OP_SCOND)  if (opcode == OP_COND || opcode == OP_SCOND)
   {    {
  if (*hotpath == OP_CREF)  if (*trypath == OP_CREF)
     {      {
     SLJIT_ASSERT(has_alternatives);      SLJIT_ASSERT(has_alternatives);
    add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed),    add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed),
      CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(hotpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));      CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(trypath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
    hotpath += 1 + IMM2_SIZE;    trypath += 1 + IMM2_SIZE;
     }      }
  else if (*hotpath == OP_NCREF)  else if (*trypath == OP_NCREF)
     {      {
     SLJIT_ASSERT(has_alternatives);      SLJIT_ASSERT(has_alternatives);
    stacksize = GET2(hotpath, 1);    stacksize = GET2(trypath, 1);
     jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));      jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
   
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);
    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize);    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, (stacksize << 8) | (common->ovector_start / sizeof(sljit_w)));
    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0);    GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0);
     OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);      OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);
     sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector));      sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector));
     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
    add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));    add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));
   
     JUMPHERE(jump);      JUMPHERE(jump);
    hotpath += 1 + IMM2_SIZE;    trypath += 1 + IMM2_SIZE;
     }      }
  else if (*hotpath == OP_RREF || *hotpath == OP_NRREF)  else if (*trypath == OP_RREF || *trypath == OP_NRREF)
     {      {
     /* Never has other case. */      /* Never has other case. */
    FALLBACK_AS(bracket_fallback)->u.condfailed = NULL;    BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;
   
    stacksize = GET2(hotpath, 1);    stacksize = GET2(trypath, 1);
     if (common->currententry == NULL)      if (common->currententry == NULL)
       stacksize = 0;        stacksize = 0;
     else if (stacksize == RREF_ANY)      else if (stacksize == RREF_ANY)
Line 4505  if (opcode == OP_COND || opcode == OP_SCOND) Line 4897  if (opcode == OP_COND || opcode == OP_SCOND)
     else      else
       stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE);        stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
   
    if (*hotpath == OP_RREF || stacksize || common->currententry == NULL)    if (*trypath == OP_RREF || stacksize || common->currententry == NULL)
       {        {
       SLJIT_ASSERT(!has_alternatives);        SLJIT_ASSERT(!has_alternatives);
       if (stacksize != 0)        if (stacksize != 0)
        hotpath += 1 + IMM2_SIZE;        trypath += 1 + IMM2_SIZE;
       else        else
         {          {
         if (*cc == OP_ALT)          if (*cc == OP_ALT)
           {            {
          hotpath = cc + 1 + LINK_SIZE;          trypath = cc + 1 + LINK_SIZE;
           cc += GET(cc, 1);            cc += GET(cc, 1);
           }            }
         else          else
          hotpath = cc;          trypath = cc;
         }          }
       }        }
     else      else
       {        {
       SLJIT_ASSERT(has_alternatives);        SLJIT_ASSERT(has_alternatives);
   
      stacksize = GET2(hotpath, 1);      stacksize = GET2(trypath, 1);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE));        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE));
       OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize);        OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize);
      OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0);      GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0);
       OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);        OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);
       sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups));        sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups));
       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);        OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
      add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));      add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));
      hotpath += 1 + IMM2_SIZE;      trypath += 1 + IMM2_SIZE;
       }        }
     }      }
   else    else
     {      {
    SLJIT_ASSERT(has_alternatives && *hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT);    SLJIT_ASSERT(has_alternatives && *trypath >= OP_ASSERT && *trypath <= OP_ASSERTBACK_NOT);
    /* Similar code as PUSH_FALLBACK macro. */    /* Similar code as PUSH_BACKTRACK macro. */
    assert = sljit_alloc_memory(compiler, sizeof(assert_fallback));    assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack));
     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))      if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
       return NULL;        return NULL;
    memset(assert, 0, sizeof(assert_fallback));    memset(assert, 0, sizeof(assert_backtrack));
    assert->common.cc = hotpath;    assert->common.cc = trypath;
    FALLBACK_AS(bracket_fallback)->u.assert = assert;    BACKTRACK_AS(bracket_backtrack)->u.assert = assert;
    hotpath = compile_assert_hotpath(common, hotpath, assert, TRUE);    trypath = compile_assert_trypath(common, trypath, assert, TRUE);
     }      }
   }    }
   
compile_hotpath(common, hotpath, cc, fallback);compile_trypath(common, trypath, cc, backtrack);
 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
   return NULL;    return NULL;
   
 if (opcode == OP_ONCE)  if (opcode == OP_ONCE)
   {    {
  if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)  if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
     {      {
     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
     /* TMP2 which is set here used by OP_KETRMAX below. */      /* TMP2 which is set here used by OP_KETRMAX below. */
Line 4574  if (opcode == OP_ONCE) Line 4966  if (opcode == OP_ONCE)
   else    else
     {      {
     stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1;      stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1;
    OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (FALLBACK_AS(bracket_fallback)->u.framesize + stacksize) * sizeof(sljit_w));    OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize) * sizeof(sljit_w));
     if (ket == OP_KETRMAX)      if (ket == OP_KETRMAX)
       {        {
       /* TMP2 which is set here used by OP_KETRMAX below. */        /* TMP2 which is set here used by OP_KETRMAX below. */
Line 4609  if (has_alternatives) Line 5001  if (has_alternatives)
   if (opcode != OP_ONCE)    if (opcode != OP_ONCE)
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
   if (ket != OP_KETRMAX)    if (ket != OP_KETRMAX)
    FALLBACK_AS(bracket_fallback)->althotpath = LABEL();    BACKTRACK_AS(bracket_backtrack)->alttrypath = LABEL();
   }    }
   
/* Must be after the hotpath label. *//* Must be after the trypath label. */
 if (offset != 0)  if (offset != 0)
   {    {
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
Line 4625  if (ket == OP_KETRMAX) Line 5017  if (ket == OP_KETRMAX)
   if (opcode == OP_ONCE || opcode >= OP_SBRA)    if (opcode == OP_ONCE || opcode >= OP_SBRA)
     {      {
     if (has_alternatives)      if (has_alternatives)
      FALLBACK_AS(bracket_fallback)->althotpath = LABEL();      BACKTRACK_AS(bracket_backtrack)->alttrypath = LABEL();
     /* Checking zero-length iteration. */      /* Checking zero-length iteration. */
     if (opcode != OP_ONCE)      if (opcode != OP_ONCE)
         {
       CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel);        CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel);
         /* Drop STR_PTR for greedy plus quantifier. */
         if (bra != OP_BRAZERO)
           free_stack(common, 1);
         }
     else      else
       /* TMP2 must contain the starting STR_PTR. */        /* TMP2 must contain the starting STR_PTR. */
       CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);        CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);
     }      }
   else    else
     JUMPTO(SLJIT_JUMP, rmaxlabel);      JUMPTO(SLJIT_JUMP, rmaxlabel);
  FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();  BACKTRACK_AS(bracket_backtrack)->recursivetrypath = LABEL();
   }    }
   
 if (bra == OP_BRAZERO)  if (bra == OP_BRAZERO)
  FALLBACK_AS(bracket_fallback)->zerohotpath = LABEL();  BACKTRACK_AS(bracket_backtrack)->zerotrypath = LABEL();
   
 if (bra == OP_BRAMINZERO)  if (bra == OP_BRAMINZERO)
   {    {
  /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */  /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */
  JUMPTO(SLJIT_JUMP, ((braminzero_fallback*)parent)->hotpath);  JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->trypath);
   if (braminzerojump != NULL)    if (braminzerojump != NULL)
     {      {
     JUMPHERE(braminzerojump);      JUMPHERE(braminzerojump);
     /* We need to release the end pointer to perform the      /* We need to release the end pointer to perform the
    fallback for the zero-length iteration. When    backtrack for the zero-length iteration. When
     framesize is < 0, OP_ONCE will do the release itself. */      framesize is < 0, OP_ONCE will do the release itself. */
    if (opcode == OP_ONCE && FALLBACK_AS(bracket_fallback)->u.framesize >= 0)    if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0)
       {        {
       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);        OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));        add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
Line 4659  if (bra == OP_BRAMINZERO) Line 5056  if (bra == OP_BRAMINZERO)
     else if (ket == OP_KETRMIN && opcode != OP_ONCE)      else if (ket == OP_KETRMIN && opcode != OP_ONCE)
       free_stack(common, 1);        free_stack(common, 1);
     }      }
  /* Continue to the normal fallback. */  /* Continue to the normal backtrack. */
   }    }
   
 if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)  if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
Line 4672  cc += 1 + LINK_SIZE; Line 5069  cc += 1 + LINK_SIZE;
 return cc;  return cc;
 }  }
   
static pcre_uchar *compile_bracketpos_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)static pcre_uchar *compile_bracketpos_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
fallback_common *fallback;backtrack_common *backtrack;
 pcre_uchar opcode;  pcre_uchar opcode;
 int localptr;  int localptr;
 int cbraprivptr = 0;  int cbraprivptr = 0;
Line 4688  int stack; Line 5085  int stack;
 struct sljit_label *loop = NULL;  struct sljit_label *loop = NULL;
 struct jump_list *emptymatch = NULL;  struct jump_list *emptymatch = NULL;
   
PUSH_FALLBACK(sizeof(bracketpos_fallback), cc, NULL);PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL);
 if (*cc == OP_BRAPOSZERO)  if (*cc == OP_BRAPOSZERO)
   {    {
   zero = TRUE;    zero = TRUE;
Line 4698  if (*cc == OP_BRAPOSZERO) Line 5095  if (*cc == OP_BRAPOSZERO)
 opcode = *cc;  opcode = *cc;
 localptr = PRIV_DATA(cc);  localptr = PRIV_DATA(cc);
 SLJIT_ASSERT(localptr != 0);  SLJIT_ASSERT(localptr != 0);
FALLBACK_AS(bracketpos_fallback)->localptr = localptr;BACKTRACK_AS(bracketpos_backtrack)->localptr = localptr;
 switch(opcode)  switch(opcode)
   {    {
   case OP_BRAPOS:    case OP_BRAPOS:
Line 4720  switch(opcode) Line 5117  switch(opcode)
   }    }
   
 framesize = get_framesize(common, cc, FALSE);  framesize = get_framesize(common, cc, FALSE);
FALLBACK_AS(bracketpos_fallback)->framesize = framesize;BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize;
 if (framesize < 0)  if (framesize < 0)
   {    {
   stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1;    stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1;
   if (!zero)    if (!zero)
     stacksize++;      stacksize++;
  FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;  BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;
   allocate_stack(common, stacksize);    allocate_stack(common, stacksize);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
   
Line 4750  else Line 5147  else
     stacksize++;      stacksize++;
   if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)    if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
     stacksize++;      stacksize++;
  FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;  BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;
   allocate_stack(common, stacksize);    allocate_stack(common, stacksize);
   
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
Line 4777  if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) Line 5174  if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
 loop = LABEL();  loop = LABEL();
 while (*cc != OP_KETRPOS)  while (*cc != OP_KETRPOS)
   {    {
  fallback->top = NULL;  backtrack->top = NULL;
  fallback->topfallbacks = NULL;  backtrack->topbacktracks = NULL;
   cc += GET(cc, 1);    cc += GET(cc, 1);
   
  compile_hotpath(common, ccbegin, cc, fallback);  compile_trypath(common, ccbegin, cc, backtrack);
   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
     return NULL;      return NULL;
   
Line 4842  while (*cc != OP_KETRPOS) Line 5239  while (*cc != OP_KETRPOS)
   JUMPTO(SLJIT_JUMP, loop);    JUMPTO(SLJIT_JUMP, loop);
   flush_stubs(common);    flush_stubs(common);
   
  compile_fallbackpath(common, fallback->top);  compile_backtrackpath(common, backtrack->top);
   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
     return NULL;      return NULL;
  set_jumps(fallback->topfallbacks, LABEL());  set_jumps(backtrack->topbacktracks, LABEL());
   
   if (framesize < 0)    if (framesize < 0)
     {      {
Line 4875  while (*cc != OP_KETRPOS) Line 5272  while (*cc != OP_KETRPOS)
   ccbegin = cc + 1 + LINK_SIZE;    ccbegin = cc + 1 + LINK_SIZE;
   }    }
   
fallback->topfallbacks = NULL;backtrack->topbacktracks = NULL;
 if (!zero)  if (!zero)
   {    {
   if (framesize < 0)    if (framesize < 0)
    add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));
   else /* TMP2 is set to [localptr] above. */    else /* TMP2 is set to [localptr] above. */
    add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0));    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0));
   }    }
   
 /* None of them matched. */  /* None of them matched. */
Line 4982  if (end != NULL) Line 5379  if (end != NULL)
 return cc;  return cc;
 }  }
   
static pcre_uchar *compile_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)static pcre_uchar *compile_iterator_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
fallback_common *fallback;backtrack_common *backtrack;
 pcre_uchar opcode;  pcre_uchar opcode;
 pcre_uchar type;  pcre_uchar type;
 int arg1 = -1, arg2 = -1;  int arg1 = -1, arg2 = -1;
Line 4994  jump_list *nomatch = NULL; Line 5391  jump_list *nomatch = NULL;
 struct sljit_jump *jump = NULL;  struct sljit_jump *jump = NULL;
 struct sljit_label *label;  struct sljit_label *label;
   
PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL);PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);
   
 cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end);  cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end);
   
Line 5021  switch(opcode) Line 5418  switch(opcode)
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
   
     label = LABEL();      label = LABEL();
    compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);    compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
     if (opcode == OP_UPTO || opcode == OP_CRRANGE)      if (opcode == OP_UPTO || opcode == OP_CRRANGE)
       {        {
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
Line 5041  switch(opcode) Line 5438  switch(opcode)
     }      }
   else    else
     {      {
       if (opcode == OP_PLUS)
         compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
     allocate_stack(common, 2);      allocate_stack(common, 2);
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
     label = LABEL();      label = LABEL();
    compile_char1_hotpath(common, type, cc, &nomatch);    compile_char1_trypath(common, type, cc, &nomatch);
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
     if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0))      if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0))
       {        {
Line 5060  switch(opcode) Line 5459  switch(opcode)
       CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);        CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
       }        }
     set_jumps(nomatch, LABEL());      set_jumps(nomatch, LABEL());
    if (opcode == OP_PLUS || opcode == OP_CRRANGE)    if (opcode == OP_CRRANGE)
      add_jump(compiler, &fallback->topfallbacks,      add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, arg2 + 1));
        CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, opcode == OP_PLUS ? 2 : arg2 + 1)); 
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
     }      }
  FALLBACK_AS(iterator_fallback)->hotpath = LABEL();  BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
   break;    break;
   
   case OP_MINSTAR:    case OP_MINSTAR:
   case OP_MINPLUS:    case OP_MINPLUS:
     if (opcode == OP_MINPLUS)
       compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
   allocate_stack(common, 1);    allocate_stack(common, 1);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  if (opcode == OP_MINPLUS)  BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
    add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); 
  FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); 
   break;    break;
   
   case OP_MINUPTO:    case OP_MINUPTO:
Line 5083  switch(opcode) Line 5481  switch(opcode)
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
   if (opcode == OP_CRMINRANGE)    if (opcode == OP_CRMINRANGE)
    add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));    add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
  FALLBACK_AS(iterator_fallback)->hotpath = LABEL();  BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
   break;    break;
   
   case OP_QUERY:    case OP_QUERY:
Line 5092  switch(opcode) Line 5490  switch(opcode)
   allocate_stack(common, 1);    allocate_stack(common, 1);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
   if (opcode == OP_QUERY)    if (opcode == OP_QUERY)
    compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);    compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
  FALLBACK_AS(iterator_fallback)->hotpath = LABEL();  BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
   break;    break;
   
   case OP_EXACT:    case OP_EXACT:
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
   label = LABEL();    label = LABEL();
  compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);  compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
   OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);    OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
Line 5113  switch(opcode) Line 5511  switch(opcode)
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
   label = LABEL();    label = LABEL();
  compile_char1_hotpath(common, type, cc, &nomatch);  compile_char1_trypath(common, type, cc, &nomatch);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
   if (opcode != OP_POSUPTO)    if (opcode != OP_POSUPTO)
     {      {
Line 5130  switch(opcode) Line 5528  switch(opcode)
     }      }
   set_jumps(nomatch, LABEL());    set_jumps(nomatch, LABEL());
   if (opcode == OP_POSPLUS)    if (opcode == OP_POSPLUS)
    add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2));    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2));
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
   break;    break;
   
   case OP_POSQUERY:    case OP_POSQUERY:
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
  compile_char1_hotpath(common, type, cc, &nomatch);  compile_char1_trypath(common, type, cc, &nomatch);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
   set_jumps(nomatch, LABEL());    set_jumps(nomatch, LABEL());
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
Line 5151  decrease_call_count(common); Line 5549  decrease_call_count(common);
 return end;  return end;
 }  }
   
static SLJIT_INLINE pcre_uchar *compile_fail_accept_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)static SLJIT_INLINE pcre_uchar *compile_fail_accept_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
fallback_common *fallback;backtrack_common *backtrack;
   
PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL);PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);
   
 if (*cc == OP_FAIL)  if (*cc == OP_FAIL)
   {    {
  add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));  add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
   return cc + 1;    return cc + 1;
   }    }
   
Line 5180  else Line 5578  else
   CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel);    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel);
 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
 if (common->acceptlabel == NULL)  if (common->acceptlabel == NULL)
   add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0));    add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0));
Line 5191  if (common->acceptlabel == NULL) Line 5589  if (common->acceptlabel == NULL)
   add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0));    add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0));
 else  else
   CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel);    CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel);
add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
 return cc + 1;  return cc + 1;
 }  }
   
static SLJIT_INLINE pcre_uchar *compile_close_hotpath(compiler_common *common, pcre_uchar *cc)static SLJIT_INLINE pcre_uchar *compile_close_trypath(compiler_common *common, pcre_uchar *cc)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 int offset = GET2(cc, 1);  int offset = GET2(cc, 1);
Line 5211  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(o Line 5609  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(o
 return cc + 1 + IMM2_SIZE;  return cc + 1 + IMM2_SIZE;
 }  }
   
static void compile_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, fallback_common *parent)static void compile_trypath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
fallback_common *fallback;backtrack_common *backtrack;
   
 while (cc < ccend)  while (cc < ccend)
   {    {
Line 5250  while (cc < ccend) Line 5648  while (cc < ccend)
     case OP_NOT:      case OP_NOT:
     case OP_NOTI:      case OP_NOTI:
     case OP_REVERSE:      case OP_REVERSE:
    cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);    cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
     break;      break;
   
     case OP_SET_SOM:      case OP_SET_SOM:
    PUSH_FALLBACK_NOVALUE(sizeof(fallback_common), cc);    PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
     allocate_stack(common, 1);      allocate_stack(common, 1);
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));  
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
     cc++;      cc++;
     break;      break;
   
     case OP_CHAR:      case OP_CHAR:
     case OP_CHARI:      case OP_CHARI:
    cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);    if (common->mode == JIT_COMPILE)
       cc = compile_charn_trypath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
     else
       cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
     break;      break;
   
     case OP_STAR:      case OP_STAR:
Line 5332  while (cc < ccend) Line 5733  while (cc < ccend)
     case OP_TYPEPOSPLUS:      case OP_TYPEPOSPLUS:
     case OP_TYPEPOSQUERY:      case OP_TYPEPOSQUERY:
     case OP_TYPEPOSUPTO:      case OP_TYPEPOSUPTO:
    cc = compile_iterator_hotpath(common, cc, parent);    cc = compile_iterator_trypath(common, cc, parent);
     break;      break;
   
     case OP_CLASS:      case OP_CLASS:
     case OP_NCLASS:      case OP_NCLASS:
     if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRMINRANGE)      if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRMINRANGE)
      cc = compile_iterator_hotpath(common, cc, parent);      cc = compile_iterator_trypath(common, cc, parent);
     else      else
      cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);      cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
     break;      break;
   
 #if defined SUPPORT_UTF || defined COMPILE_PCRE16  #if defined SUPPORT_UTF || defined COMPILE_PCRE16
     case OP_XCLASS:      case OP_XCLASS:
     if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE)      if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE)
      cc = compile_iterator_hotpath(common, cc, parent);      cc = compile_iterator_trypath(common, cc, parent);
     else      else
      cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);      cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
     break;      break;
 #endif  #endif
   
     case OP_REF:      case OP_REF:
     case OP_REFI:      case OP_REFI:
     if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE)      if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE)
      cc = compile_ref_iterator_hotpath(common, cc, parent);      cc = compile_ref_iterator_trypath(common, cc, parent);
     else      else
      cc = compile_ref_hotpath(common, cc, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks, TRUE, FALSE);      cc = compile_ref_trypath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);
     break;      break;
   
     case OP_RECURSE:      case OP_RECURSE:
    cc = compile_recurse_hotpath(common, cc, parent);    cc = compile_recurse_trypath(common, cc, parent);
     break;      break;
   
     case OP_ASSERT:      case OP_ASSERT:
     case OP_ASSERT_NOT:      case OP_ASSERT_NOT:
     case OP_ASSERTBACK:      case OP_ASSERTBACK:
     case OP_ASSERTBACK_NOT:      case OP_ASSERTBACK_NOT:
    PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc);    PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);
    cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE);    cc = compile_assert_trypath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);
     break;      break;
   
     case OP_BRAMINZERO:      case OP_BRAMINZERO:
    PUSH_FALLBACK_NOVALUE(sizeof(braminzero_fallback), cc);    PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc);
     cc = bracketend(cc + 1);      cc = bracketend(cc + 1);
     if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)      if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)
       {        {
Line 5386  while (cc < ccend) Line 5787  while (cc < ccend)
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);
       }        }
    FALLBACK_AS(braminzero_fallback)->hotpath = LABEL();    BACKTRACK_AS(braminzero_backtrack)->trypath = LABEL();
     if (cc[1] > OP_ASSERTBACK_NOT)      if (cc[1] > OP_ASSERTBACK_NOT)
       decrease_call_count(common);        decrease_call_count(common);
     break;      break;
Line 5399  while (cc < ccend) Line 5800  while (cc < ccend)
     case OP_SBRA:      case OP_SBRA:
     case OP_SCBRA:      case OP_SCBRA:
     case OP_SCOND:      case OP_SCOND:
    cc = compile_bracket_hotpath(common, cc, parent);    cc = compile_bracket_trypath(common, cc, parent);
     break;      break;
   
     case OP_BRAZERO:      case OP_BRAZERO:
     if (cc[1] > OP_ASSERTBACK_NOT)      if (cc[1] > OP_ASSERTBACK_NOT)
      cc = compile_bracket_hotpath(common, cc, parent);      cc = compile_bracket_trypath(common, cc, parent);
     else      else
       {        {
      PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc);      PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);
      cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE);      cc = compile_assert_trypath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);
       }        }
     break;      break;
   
Line 5417  while (cc < ccend) Line 5818  while (cc < ccend)
     case OP_SBRAPOS:      case OP_SBRAPOS:
     case OP_SCBRAPOS:      case OP_SCBRAPOS:
     case OP_BRAPOSZERO:      case OP_BRAPOSZERO:
    cc = compile_bracketpos_hotpath(common, cc, parent);    cc = compile_bracketpos_trypath(common, cc, parent);
     break;      break;
   
       case OP_MARK:
       PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
       SLJIT_ASSERT(common->mark_ptr != 0);
       OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
       allocate_stack(common, 1);
       OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
       OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)(cc + 2));
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0);
       OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
       cc += 1 + 2 + cc[1];
       break;
   
       case OP_COMMIT:
       PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
       cc += 1;
       break;
   
     case OP_FAIL:      case OP_FAIL:
     case OP_ACCEPT:      case OP_ACCEPT:
     case OP_ASSERT_ACCEPT:      case OP_ASSERT_ACCEPT:
    cc = compile_fail_accept_hotpath(common, cc, parent);    cc = compile_fail_accept_trypath(common, cc, parent);
     break;      break;
   
     case OP_CLOSE:      case OP_CLOSE:
    cc = compile_close_hotpath(common, cc);    cc = compile_close_trypath(common, cc);
     break;      break;
   
     case OP_SKIPZERO:      case OP_SKIPZERO:
Line 5444  while (cc < ccend) Line 5863  while (cc < ccend)
 SLJIT_ASSERT(cc == ccend);  SLJIT_ASSERT(cc == ccend);
 }  }
   
#undef PUSH_FALLBACK#undef PUSH_BACKTRACK
#undef PUSH_FALLBACK_NOVALUE#undef PUSH_BACKTRACK_NOVALUE
#undef FALLBACK_AS#undef BACKTRACK_AS
   
#define COMPILE_FALLBACKPATH(current) \#define COMPILE_BACKTRACKPATH(current) \
   do \    do \
     { \      { \
    compile_fallbackpath(common, (current)); \    compile_backtrackpath(common, (current)); \
     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \      if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
       return; \        return; \
     } \      } \
   while (0)    while (0)
   
#define CURRENT_AS(type) ((type*)current)#define CURRENT_AS(type) ((type *)current)
   
static void compile_iterator_fallbackpath(compiler_common *common, struct fallback_common *current)static void compile_iterator_backtrackpath(compiler_common *common, struct backtrack_common *current)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 pcre_uchar *cc = current->cc;  pcre_uchar *cc = current->cc;
Line 5468  pcre_uchar type; Line 5887  pcre_uchar type;
 int arg1 = -1, arg2 = -1;  int arg1 = -1, arg2 = -1;
 struct sljit_label *label = NULL;  struct sljit_label *label = NULL;
 struct sljit_jump *jump = NULL;  struct sljit_jump *jump = NULL;
   jump_list *jumplist = NULL;
   
 cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL);  cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL);
   
Line 5479  switch(opcode) Line 5899  switch(opcode)
   case OP_CRRANGE:    case OP_CRRANGE:
   if (type == OP_ANYNL || type == OP_EXTUNI)    if (type == OP_ANYNL || type == OP_EXTUNI)
     {      {
    set_jumps(current->topfallbacks, LABEL());    set_jumps(current->topbacktracks, LABEL());
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
     free_stack(common, 1);      free_stack(common, 1);
    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
     }      }
   else    else
     {      {
    if (opcode == OP_STAR || opcode == OP_UPTO)    if (opcode <= OP_PLUS || opcode == OP_UPTO)
       arg2 = 0;        arg2 = 0;
    else if (opcode == OP_PLUS)    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
      arg2 = 1;    jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, arg2 + 1);
    jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, arg2 + 1);    OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(1)TMP1, 0, SLJIT_IMM, 1);
    OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(1)SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); 
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
     skip_char_back(common);      skip_char_back(common);
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
    if (opcode == OP_PLUS || opcode == OP_CRRANGE)    if (opcode == OP_CRRANGE)
      set_jumps(current->topfallbacks, LABEL());      set_jumps(current->topbacktracks, LABEL());
     JUMPHERE(jump);      JUMPHERE(jump);
     free_stack(common, 2);      free_stack(common, 2);
       if (opcode == OP_PLUS)
         set_jumps(current->topbacktracks, LABEL());
     }      }
   break;    break;
   
   case OP_MINSTAR:    case OP_MINSTAR:
   case OP_MINPLUS:    case OP_MINPLUS:
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  if (opcode == OP_MINPLUS)  compile_char1_trypath(common, type, cc, &jumplist);
    { 
    set_jumps(current->topfallbacks, LABEL()); 
    current->topfallbacks = NULL; 
    } 
  compile_char1_hotpath(common, type, cc, &current->topfallbacks); 
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
  set_jumps(current->topfallbacks, LABEL());  set_jumps(jumplist, LABEL());
   free_stack(common, 1);    free_stack(common, 1);
     if (opcode == OP_MINPLUS)
       set_jumps(current->topbacktracks, LABEL());
   break;    break;
   
   case OP_MINUPTO:    case OP_MINUPTO:
   case OP_CRMINRANGE:    case OP_CRMINRANGE:
   if (opcode == OP_CRMINRANGE)    if (opcode == OP_CRMINRANGE)
     {      {
     set_jumps(current->topfallbacks, LABEL());  
     current->topfallbacks = NULL;  
     label = LABEL();      label = LABEL();
       set_jumps(current->topbacktracks, label);
     }      }
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  compile_char1_hotpath(common, type, cc, &current->topfallbacks);  compile_char1_trypath(common, type, cc, &jumplist);
   
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
Line 5538  switch(opcode) Line 5955  switch(opcode)
     CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label);      CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label);
   
   if (opcode == OP_CRMINRANGE && arg1 == 0)    if (opcode == OP_CRMINRANGE && arg1 == 0)
    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
   else    else
    CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_fallback)->hotpath);    CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_backtrack)->trypath);
   
  set_jumps(current->topfallbacks, LABEL());  set_jumps(jumplist, LABEL());
   free_stack(common, 2);    free_stack(common, 2);
   break;    break;
   
   case OP_QUERY:    case OP_QUERY:
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
   jump = JUMP(SLJIT_JUMP);    jump = JUMP(SLJIT_JUMP);
  set_jumps(current->topfallbacks, LABEL());  set_jumps(current->topbacktracks, LABEL());
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
   JUMPHERE(jump);    JUMPHERE(jump);
   free_stack(common, 1);    free_stack(common, 1);
   break;    break;
Line 5563  switch(opcode) Line 5980  switch(opcode)
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
   jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);    jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
  compile_char1_hotpath(common, type, cc, &current->topfallbacks);  compile_char1_trypath(common, type, cc, &jumplist);
  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
  set_jumps(current->topfallbacks, LABEL());  set_jumps(jumplist, LABEL());
   JUMPHERE(jump);    JUMPHERE(jump);
   free_stack(common, 1);    free_stack(common, 1);
   break;    break;
   
   case OP_EXACT:    case OP_EXACT:
   case OP_POSPLUS:    case OP_POSPLUS:
  set_jumps(current->topfallbacks, LABEL());  set_jumps(current->topbacktracks, LABEL());
   break;    break;
   
   case OP_POSSTAR:    case OP_POSSTAR:
Line 5586  switch(opcode) Line 6003  switch(opcode)
   }    }
 }  }
   
static void compile_ref_iterator_fallbackpath(compiler_common *common, struct fallback_common *current)static void compile_ref_iterator_backtrackpath(compiler_common *common, struct backtrack_common *current)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 pcre_uchar *cc = current->cc;  pcre_uchar *cc = current->cc;
Line 5595  pcre_uchar type; Line 6012  pcre_uchar type;
 type = cc[1 + IMM2_SIZE];  type = cc[1 + IMM2_SIZE];
 if ((type & 0x1) == 0)  if ((type & 0x1) == 0)
   {    {
  set_jumps(current->topfallbacks, LABEL());  set_jumps(current->topbacktracks, LABEL());
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   free_stack(common, 1);    free_stack(common, 1);
  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
   return;    return;
   }    }
   
 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
set_jumps(current->topfallbacks, LABEL());set_jumps(current->topbacktracks, LABEL());
 free_stack(common, 2);  free_stack(common, 2);
 }  }
   
static void compile_recurse_fallbackpath(compiler_common *common, struct fallback_common *current)static void compile_recurse_backtrackpath(compiler_common *common, struct backtrack_common *current)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
   
set_jumps(current->topfallbacks, LABEL());set_jumps(current->topbacktracks, LABEL());
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
free_stack(common, 1);if (common->has_set_som && common->mark_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);  {
   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
   free_stack(common, 2);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0);
   }
 else if (common->has_set_som || common->mark_ptr != 0)
   {
   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   free_stack(common, 1);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0);
   }
 }  }
   
static void compile_assert_fallbackpath(compiler_common *common, struct fallback_common *current)static void compile_assert_backtrackpath(compiler_common *common, struct backtrack_common *current)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 pcre_uchar *cc = current->cc;  pcre_uchar *cc = current->cc;
Line 5634  if (*cc == OP_BRAZERO) Line 6063  if (*cc == OP_BRAZERO)
   
 if (bra == OP_BRAZERO)  if (bra == OP_BRAZERO)
   {    {
  SLJIT_ASSERT(current->topfallbacks == NULL);  SLJIT_ASSERT(current->topbacktracks == NULL);
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   }    }
   
if (CURRENT_AS(assert_fallback)->framesize < 0)if (CURRENT_AS(assert_backtrack)->framesize < 0)
   {    {
  set_jumps(current->topfallbacks, LABEL());  set_jumps(current->topbacktracks, LABEL());
   
   if (bra == OP_BRAZERO)    if (bra == OP_BRAZERO)
     {      {
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_fallback)->hotpath);    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->trypath);
     free_stack(common, 1);      free_stack(common, 1);
     }      }
   return;    return;
Line 5656  if (bra == OP_BRAZERO) Line 6085  if (bra == OP_BRAZERO)
   if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)    if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)
     {      {
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_fallback)->hotpath);    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->trypath);
     free_stack(common, 1);      free_stack(common, 1);
     return;      return;
     }      }
Line 5666  if (bra == OP_BRAZERO) Line 6095  if (bra == OP_BRAZERO)
   
 if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)  if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)
   {    {
  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr);  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->localptr);
   add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));    add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_fallback)->framesize * sizeof(sljit_w));  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_w));
   
  set_jumps(current->topfallbacks, LABEL());  set_jumps(current->topbacktracks, LABEL());
   }    }
 else  else
  set_jumps(current->topfallbacks, LABEL());  set_jumps(current->topbacktracks, LABEL());
   
 if (bra == OP_BRAZERO)  if (bra == OP_BRAZERO)
   {    {
   /* We know there is enough place on the stack. */    /* We know there is enough place on the stack. */
   OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));    OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
  JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_fallback)->hotpath);  JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->trypath);
   JUMPHERE(brajump);    JUMPHERE(brajump);
   }    }
 }  }
   
static void compile_bracket_fallbackpath(compiler_common *common, struct fallback_common *current)static void compile_bracket_backtrackpath(compiler_common *common, struct backtrack_common *current)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 int opcode;  int opcode;
 int offset = 0;  int offset = 0;
int localptr = CURRENT_AS(bracket_fallback)->localptr;int localptr = CURRENT_AS(bracket_backtrack)->localptr;
 int stacksize;  int stacksize;
 int count;  int count;
 pcre_uchar *cc = current->cc;  pcre_uchar *cc = current->cc;
Line 5700  jump_list *jumplist = NULL; Line 6129  jump_list *jumplist = NULL;
 jump_list *jumplistitem = NULL;  jump_list *jumplistitem = NULL;
 pcre_uchar bra = OP_BRA;  pcre_uchar bra = OP_BRA;
 pcre_uchar ket;  pcre_uchar ket;
assert_fallback *assert;assert_backtrack *assert;
 BOOL has_alternatives;  BOOL has_alternatives;
 struct sljit_jump *brazero = NULL;  struct sljit_jump *brazero = NULL;
 struct sljit_jump *once = NULL;  struct sljit_jump *once = NULL;
Line 5719  ket = *(bracketend(ccbegin) - 1 - LINK_SIZE); Line 6148  ket = *(bracketend(ccbegin) - 1 - LINK_SIZE);
 cc += GET(cc, 1);  cc += GET(cc, 1);
 has_alternatives = *cc == OP_ALT;  has_alternatives = *cc == OP_ALT;
 if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
  has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_fallback)->u.condfailed != NULL;  has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL;
 if (opcode == OP_CBRA || opcode == OP_SCBRA)  if (opcode == OP_CBRA || opcode == OP_SCBRA)
   offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;    offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;
 if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))  if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
Line 5729  if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) Line 6158  if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
   
 if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
   {    {
  if (bra != OP_BRAZERO)  if (bra == OP_BRAZERO)
    free_stack(common, 1); 
  else 
     {      {
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
     free_stack(common, 1);      free_stack(common, 1);
Line 5746  else if (ket == OP_KETRMIN) Line 6173  else if (ket == OP_KETRMIN)
     if (opcode >= OP_SBRA || opcode == OP_ONCE)      if (opcode >= OP_SBRA || opcode == OP_ONCE)
       {        {
       /* Checking zero-length iteration. */        /* Checking zero-length iteration. */
      if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize < 0)      if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)
        CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_fallback)->recursivehotpath);        CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_backtrack)->recursivetrypath);
       else        else
         {          {
         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
        CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_fallback)->recursivehotpath);        CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_backtrack)->recursivetrypath);
         }          }
       if (opcode != OP_ONCE)        if (opcode != OP_ONCE)
         free_stack(common, 1);          free_stack(common, 1);
       }        }
     else      else
      JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->recursivehotpath);      JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursivetrypath);
     }      }
   rminlabel = LABEL();    rminlabel = LABEL();
   }    }
Line 5770  else if (bra == OP_BRAZERO) Line 6197  else if (bra == OP_BRAZERO)
   
 if (SLJIT_UNLIKELY(opcode == OP_ONCE))  if (SLJIT_UNLIKELY(opcode == OP_ONCE))
   {    {
  if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)  if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
     {      {
     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));      add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
Line 5825  else if (*cc == OP_ALT) Line 6252  else if (*cc == OP_ALT)
   cc = ccbegin + GET(ccbegin, 1);    cc = ccbegin + GET(ccbegin, 1);
   }    }
   
COMPILE_FALLBACKPATH(current->top);COMPILE_BACKTRACKPATH(current->top);
if (current->topfallbacks)if (current->topbacktracks)
  set_jumps(current->topfallbacks, LABEL());  set_jumps(current->topbacktracks, LABEL());
   
 if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
   {    {
Line 5835  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKEL Line 6262  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKEL
   if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)    if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)
     {      {
     SLJIT_ASSERT(has_alternatives);      SLJIT_ASSERT(has_alternatives);
    assert = CURRENT_AS(bracket_fallback)->u.assert;    assert = CURRENT_AS(bracket_backtrack)->u.assert;
     if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))      if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))
       {        {
       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr);        OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr);
Line 5843  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKEL Line 6270  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKEL
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
       }        }
     cond = JUMP(SLJIT_JUMP);      cond = JUMP(SLJIT_JUMP);
    set_jumps(CURRENT_AS(bracket_fallback)->u.assert->condfailed, LABEL());    set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL());
     }      }
  else if (CURRENT_AS(bracket_fallback)->u.condfailed != NULL)  else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL)
     {      {
     SLJIT_ASSERT(has_alternatives);      SLJIT_ASSERT(has_alternatives);
     cond = JUMP(SLJIT_JUMP);      cond = JUMP(SLJIT_JUMP);
    set_jumps(CURRENT_AS(bracket_fallback)->u.condfailed, LABEL());    set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL());
     }      }
   else    else
     SLJIT_ASSERT(!has_alternatives);      SLJIT_ASSERT(!has_alternatives);
Line 5861  if (has_alternatives) Line 6288  if (has_alternatives)
   do    do
     {      {
     current->top = NULL;      current->top = NULL;
    current->topfallbacks = NULL;    current->topbacktracks = NULL;
    current->nextfallbacks = NULL;    current->nextbacktracks = NULL;
     if (*cc == OP_ALT)      if (*cc == OP_ALT)
       {        {
       ccprev = cc + 1 + LINK_SIZE;        ccprev = cc + 1 + LINK_SIZE;
Line 5874  if (has_alternatives) Line 6301  if (has_alternatives)
         else          else
           OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));            OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
         }          }
      compile_hotpath(common, ccprev, cc, current);      compile_trypath(common, ccprev, cc, current);
       if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))        if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
         return;          return;
       }        }
   
     /* Instructions after the current alternative is succesfully matched. */      /* Instructions after the current alternative is succesfully matched. */
    /* There is a similar code in compile_bracket_hotpath. */    /* There is a similar code in compile_bracket_trypath. */
     if (opcode == OP_ONCE)      if (opcode == OP_ONCE)
       {        {
      if (CURRENT_AS(bracket_fallback)->u.framesize < 0)      if (CURRENT_AS(bracket_backtrack)->u.framesize < 0)
         {          {
         OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);          OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
         /* TMP2 which is set here used by OP_KETRMAX below. */          /* TMP2 which is set here used by OP_KETRMAX below. */
Line 5897  if (has_alternatives) Line 6324  if (has_alternatives)
         }          }
       else        else
         {          {
        OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (CURRENT_AS(bracket_fallback)->u.framesize + 2) * sizeof(sljit_w));        OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (CURRENT_AS(bracket_backtrack)->u.framesize + 2) * sizeof(sljit_w));
         if (ket == OP_KETRMAX)          if (ket == OP_KETRMAX)
           {            {
           /* TMP2 which is set here used by OP_KETRMAX below. */            /* TMP2 which is set here used by OP_KETRMAX below. */
Line 5913  if (has_alternatives) Line 6340  if (has_alternatives)
       stacksize++;        stacksize++;
   
     if (stacksize > 0) {      if (stacksize > 0) {
      if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize >= 0)      if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
         allocate_stack(common, stacksize);          allocate_stack(common, stacksize);
       else        else
         {          {
Line 5943  if (has_alternatives) Line 6370  if (has_alternatives)
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
       }        }
   
    JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->althotpath);    JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alttrypath);
   
     if (opcode != OP_ONCE)      if (opcode != OP_ONCE)
       {        {
Line 5952  if (has_alternatives) Line 6379  if (has_alternatives)
       jumplist = jumplist->next;        jumplist = jumplist->next;
       }        }
   
    COMPILE_FALLBACKPATH(current->top);    COMPILE_BACKTRACKPATH(current->top);
    if (current->topfallbacks)    if (current->topbacktracks)
      set_jumps(current->topfallbacks, LABEL());      set_jumps(current->topbacktracks, LABEL());
    SLJIT_ASSERT(!current->nextfallbacks);    SLJIT_ASSERT(!current->nextbacktracks);
     }      }
   while (*cc == OP_ALT);    while (*cc == OP_ALT);
   SLJIT_ASSERT(!jumplist);    SLJIT_ASSERT(!jumplist);
Line 5963  if (has_alternatives) Line 6390  if (has_alternatives)
   if (cond != NULL)    if (cond != NULL)
     {      {
     SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);      SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);
    assert = CURRENT_AS(bracket_fallback)->u.assert;    assert = CURRENT_AS(bracket_backtrack)->u.assert;
     if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0)      if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0)
   
       {        {
Line 5997  else if (opcode == OP_SBRA || opcode == OP_SCOND) Line 6424  else if (opcode == OP_SBRA || opcode == OP_SCOND)
 else if (opcode == OP_ONCE)  else if (opcode == OP_ONCE)
   {    {
   cc = ccbegin + GET(ccbegin, 1);    cc = ccbegin + GET(ccbegin, 1);
  if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)  if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
     {      {
     /* Reset head and drop saved frame. */      /* Reset head and drop saved frame. */
     stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1;      stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1;
    free_stack(common, CURRENT_AS(bracket_fallback)->u.framesize + stacksize);    free_stack(common, CURRENT_AS(bracket_backtrack)->u.framesize + stacksize);
     }      }
   else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))    else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))
     {      {
Line 6011  else if (opcode == OP_ONCE) Line 6438  else if (opcode == OP_ONCE)
   
   JUMPHERE(once);    JUMPHERE(once);
   /* Restore previous localptr */    /* Restore previous localptr */
  if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)  if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_fallback)->u.framesize * sizeof(sljit_w));    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_w));
   else if (ket == OP_KETRMIN)    else if (ket == OP_KETRMIN)
     {      {
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
Line 6025  else if (opcode == OP_ONCE) Line 6452  else if (opcode == OP_ONCE)
 if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
   {    {
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_fallback)->recursivehotpath);  if (bra != OP_BRAZERO)
     free_stack(common, 1);
   CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursivetrypath);
   if (bra == OP_BRAZERO)    if (bra == OP_BRAZERO)
     {      {
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
    JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath);    JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zerotrypath);
     JUMPHERE(brazero);      JUMPHERE(brazero);
       free_stack(common, 1);
     }      }
   free_stack(common, 1);  
   }    }
 else if (ket == OP_KETRMIN)  else if (ket == OP_KETRMIN)
   {    {
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   
  /* OP_ONCE removes everything in case of a fallback, so we don't  /* OP_ONCE removes everything in case of a backtrack, so we don't
   need to explicitly release the STR_PTR. The extra release would    need to explicitly release the STR_PTR. The extra release would
   affect badly the free_stack(2) above. */    affect badly the free_stack(2) above. */
   if (opcode != OP_ONCE)    if (opcode != OP_ONCE)
Line 6052  else if (ket == OP_KETRMIN) Line 6481  else if (ket == OP_KETRMIN)
 else if (bra == OP_BRAZERO)  else if (bra == OP_BRAZERO)
   {    {
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath);  JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zerotrypath);
   JUMPHERE(brazero);    JUMPHERE(brazero);
   }    }
 }  }
   
static void compile_bracketpos_fallbackpath(compiler_common *common, struct fallback_common *current)static void compile_bracketpos_backtrackpath(compiler_common *common, struct backtrack_common *current)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
 int offset;  int offset;
 struct sljit_jump *jump;  struct sljit_jump *jump;
   
if (CURRENT_AS(bracketpos_fallback)->framesize < 0)if (CURRENT_AS(bracketpos_backtrack)->framesize < 0)
   {    {
   if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS)    if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS)
     {      {
Line 6073  if (CURRENT_AS(bracketpos_fallback)->framesize < 0) Line 6502  if (CURRENT_AS(bracketpos_fallback)->framesize < 0)
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
     }      }
  set_jumps(current->topfallbacks, LABEL());  set_jumps(current->topbacktracks, LABEL());
  free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize);  free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
   return;    return;
   }    }
   
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr);OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->localptr);
 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));  add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
   
if (current->topfallbacks)if (current->topbacktracks)
   {    {
   jump = JUMP(SLJIT_JUMP);    jump = JUMP(SLJIT_JUMP);
  set_jumps(current->topfallbacks, LABEL());  set_jumps(current->topbacktracks, LABEL());
   /* Drop the stack frame. */    /* Drop the stack frame. */
  free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize);  free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
   JUMPHERE(jump);    JUMPHERE(jump);
   }    }
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_fallback)->framesize * sizeof(sljit_w));OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_w));
 }  }
   
static void compile_braminzero_fallbackpath(compiler_common *common, struct fallback_common *current)static void compile_braminzero_backtrackpath(compiler_common *common, struct backtrack_common *current)
 {  {
assert_fallback fallback;assert_backtrack backtrack;
   
 current->top = NULL;  current->top = NULL;
current->topfallbacks = NULL;current->topbacktracks = NULL;
current->nextfallbacks = NULL;current->nextbacktracks = NULL;
 if (current->cc[1] > OP_ASSERTBACK_NOT)  if (current->cc[1] > OP_ASSERTBACK_NOT)
   {    {
  /* Manual call of compile_bracket_hotpath and compile_bracket_fallbackpath. */  /* Manual call of compile_bracket_trypath and compile_bracket_backtrackpath. */
  compile_bracket_hotpath(common, current->cc, current);  compile_bracket_trypath(common, current->cc, current);
  compile_bracket_fallbackpath(common, current->top);  compile_bracket_backtrackpath(common, current->top);
   }    }
 else  else
   {    {
  memset(&fallback, 0, sizeof(fallback));  memset(&backtrack, 0, sizeof(backtrack));
  fallback.common.cc = current->cc;  backtrack.common.cc = current->cc;
  fallback.hotpath = CURRENT_AS(braminzero_fallback)->hotpath;  backtrack.trypath = CURRENT_AS(braminzero_backtrack)->trypath;
  /* Manual call of compile_assert_hotpath. */  /* Manual call of compile_assert_trypath. */
  compile_assert_hotpath(common, current->cc, &fallback, FALSE);  compile_assert_trypath(common, current->cc, &backtrack, FALSE);
   }    }
SLJIT_ASSERT(!current->nextfallbacks && !current->topfallbacks);SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks);
 }  }
   
static void compile_fallbackpath(compiler_common *common, struct fallback_common *current)static void compile_backtrackpath(compiler_common *common, struct backtrack_common *current)
 {  {
 DEFINE_COMPILER;  DEFINE_COMPILER;
   
 while (current)  while (current)
   {    {
  if (current->nextfallbacks != NULL)  if (current->nextbacktracks != NULL)
    set_jumps(current->nextfallbacks, LABEL());    set_jumps(current->nextbacktracks, LABEL());
   switch(*current->cc)    switch(*current->cc)
     {      {
     case OP_SET_SOM:      case OP_SET_SOM:
Line 6202  while (current) Line 6631  while (current)
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8  #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
     case OP_XCLASS:      case OP_XCLASS:
 #endif  #endif
    compile_iterator_fallbackpath(common, current);    compile_iterator_backtrackpath(common, current);
     break;      break;
   
     case OP_REF:      case OP_REF:
     case OP_REFI:      case OP_REFI:
    compile_ref_iterator_fallbackpath(common, current);    compile_ref_iterator_backtrackpath(common, current);
     break;      break;
   
     case OP_RECURSE:      case OP_RECURSE:
    compile_recurse_fallbackpath(common, current);    compile_recurse_backtrackpath(common, current);
     break;      break;
   
     case OP_ASSERT:      case OP_ASSERT:
     case OP_ASSERT_NOT:      case OP_ASSERT_NOT:
     case OP_ASSERTBACK:      case OP_ASSERTBACK:
     case OP_ASSERTBACK_NOT:      case OP_ASSERTBACK_NOT:
    compile_assert_fallbackpath(common, current);    compile_assert_backtrackpath(common, current);
     break;      break;
   
     case OP_ONCE:      case OP_ONCE:
Line 6229  while (current) Line 6658  while (current)
     case OP_SBRA:      case OP_SBRA:
     case OP_SCBRA:      case OP_SCBRA:
     case OP_SCOND:      case OP_SCOND:
    compile_bracket_fallbackpath(common, current);    compile_bracket_backtrackpath(common, current);
     break;      break;
   
     case OP_BRAZERO:      case OP_BRAZERO:
     if (current->cc[1] > OP_ASSERTBACK_NOT)      if (current->cc[1] > OP_ASSERTBACK_NOT)
      compile_bracket_fallbackpath(common, current);      compile_bracket_backtrackpath(common, current);
     else      else
      compile_assert_fallbackpath(common, current);      compile_assert_backtrackpath(common, current);
     break;      break;
   
     case OP_BRAPOS:      case OP_BRAPOS:
Line 6244  while (current) Line 6673  while (current)
     case OP_SBRAPOS:      case OP_SBRAPOS:
     case OP_SCBRAPOS:      case OP_SCBRAPOS:
     case OP_BRAPOSZERO:      case OP_BRAPOSZERO:
    compile_bracketpos_fallbackpath(common, current);    compile_bracketpos_backtrackpath(common, current);
     break;      break;
   
     case OP_BRAMINZERO:      case OP_BRAMINZERO:
    compile_braminzero_fallbackpath(common, current);    compile_braminzero_backtrackpath(common, current);
     break;      break;
   
       case OP_MARK:
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
       free_stack(common, 1);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0);
       break;
   
       case OP_COMMIT:
       OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
       if (common->leavelabel == NULL)
         add_jump(compiler, &common->leave, JUMP(SLJIT_JUMP));
       else
         JUMPTO(SLJIT_JUMP, common->leavelabel);
       break;
   
     case OP_FAIL:      case OP_FAIL:
     case OP_ACCEPT:      case OP_ACCEPT:
     case OP_ASSERT_ACCEPT:      case OP_ASSERT_ACCEPT:
    set_jumps(current->topfallbacks, LABEL());    set_jumps(current->topbacktracks, LABEL());
     break;      break;
   
     default:      default:
Line 6275  int localsize = get_localsize(common, ccbegin, ccend); Line 6718  int localsize = get_localsize(common, ccbegin, ccend);
 int framesize = get_framesize(common, cc, TRUE);  int framesize = get_framesize(common, cc, TRUE);
 int alternativesize;  int alternativesize;
 BOOL needsframe;  BOOL needsframe;
fallback_common altfallback;backtrack_common altbacktrack;
 struct sljit_label *save_leavelabel = common->leavelabel;
 jump_list *save_leave = common->leave;
 struct sljit_jump *jump;  struct sljit_jump *jump;
   
 SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);  SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);
Line 6284  if (!needsframe) Line 6729  if (!needsframe)
   framesize = 0;    framesize = 0;
 alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0;  alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0;
   
SLJIT_ASSERT(common->currententry->entry == NULL);SLJIT_ASSERT(common->currententry->entry == NULL && common->recursive_head != 0);
 common->currententry->entry = LABEL();  common->currententry->entry = LABEL();
 set_jumps(common->currententry->calls, common->currententry->entry);  set_jumps(common->currententry->calls, common->currententry->entry);
   
sljit_emit_fast_enter(compiler, TMP2, 0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, TMP2, 0);
 allocate_stack(common, localsize + framesize + alternativesize);  allocate_stack(common, localsize + framesize + alternativesize);
 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(localsize + framesize + alternativesize - 1), TMP2, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(localsize + framesize + alternativesize - 1), TMP2, 0);
 copy_locals(common, ccbegin, ccend, TRUE, localsize + framesize + alternativesize, framesize + alternativesize);  copy_locals(common, ccbegin, ccend, TRUE, localsize + framesize + alternativesize, framesize + alternativesize);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD, STACK_TOP, 0);OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head, STACK_TOP, 0);
 if (needsframe)  if (needsframe)
  init_frame(common, cc, framesize + alternativesize - 1, alternativesize, FALSE);  init_frame(common, cc, framesize + alternativesize - 1, alternativesize, TRUE);
   
 if (alternativesize > 0)  if (alternativesize > 0)
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
   
memset(&altfallback, 0, sizeof(fallback_common));memset(&altbacktrack, 0, sizeof(backtrack_common));
 common->leavelabel = NULL;
 common->acceptlabel = NULL;  common->acceptlabel = NULL;
   common->leave = NULL;
 common->accept = NULL;  common->accept = NULL;
altfallback.cc = ccbegin;altbacktrack.cc = ccbegin;
 cc += GET(cc, 1);  cc += GET(cc, 1);
 while (1)  while (1)
   {    {
  altfallback.top = NULL;  altbacktrack.top = NULL;
  altfallback.topfallbacks = NULL;  altbacktrack.topbacktracks = NULL;
   
  if (altfallback.cc != ccbegin)  if (altbacktrack.cc != ccbegin)
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   
  compile_hotpath(common, altfallback.cc, cc, &altfallback);  compile_trypath(common, altbacktrack.cc, cc, &altbacktrack);
   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
       {
       common->leavelabel = save_leavelabel;
       common->leave = save_leave;
     return;      return;
       }
   
   add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));    add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
   
  compile_fallbackpath(common, altfallback.top);  compile_backtrackpath(common, altbacktrack.top);
   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
       {
       common->leavelabel = save_leavelabel;
       common->leave = save_leave;
     return;      return;
  set_jumps(altfallback.topfallbacks, LABEL());    }
   set_jumps(altbacktrack.topbacktracks, LABEL());
   
   if (*cc != OP_ALT)    if (*cc != OP_ALT)
     break;      break;
   
  altfallback.cc = cc + 1 + LINK_SIZE;  altbacktrack.cc = cc + 1 + LINK_SIZE;
   cc += GET(cc, 1);    cc += GET(cc, 1);
   }    }
 /* None of them matched. */  /* None of them matched. */
   if (common->leave != NULL)
     set_jumps(common->leave, LABEL());
   
 OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);  OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
 jump = JUMP(SLJIT_JUMP);  jump = JUMP(SLJIT_JUMP);
   
 set_jumps(common->accept, LABEL());  set_jumps(common->accept, LABEL());
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD);OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head);
 if (needsframe)  if (needsframe)
   {    {
   OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));  
   OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));    OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));
   add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));    add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
   OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));    OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP3, 0);  
   }    }
 OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);  OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);
   
Line 6350  copy_locals(common, ccbegin, ccend, FALSE, localsize + Line 6806  copy_locals(common, ccbegin, ccend, FALSE, localsize +
 free_stack(common, localsize + framesize + alternativesize);  free_stack(common, localsize + framesize + alternativesize);
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_w));  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_w));
 OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);  OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD, TMP2, 0);OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head, TMP2, 0);
 sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);  sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);
   
   common->leavelabel = save_leavelabel;
   common->leave = save_leave;
 }  }
   
#undef COMPILE_FALLBACKPATH#undef COMPILE_BACKTRACKPATH
 #undef CURRENT_AS  #undef CURRENT_AS
   
 void  void
PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra)PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra, int mode)
 {  {
 struct sljit_compiler *compiler;  struct sljit_compiler *compiler;
fallback_common rootfallback;backtrack_common rootbacktrack;
 compiler_common common_data;  compiler_common common_data;
 compiler_common *common = &common_data;  compiler_common *common = &common_data;
 const pcre_uint8 *tables = re->tables;  const pcre_uint8 *tables = re->tables;
 pcre_study_data *study;  pcre_study_data *study;
   int localsize;
 pcre_uchar *ccend;  pcre_uchar *ccend;
executable_function *function;executable_functions *functions;
 void *executable_func;  void *executable_func;
 sljit_uw executable_size;  sljit_uw executable_size;
 struct sljit_label *leave;  
 struct sljit_label *mainloop = NULL;  struct sljit_label *mainloop = NULL;
 struct sljit_label *empty_match_found;  struct sljit_label *empty_match_found;
struct sljit_label *empty_match_fallback;struct sljit_label *empty_match_backtrack;
struct sljit_jump *alloc_error;struct sljit_jump *jump;
 struct sljit_jump *reqbyte_notfound = NULL;  struct sljit_jump *reqbyte_notfound = NULL;
 struct sljit_jump *empty_match;  struct sljit_jump *empty_match;
   
Line 6384  study = extra->study_data; Line 6843  study = extra->study_data;
 if (!tables)  if (!tables)
   tables = PRIV(default_tables);    tables = PRIV(default_tables);
   
memset(&rootfallback, 0, sizeof(fallback_common));memset(&rootbacktrack, 0, sizeof(backtrack_common));
rootfallback.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size;memset(common, 0, sizeof(compiler_common));
 rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size;
   
common->compiler = NULL;common->start = rootbacktrack.cc;
common->start = rootfallback.cc; 
common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w); 
 common->fcc = tables + fcc_offset;  common->fcc = tables + fcc_offset;
 common->lcc = (sljit_w)(tables + lcc_offset);  common->lcc = (sljit_w)(tables + lcc_offset);
   common->mode = mode;
 common->nltype = NLTYPE_FIXED;  common->nltype = NLTYPE_FIXED;
 switch(re->options & PCRE_NEWLINE_BITS)  switch(re->options & PCRE_NEWLINE_BITS)
   {    {
Line 6429  common->ctypes = (sljit_w)(tables + ctypes_offset); Line 6888  common->ctypes = (sljit_w)(tables + ctypes_offset);
 common->name_table = (sljit_w)((pcre_uchar *)re + re->name_table_offset);  common->name_table = (sljit_w)((pcre_uchar *)re + re->name_table_offset);
 common->name_count = re->name_count;  common->name_count = re->name_count;
 common->name_entry_size = re->name_entry_size;  common->name_entry_size = re->name_entry_size;
 common->acceptlabel = NULL;  
 common->stubs = NULL;  
 common->entries = NULL;  
 common->currententry = NULL;  
 common->accept = NULL;  
 common->calllimit = NULL;  
 common->stackalloc = NULL;  
 common->revertframes = NULL;  
 common->wordboundary = NULL;  
 common->anynewline = NULL;  
 common->hspace = NULL;  
 common->vspace = NULL;  
 common->casefulcmp = NULL;  
 common->caselesscmp = NULL;  
 common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;  common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
 /* PCRE_UTF16 has the same value as PCRE_UTF8. */  /* PCRE_UTF16 has the same value as PCRE_UTF8. */
Line 6450  common->utf = (re->options & PCRE_UTF8) != 0; Line 6895  common->utf = (re->options & PCRE_UTF8) != 0;
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
 common->use_ucp = (re->options & PCRE_UCP) != 0;  common->use_ucp = (re->options & PCRE_UCP) != 0;
 #endif  #endif
 common->utfreadchar = NULL;  
 #ifdef COMPILE_PCRE8  
 common->utfreadtype8 = NULL;  
 #endif  
 #endif /* SUPPORT_UTF */  #endif /* SUPPORT_UTF */
#ifdef SUPPORT_UCPccend = bracketend(rootbacktrack.cc);
common->getucd = NULL;
#endif/* Calculate the local space size on the stack. */
ccend = bracketend(rootfallback.cc);common->ovector_start = CALL_LIMIT + sizeof(sljit_w);
SLJIT_ASSERT(*rootfallback.cc == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
common->localsize = get_localspace(common, rootfallback.cc, ccend);SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
if (common->localsize < 0)localsize = get_localspace(common, rootbacktrack.cc, ccend);
 if (localsize < 0)
   return;    return;
common->localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w);
if (common->localsize > SLJIT_MAX_LOCAL_SIZE)/* Checking flags and updating ovector_start. */
 if (mode == JIT_COMPILE && (re->flags & PCRE_REQCHSET) != 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
   {
   common->req_char_ptr = common->ovector_start;
   common->ovector_start += sizeof(sljit_w);
   }
 if (mode != JIT_COMPILE)
   {
   common->start_used_ptr = common->ovector_start;
   common->ovector_start += sizeof(sljit_w);
   if (mode == JIT_PARTIAL_SOFT_COMPILE)
     {
     common->hit_start = common->ovector_start;
     common->ovector_start += sizeof(sljit_w);
     }
   }
 if ((re->options & PCRE_FIRSTLINE) != 0)
   {
   common->first_line_end = common->ovector_start;
   common->ovector_start += sizeof(sljit_w);
   }
 
 /* Aligning ovector to even number of sljit words. */
 if ((common->ovector_start & sizeof(sljit_w)) != 0)
   common->ovector_start += sizeof(sljit_w);
 
 SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
 common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w);
 localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w);
 if (localsize > SLJIT_MAX_LOCAL_SIZE)
   return;    return;
common->localptrs = (int*)SLJIT_MALLOC((ccend - rootfallback.cc) * sizeof(int));common->localptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(int));
 if (!common->localptrs)  if (!common->localptrs)
   return;    return;
memset(common->localptrs, 0, (ccend - rootfallback.cc) * sizeof(int));memset(common->localptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int));
 set_localptrs(common, common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w), ccend);  set_localptrs(common, common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w), ccend);
   
 compiler = sljit_create_compiler();  compiler = sljit_create_compiler();
Line 6481  if (!compiler) Line 6952  if (!compiler)
 common->compiler = compiler;  common->compiler = compiler;
   
 /* Main pcre_jit_exec entry. */  /* Main pcre_jit_exec entry. */
sljit_emit_enter(compiler, 1, 5, 5, common->localsize);sljit_emit_enter(compiler, 1, 5, 5, localsize);
   
 /* Register init. */  /* Register init. */
 reset_ovector(common, (re->top_bracket + 1) * 2);  reset_ovector(common, (re->top_bracket + 1) * 2);
if ((re->flags & PCRE_REQCHSET) != 0)if (common->req_char_ptr != 0)
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, SLJIT_TEMPORARY_REG1, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, SLJIT_TEMPORARY_REG1, 0);
   
 OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0);  OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0);
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1, 0);  OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1, 0);
Line 6498  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_O Line 6969  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_O
 OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));  OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0);
   
   if (mode == JIT_PARTIAL_SOFT_COMPILE)
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0);
   
 /* Main part of the matching */  /* Main part of the matching */
 if ((re->options & PCRE_ANCHORED) == 0)  if ((re->options & PCRE_ANCHORED) == 0)
   {    {
   mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0);    mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0);
   /* Forward search if possible. */    /* Forward search if possible. */
  if ((re->flags & PCRE_FIRSTSET) != 0)  if ((re->options & PCRE_NO_START_OPTIMIZE) == 0)
    fast_forward_first_char(common, re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0);    {
  else if ((re->flags & PCRE_STARTLINE) != 0)    if ((re->flags & PCRE_FIRSTSET) != 0)
    fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0);      fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0);
  else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)    else if ((re->flags & PCRE_STARTLINE) != 0)
    fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);      fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0);
     else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
       fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);
     }
   }    }
if ((re->flags & PCRE_REQCHSET) != 0)if (common->req_char_ptr != 0)
  reqbyte_notfound = search_requested_char(common, re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0);  reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0);
   
 /* Store the current STR_PTR in OVECTOR(0). */  /* Store the current STR_PTR in OVECTOR(0). */
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
 /* Copy the limit of allowed recursions. */  /* Copy the limit of allowed recursions. */
 OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT);  OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT);
   if (common->mark_ptr != 0)
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0);
   /* Copy the beginning of the string. */
   if (mode == JIT_PARTIAL_SOFT_COMPILE)
     {
     jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
     JUMPHERE(jump);
     }
   else if (mode == JIT_PARTIAL_HARD_COMPILE)
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
   
compile_hotpath(common, rootfallback.cc, ccend, &rootfallback);compile_trypath(common, rootbacktrack.cc, ccend, &rootbacktrack);
 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
   {    {
   sljit_free_compiler(compiler);    sljit_free_compiler(compiler);
Line 6535  if (common->accept != NULL) Line 7023  if (common->accept != NULL)
   
 /* This means we have a match. Update the ovector. */  /* This means we have a match. Update the ovector. */
 copy_ovector(common, re->top_bracket + 1);  copy_ovector(common, re->top_bracket + 1);
leave = LABEL();common->leavelabel = LABEL();
 if (common->leave != NULL)
   set_jumps(common->leave, common->leavelabel);
 sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);  sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);
   
empty_match_fallback = LABEL();if (mode != JIT_COMPILE)
compile_fallbackpath(common, rootfallback.top);  {
   common->partialmatchlabel = LABEL();
   set_jumps(common->partialmatch, common->partialmatchlabel);
   return_with_partial_match(common, common->leavelabel);
   }
 
 empty_match_backtrack = LABEL();
 compile_backtrackpath(common, rootbacktrack.top);
 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
   {    {
   sljit_free_compiler(compiler);    sljit_free_compiler(compiler);
Line 6547  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)) Line 7044  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))
   return;    return;
   }    }
   
SLJIT_ASSERT(rootfallback.prev == NULL);SLJIT_ASSERT(rootbacktrack.prev == NULL);
   
   if (mode == JIT_PARTIAL_SOFT_COMPILE)
     {
     /* Update hit_start only in the first time. */
     jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, TMP1, 0);
     JUMPHERE(jump);
     }
   
 /* Check we have remaining characters. */  /* Check we have remaining characters. */
 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
   
Line 6556  if ((re->options & PCRE_ANCHORED) == 0) Line 7063  if ((re->options & PCRE_ANCHORED) == 0)
   {    {
   if ((re->options & PCRE_FIRSTLINE) == 0)    if ((re->options & PCRE_FIRSTLINE) == 0)
     {      {
    if (study != NULL && study->minlength > 1)    if (mode == JIT_COMPILE && study != NULL && study->minlength > 1 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
       {        {
      OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength));      OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength + 1));
       CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop);        CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop);
       }        }
     else      else
Line 6566  if ((re->options & PCRE_ANCHORED) == 0) Line 7073  if ((re->options & PCRE_ANCHORED) == 0)
     }      }
   else    else
     {      {
    if (study != NULL && study->minlength > 1)    SLJIT_ASSERT(common->first_line_end != 0);
     if (mode == JIT_COMPILE && study != NULL && study->minlength > 1 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
       {        {
      OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength));      OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength + 1));
       OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);        OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
       COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER);        COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER);
      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
       COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_GREATER_EQUAL);        COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_GREATER_EQUAL);
       JUMPTO(SLJIT_C_ZERO, mainloop);        JUMPTO(SLJIT_C_ZERO, mainloop);
       }        }
     else      else
      CMPTO(SLJIT_C_LESS, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, mainloop);      CMPTO(SLJIT_C_LESS, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, mainloop);
     }      }
   }    }
   
   /* No more remaining characters. */
 if (reqbyte_notfound != NULL)  if (reqbyte_notfound != NULL)
   JUMPHERE(reqbyte_notfound);    JUMPHERE(reqbyte_notfound);
/* Copy OVECTOR(1) to OVECTOR(0) */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));if (mode == JIT_PARTIAL_SOFT_COMPILE)
   CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0, common->partialmatchlabel);
 
 OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);  OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
JUMPTO(SLJIT_JUMP, leave);JUMPTO(SLJIT_JUMP, common->leavelabel);
   
 flush_stubs(common);  flush_stubs(common);
   
 JUMPHERE(empty_match);  JUMPHERE(empty_match);
 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_fallback);CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack);
 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
 CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found);  CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found);
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
 CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found);  CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found);
JUMPTO(SLJIT_JUMP, empty_match_fallback);JUMPTO(SLJIT_JUMP, empty_match_backtrack);
   
 common->currententry = common->entries;  common->currententry = common->entries;
 while (common->currententry != NULL)  while (common->currententry != NULL)
Line 6618  while (common->currententry != NULL) Line 7129  while (common->currententry != NULL)
 /* This is a (really) rare case. */  /* This is a (really) rare case. */
 set_jumps(common->stackalloc, LABEL());  set_jumps(common->stackalloc, LABEL());
 /* RETURN_ADDR is not a saved register. */  /* RETURN_ADDR is not a saved register. */
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize);sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
Line 6626  OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct Line 7137  OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct
 OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);  OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
   
 sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));  sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
alloc_error = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top));  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top));
Line 6635  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG),  Line 7146  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), 
 sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);  sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
   
 /* Allocation failed. */  /* Allocation failed. */
JUMPHERE(alloc_error);JUMPHERE(jump);
 /* We break the return address cache here, but this is a really rare case. */  /* We break the return address cache here, but this is a really rare case. */
 OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);  OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);
JUMPTO(SLJIT_JUMP, leave);JUMPTO(SLJIT_JUMP, common->leavelabel);
   
 /* Call limit reached. */  /* Call limit reached. */
 set_jumps(common->calllimit, LABEL());  set_jumps(common->calllimit, LABEL());
 OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);  OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
JUMPTO(SLJIT_JUMP, leave);JUMPTO(SLJIT_JUMP, common->leavelabel);
   
 if (common->revertframes != NULL)  if (common->revertframes != NULL)
   {    {
Line 6709  sljit_free_compiler(compiler); Line 7220  sljit_free_compiler(compiler);
 if (executable_func == NULL)  if (executable_func == NULL)
   return;    return;
   
function = SLJIT_MALLOC(sizeof(executable_function));/* Reuse the function descriptor if possible. */
if (function == NULL)if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL)
   functions = (executable_functions *)extra->executable_jit;
 else
   {    {
  /* This case is highly unlikely since we just recently  functions = SLJIT_MALLOC(sizeof(executable_functions));
  freed a lot of memory. Although not impossible. */  if (functions == NULL)
  sljit_free_code(executable_func);    {
  return;    /* This case is highly unlikely since we just recently
     freed a lot of memory. Although not impossible. */
     sljit_free_code(executable_func);
     return;
     }
   memset(functions, 0, sizeof(executable_functions));
   extra->executable_jit = functions;
   extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;
   }    }
   
function->executable_func = executable_func;functions->executable_funcs[mode] = executable_func;
function->executable_size = executable_size;functions->executable_sizes[mode] = executable_size;
function->callback = NULL; 
function->userdata = NULL; 
extra->executable_jit = function; 
extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT; 
 }  }
   
static int jit_machine_stack_exec(jit_arguments *arguments, executable_function *function)static int jit_machine_stack_exec(jit_arguments *arguments, void* executable_func)
 {  {
 union {  union {
    void* executable_func;     void* executable_func;
Line 6740  local_stack.base = local_stack.top; Line 7256  local_stack.base = local_stack.top;
 local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE;  local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE;
 local_stack.max_limit = local_stack.limit;  local_stack.max_limit = local_stack.limit;
 arguments->stack = &local_stack;  arguments->stack = &local_stack;
convert_executable_func.executable_func = function->executable_func;convert_executable_func.executable_func = executable_func;
 return convert_executable_func.call_executable_func(arguments);  return convert_executable_func.call_executable_func(arguments);
 }  }
   
 int  int
PRIV(jit_exec)(const REAL_PCRE *re, void *executable_func,PRIV(jit_exec)(const REAL_PCRE *re, const PUBL(extra) *extra_data, const pcre_uchar *subject,
  const pcre_uchar *subject, int length, int start_offset, int options,  int length, int start_offset, int options, int *offsets, int offsetcount)
  int match_limit, int *offsets, int offsetcount) 
 {  {
executable_function *function = (executable_function*)executable_func;executable_functions *functions = (executable_functions *)extra_data->executable_jit;
 union {  union {
    void* executable_func;     void* executable_func;
    jit_function call_executable_func;     jit_function call_executable_func;
Line 6757  union { Line 7272  union {
 jit_arguments arguments;  jit_arguments arguments;
 int maxoffsetcount;  int maxoffsetcount;
 int retval;  int retval;
   int mode = JIT_COMPILE;
   
   if ((options & PCRE_PARTIAL_HARD) != 0)
     mode = JIT_PARTIAL_HARD_COMPILE;
   else if ((options & PCRE_PARTIAL_SOFT) != 0)
     mode = JIT_PARTIAL_SOFT_COMPILE;
   
   if (functions->executable_funcs[mode] == NULL)
     return PCRE_ERROR_NULL;
   
 /* Sanity checks should be handled by pcre_exec. */  /* Sanity checks should be handled by pcre_exec. */
 arguments.stack = NULL;  arguments.stack = NULL;
 arguments.str = subject + start_offset;  arguments.str = subject + start_offset;
 arguments.begin = subject;  arguments.begin = subject;
 arguments.end = subject + length;  arguments.end = subject + length;
arguments.calllimit = match_limit; /* JIT decreases this value less times. */arguments.mark_ptr = NULL;
 /* JIT decreases this value less frequently than the interpreter. */
 arguments.calllimit = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : extra_data->match_limit;
 arguments.notbol = (options & PCRE_NOTBOL) != 0;  arguments.notbol = (options & PCRE_NOTBOL) != 0;
 arguments.noteol = (options & PCRE_NOTEOL) != 0;  arguments.noteol = (options & PCRE_NOTEOL) != 0;
 arguments.notempty = (options & PCRE_NOTEMPTY) != 0;  arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
Line 6783  if (offsetcount > maxoffsetcount) Line 7309  if (offsetcount > maxoffsetcount)
   offsetcount = maxoffsetcount;    offsetcount = maxoffsetcount;
 arguments.offsetcount = offsetcount;  arguments.offsetcount = offsetcount;
   
if (function->callback)if (functions->callback)
  arguments.stack = (struct sljit_stack*)function->callback(function->userdata);  arguments.stack = (struct sljit_stack *)functions->callback(functions->userdata);
 else  else
  arguments.stack = (struct sljit_stack*)function->userdata;  arguments.stack = (struct sljit_stack *)functions->userdata;
   
 if (arguments.stack == NULL)  if (arguments.stack == NULL)
  retval = jit_machine_stack_exec(&arguments, function);  retval = jit_machine_stack_exec(&arguments, functions->executable_funcs[mode]);
 else  else
   {    {
  convert_executable_func.executable_func = function->executable_func;  convert_executable_func.executable_func = functions->executable_funcs[mode];
   retval = convert_executable_func.call_executable_func(&arguments);    retval = convert_executable_func.call_executable_func(&arguments);
   }    }
   
 if (retval * 2 > offsetcount)  if (retval * 2 > offsetcount)
   retval = 0;    retval = 0;
   if ((extra_data->flags & PCRE_EXTRA_MARK) != 0)
     *(extra_data->mark) = arguments.mark_ptr;
   
 return retval;  return retval;
 }  }
   
 void  void
PRIV(jit_free)(void *executable_func)PRIV(jit_free)(void *executable_funcs)
 {  {
executable_function *function = (executable_function*)executable_func;int i;
sljit_free_code(function->executable_func);executable_functions *functions = (executable_functions *)executable_funcs;
SLJIT_FREE(function);for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
   {
   if (functions->executable_funcs[i] != NULL)
     sljit_free_code(functions->executable_funcs[i]);
   }
 SLJIT_FREE(functions);
 }  }
   
 int  int
PRIV(jit_get_size)(void *executable_func)PRIV(jit_get_size)(void *executable_funcs)
 {  {
return ((executable_function*)executable_func)->executable_size;int i;
 sljit_uw size = 0;
 sljit_uw *executable_sizes = ((executable_functions *)executable_funcs)->executable_sizes;
 for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
   size += executable_sizes[i];
 return (int)size;
 }  }
   
 const char*  const char*
Line 6846  PCRE_EXP_DECL void Line 7385  PCRE_EXP_DECL void
 pcre16_jit_stack_free(pcre16_jit_stack *stack)  pcre16_jit_stack_free(pcre16_jit_stack *stack)
 #endif  #endif
 {  {
sljit_free_stack((struct sljit_stack*)stack);sljit_free_stack((struct sljit_stack *)stack);
 }  }
   
 #ifdef COMPILE_PCRE8  #ifdef COMPILE_PCRE8
Line 6857  PCRE_EXP_DECL void Line 7396  PCRE_EXP_DECL void
 pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)  pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
 #endif  #endif
 {  {
executable_function *function;executable_functions *functions;
 if (extra != NULL &&  if (extra != NULL &&
     (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&      (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
     extra->executable_jit != NULL)      extra->executable_jit != NULL)
   {    {
  function = (executable_function*)extra->executable_jit;  functions = (executable_functions *)extra->executable_jit;
  function->callback = callback;  functions->callback = callback;
  function->userdata = userdata;  functions->userdata = userdata;
   }    }
 }  }
   

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>