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

Diff of /code/trunk/pcre_jit_compile.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1308 by zherczeg, Tue Apr 2 06:58:55 2013 UTC revision 1377 by zherczeg, Sun Oct 13 20:44:30 2013 UTC
# Line 168  typedef struct jit_arguments { Line 168  typedef struct jit_arguments {
168    pcre_uchar *mark_ptr;    pcre_uchar *mark_ptr;
169    void *callout_data;    void *callout_data;
170    /* Everything else after. */    /* Everything else after. */
171      pcre_uint32 limit_match;
172    int real_offset_count;    int real_offset_count;
173    int offset_count;    int offset_count;
   int call_limit;  
174    pcre_uint8 notbol;    pcre_uint8 notbol;
175    pcre_uint8 noteol;    pcre_uint8 noteol;
176    pcre_uint8 notempty;    pcre_uint8 notempty;
# Line 182  typedef struct executable_functions { Line 182  typedef struct executable_functions {
182    PUBL(jit_callback) callback;    PUBL(jit_callback) callback;
183    void *userdata;    void *userdata;
184    pcre_uint32 top_bracket;    pcre_uint32 top_bracket;
185      pcre_uint32 limit_match;
186    sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];    sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];
187  } executable_functions;  } executable_functions;
188    
# Line 210  typedef int (SLJIT_CALL *jit_function)(j Line 211  typedef int (SLJIT_CALL *jit_function)(j
211    
212  /* The following structure is the key data type for the recursive  /* The following structure is the key data type for the recursive
213  code generator. It is allocated by compile_matchingpath, and contains  code generator. It is allocated by compile_matchingpath, and contains
214  the aguments for compile_backtrackingpath. Must be the first member  the arguments for compile_backtrackingpath. Must be the first member
215  of its descendants. */  of its descendants. */
216  typedef struct backtrack_common {  typedef struct backtrack_common {
217    /* Concatenation stack. */    /* Concatenation stack. */
# Line 370  typedef struct compiler_common { Line 371  typedef struct compiler_common {
371    sljit_sw ctypes;    sljit_sw ctypes;
372    int digits[2 + MAX_RANGE_SIZE];    int digits[2 + MAX_RANGE_SIZE];
373    /* Named capturing brackets. */    /* Named capturing brackets. */
374    sljit_uw name_table;    pcre_uchar *name_table;
375    sljit_sw name_count;    sljit_sw name_count;
376    sljit_sw name_entry_size;    sljit_sw name_entry_size;
377    
# Line 463  typedef struct compare_context { Line 464  typedef struct compare_context {
464  #define STACK_TOP     SLJIT_SCRATCH_REG2  #define STACK_TOP     SLJIT_SCRATCH_REG2
465  #define STACK_LIMIT   SLJIT_SAVED_REG3  #define STACK_LIMIT   SLJIT_SAVED_REG3
466  #define ARGUMENTS     SLJIT_SAVED_EREG1  #define ARGUMENTS     SLJIT_SAVED_EREG1
467  #define CALL_COUNT    SLJIT_SAVED_EREG2  #define COUNT_MATCH   SLJIT_SAVED_EREG2
468  #define RETURN_ADDR   SLJIT_TEMPORARY_EREG1  #define RETURN_ADDR   SLJIT_TEMPORARY_EREG1
469    
470  /* Local space layout. */  /* Local space layout. */
# Line 474  typedef struct compare_context { Line 475  typedef struct compare_context {
475  #define POSSESSIVE0      (2 * sizeof(sljit_sw))  #define POSSESSIVE0      (2 * sizeof(sljit_sw))
476  #define POSSESSIVE1      (3 * sizeof(sljit_sw))  #define POSSESSIVE1      (3 * sizeof(sljit_sw))
477  /* Max limit of recursions. */  /* Max limit of recursions. */
478  #define CALL_LIMIT       (4 * sizeof(sljit_sw))  #define LIMIT_MATCH      (4 * sizeof(sljit_sw))
479  /* The output vector is stored on the stack, and contains pointers  /* The output vector is stored on the stack, and contains pointers
480  to characters. The vector data is divided into two groups: the first  to characters. The vector data is divided into two groups: the first
481  group contains the start / end character pointers, and the second is  group contains the start / end character pointers, and the second is
482  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. */
483  #define OVECTOR_START    (common->ovector_start)  #define OVECTOR_START    (common->ovector_start)
484  #define OVECTOR(i)       (OVECTOR_START + (i) * sizeof(sljit_sw))  #define OVECTOR(i)       (OVECTOR_START + (i) * (sljit_sw)sizeof(sljit_sw))
485  #define OVECTOR_PRIV(i)  (common->cbra_ptr + (i) * sizeof(sljit_sw))  #define OVECTOR_PRIV(i)  (common->cbra_ptr + (i) * (sljit_sw)sizeof(sljit_sw))
486  #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start])  #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start])
487    
488  #if defined COMPILE_PCRE8  #if defined COMPILE_PCRE8
# Line 588  switch(*cc) Line 589  switch(*cc)
589    case OP_NCLASS:    case OP_NCLASS:
590    case OP_REF:    case OP_REF:
591    case OP_REFI:    case OP_REFI:
592      case OP_DNREF:
593      case OP_DNREFI:
594    case OP_RECURSE:    case OP_RECURSE:
595    case OP_CALLOUT:    case OP_CALLOUT:
596    case OP_ALT:    case OP_ALT:
# Line 613  switch(*cc) Line 616  switch(*cc)
616    case OP_SCBRAPOS:    case OP_SCBRAPOS:
617    case OP_SCOND:    case OP_SCOND:
618    case OP_CREF:    case OP_CREF:
619    case OP_NCREF:    case OP_DNCREF:
620    case OP_RREF:    case OP_RREF:
621    case OP_NRREF:    case OP_DNRREF:
622    case OP_DEF:    case OP_DEF:
623    case OP_BRAZERO:    case OP_BRAZERO:
624    case OP_BRAMINZERO:    case OP_BRAMINZERO:
# Line 735  switch(*cc) Line 738  switch(*cc)
738    
739  static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)  static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
740  {  {
741  pcre_uchar *name;  int count;
742  pcre_uchar *name2;  pcre_uchar *slot;
 int i, cbra_index;  
743    
744  /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */  /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
745  while (cc < ccend)  while (cc < ccend)
# Line 771  while (cc < ccend) Line 773  while (cc < ccend)
773      break;      break;
774    
775      case OP_CREF:      case OP_CREF:
776      i = GET2(cc, 1);      common->optimized_cbracket[GET2(cc, 1)] = 0;
     common->optimized_cbracket[i] = 0;  
777      cc += 1 + IMM2_SIZE;      cc += 1 + IMM2_SIZE;
778      break;      break;
779    
780      case OP_NCREF:      case OP_DNREF:
781      cbra_index = GET2(cc, 1);      case OP_DNREFI:
782      name = (pcre_uchar *)common->name_table;      case OP_DNCREF:
783      name2 = name;      count = GET2(cc, 1 + IMM2_SIZE);
784      for (i = 0; i < common->name_count; i++)      slot = common->name_table + GET2(cc, 1) * common->name_entry_size;
785        {      while (count-- > 0)
786        if (GET2(name, 0) == cbra_index) break;        {
787        name += common->name_entry_size;        common->optimized_cbracket[GET2(slot, 0)] = 0;
788        }        slot += common->name_entry_size;
     SLJIT_ASSERT(i != common->name_count);  
   
     for (i = 0; i < common->name_count; i++)  
       {  
       if (STRCMP_UC_UC(name2 + IMM2_SIZE, name + IMM2_SIZE) == 0)  
         common->optimized_cbracket[GET2(name2, 0)] = 0;  
       name2 += common->name_entry_size;  
789        }        }
790      cc += 1 + IMM2_SIZE;      cc += 1 + 2 * IMM2_SIZE;
791      break;      break;
792    
793      case OP_RECURSE:      case OP_RECURSE:
# Line 892  pcre_uchar *next; Line 886  pcre_uchar *next;
886  pcre_uchar *next_end;  pcre_uchar *next_end;
887  pcre_uchar *max_end;  pcre_uchar *max_end;
888  pcre_uchar type;  pcre_uchar type;
889  sljit_uw length = end - begin;  sljit_sw length = end - begin;
890  int min, max, i;  int min, max, i;
891    
892  /* Detect fixed iterations first. */  /* Detect fixed iterations first. */
# Line 2021  while (list_item) Line 2015  while (list_item)
2015  common->stubs = NULL;  common->stubs = NULL;
2016  }  }
2017    
2018  static SLJIT_INLINE void decrease_call_count(compiler_common *common)  static SLJIT_INLINE void count_match(compiler_common *common)
2019  {  {
2020  DEFINE_COMPILER;  DEFINE_COMPILER;
2021    
2022  OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 0, SLJIT_IMM, 1);  OP2(SLJIT_SUB | SLJIT_SET_E, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);
2023  add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));  add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));
2024  }  }
2025    
# Line 2372  return (bit < 256) ? ((0 << 8) | bit) : Line 2366  return (bit < 256) ? ((0 << 8) | bit) :
2366    
2367  static void check_partial(compiler_common *common, BOOL force)  static void check_partial(compiler_common *common, BOOL force)
2368  {  {
2369  /* Checks whether a partial matching is occured. Does not modify registers. */  /* Checks whether a partial matching is occurred. Does not modify registers. */
2370  DEFINE_COMPILER;  DEFINE_COMPILER;
2371  struct sljit_jump *jump = NULL;  struct sljit_jump *jump = NULL;
2372    
# Line 4315  while (*cc != XCL_END) Line 4309  while (*cc != XCL_END)
4309    
4310        case PT_SPACE:        case PT_SPACE:
4311        case PT_PXSPACE:        case PT_PXSPACE:
       if (*cc == PT_SPACE)  
         {  
         OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);  
         jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 11 - charoffset);  
         }  
4312        SET_CHAR_OFFSET(9);        SET_CHAR_OFFSET(9);
4313        OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9);        OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9);
4314        OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL);        OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL);
4315        if (*cc == PT_SPACE)  
4316          JUMPHERE(jump);        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);
4317          OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
4318    
4319          OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);
4320          OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
4321    
4322        SET_TYPE_OFFSET(ucp_Zl);        SET_TYPE_OFFSET(ucp_Zl);
4323        OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);        OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
# Line 5054  if (context.length > 0) Line 5047  if (context.length > 0)
5047  return compile_char1_matchingpath(common, *cc, cc + 1, backtracks);  return compile_char1_matchingpath(common, *cc, cc + 1, backtracks);
5048  }  }
5049    
 static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)  
 {  
 DEFINE_COMPILER;  
 int offset = GET2(cc, 1) << 1;  
   
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));  
 if (!common->jscript_compat)  
   {  
   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));  
     OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);  
     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));  
     OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);  
     return JUMP(SLJIT_C_NOT_ZERO);  
     }  
   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));  
 }  
   
5050  /* Forward definitions. */  /* Forward definitions. */
5051  static void compile_matchingpath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *);  static void compile_matchingpath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *);
5052  static void compile_backtrackingpath(compiler_common *, struct backtrack_common *);  static void compile_backtrackingpath(compiler_common *, struct backtrack_common *);
# Line 5108  static void compile_backtrackingpath(com Line 5079  static void compile_backtrackingpath(com
5079    
5080  #define BACKTRACK_AS(type) ((type *)backtrack)  #define BACKTRACK_AS(type) ((type *)backtrack)
5081    
5082  static pcre_uchar *compile_ref_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)  static void compile_dnref_search(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
5083    {
5084    /* The OVECTOR offset goes to TMP2. */
5085    DEFINE_COMPILER;
5086    int count = GET2(cc, 1 + IMM2_SIZE);
5087    pcre_uchar *slot = common->name_table + GET2(cc, 1) * common->name_entry_size;
5088    unsigned int offset;
5089    jump_list *found = NULL;
5090    
5091    SLJIT_ASSERT(*cc == OP_DNREF || *cc == OP_DNREFI);
5092    
5093    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
5094    
5095    count--;
5096    while (count-- > 0)
5097      {
5098      offset = GET2(slot, 0) << 1;
5099      GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));
5100      add_jump(compiler, &found, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0));
5101      slot += common->name_entry_size;
5102      }
5103    
5104    offset = GET2(slot, 0) << 1;
5105    GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));
5106    if (backtracks != NULL && !common->jscript_compat)
5107      add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0));
5108    
5109    set_jumps(found, LABEL());
5110    }
5111    
5112    static void compile_ref_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)
5113  {  {
5114  DEFINE_COMPILER;  DEFINE_COMPILER;
5115  int offset = GET2(cc, 1) << 1;  BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
5116    int offset = 0;
5117  struct sljit_jump *jump = NULL;  struct sljit_jump *jump = NULL;
5118  struct sljit_jump *partial;  struct sljit_jump *partial;
5119  struct sljit_jump *nopartial;  struct sljit_jump *nopartial;
5120    
5121  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));  if (ref)
5122  /* OVECTOR(1) contains the "string begin - 1" constant. */    {
5123  if (withchecks && !common->jscript_compat)    offset = GET2(cc, 1) << 1;
5124    add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
5125      /* OVECTOR(1) contains the "string begin - 1" constant. */
5126      if (withchecks && !common->jscript_compat)
5127        add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
5128      }
5129    else
5130      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
5131    
5132  #if defined SUPPORT_UTF && defined SUPPORT_UCP  #if defined SUPPORT_UTF && defined SUPPORT_UCP
5133  if (common->utf && *cc == OP_REFI)  if (common->utf && *cc == OP_REFI)
5134    {    {
5135    SLJIT_ASSERT(TMP1 == SLJIT_SCRATCH_REG1 && STACK_TOP == SLJIT_SCRATCH_REG2 && TMP2 == SLJIT_SCRATCH_REG3);    SLJIT_ASSERT(TMP1 == SLJIT_SCRATCH_REG1 && STACK_TOP == SLJIT_SCRATCH_REG2 && TMP2 == SLJIT_SCRATCH_REG3);
5136    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));    if (ref)
5137        OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
5138      else
5139        OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
5140    
5141    if (withchecks)    if (withchecks)
5142      jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0);      jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0);
5143    
# Line 5150  if (common->utf && *cc == OP_REFI) Line 5162  if (common->utf && *cc == OP_REFI)
5162  else  else
5163  #endif /* SUPPORT_UTF && SUPPORT_UCP */  #endif /* SUPPORT_UTF && SUPPORT_UCP */
5164    {    {
5165    OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);    if (ref)
5166        OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
5167      else
5168        OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
5169    
5170    if (withchecks)    if (withchecks)
5171      jump = JUMP(SLJIT_C_ZERO);      jump = JUMP(SLJIT_C_ZERO);
5172    
# Line 5187  if (jump != NULL) Line 5203  if (jump != NULL)
5203    else    else
5204      JUMPHERE(jump);      JUMPHERE(jump);
5205    }    }
 return cc + 1 + IMM2_SIZE;  
5206  }  }
5207    
5208  static SLJIT_INLINE pcre_uchar *compile_ref_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)  static SLJIT_INLINE pcre_uchar *compile_ref_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
5209  {  {
5210  DEFINE_COMPILER;  DEFINE_COMPILER;
5211    BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
5212  backtrack_common *backtrack;  backtrack_common *backtrack;
5213  pcre_uchar type;  pcre_uchar type;
5214    int offset = 0;
5215  struct sljit_label *label;  struct sljit_label *label;
5216  struct sljit_jump *zerolength;  struct sljit_jump *zerolength;
5217  struct sljit_jump *jump = NULL;  struct sljit_jump *jump = NULL;
# Line 5204  BOOL minimize; Line 5221  BOOL minimize;
5221    
5222  PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);  PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);
5223    
5224    if (ref)
5225      offset = GET2(cc, 1) << 1;
5226    else
5227      cc += IMM2_SIZE;
5228  type = cc[1 + IMM2_SIZE];  type = cc[1 + IMM2_SIZE];
5229    
5230    SLJIT_COMPILE_ASSERT((OP_CRSTAR & 0x1) == 0, crstar_opcode_must_be_even);
5231  minimize = (type & 0x1) != 0;  minimize = (type & 0x1) != 0;
5232  switch(type)  switch(type)
5233    {    {
# Line 5242  if (!minimize) Line 5265  if (!minimize)
5265    if (min == 0)    if (min == 0)
5266      {      {
5267      allocate_stack(common, 2);      allocate_stack(common, 2);
5268        if (ref)
5269          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
5270      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5271      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
5272      /* Temporary release of STR_PTR. */      /* Temporary release of STR_PTR. */
5273      OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));      OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
5274      zerolength = compile_ref_checks(common, ccbegin, NULL);      /* Handles both invalid and empty cases. Since the minimum repeat,
5275        is zero the invalid case is basically the same as an empty case. */
5276        if (ref)
5277          zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
5278        else
5279          {
5280          compile_dnref_search(common, ccbegin, NULL);
5281          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
5282          OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, TMP2, 0);
5283          zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
5284          }
5285      /* Restore if not zero length. */      /* Restore if not zero length. */
5286      OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));      OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
5287      }      }
5288    else    else
5289      {      {
5290      allocate_stack(common, 1);      allocate_stack(common, 1);
5291        if (ref)
5292          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
5293      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5294      zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks);      if (ref)
5295          {
5296          add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
5297          zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
5298          }
5299        else
5300          {
5301          compile_dnref_search(common, ccbegin, &backtrack->topbacktracks);
5302          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
5303          OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, TMP2, 0);
5304          zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
5305          }
5306      }      }
5307    
5308    if (min > 1 || max > 1)    if (min > 1 || max > 1)
5309      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
5310    
5311    label = LABEL();    label = LABEL();
5312      if (!ref)
5313        OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
5314    compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE);    compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE);
5315    
5316    if (min > 1 || max > 1)    if (min > 1 || max > 1)
# Line 5291  if (!minimize) Line 5341  if (!minimize)
5341    JUMPHERE(zerolength);    JUMPHERE(zerolength);
5342    BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();    BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
5343    
5344    decrease_call_count(common);    count_match(common);
5345    return cc;    return cc;
5346    }    }
5347    
5348  allocate_stack(common, 2);  allocate_stack(common, ref ? 2 : 3);
5349    if (ref)
5350      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
5351  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5352  if (type != OP_CRMINSTAR)  if (type != OP_CRMINSTAR)
5353    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
5354    
5355  if (min == 0)  if (min == 0)
5356    {    {
5357    zerolength = compile_ref_checks(common, ccbegin, NULL);    /* Handles both invalid and empty cases. Since the minimum repeat,
5358      is zero the invalid case is basically the same as an empty case. */
5359      if (ref)
5360        zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
5361      else
5362        {
5363        compile_dnref_search(common, ccbegin, NULL);
5364        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
5365        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);
5366        zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
5367        }
5368      /* Length is non-zero, we can match real repeats. */
5369    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5370    jump = JUMP(SLJIT_JUMP);    jump = JUMP(SLJIT_JUMP);
5371    }    }
5372  else  else
5373    zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks);    {
5374      if (ref)
5375        {
5376        add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
5377        zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
5378        }
5379      else
5380        {
5381        compile_dnref_search(common, ccbegin, &backtrack->topbacktracks);
5382        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
5383        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);
5384        zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
5385        }
5386      }
5387    
5388  BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();  BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
5389  if (max > 0)  if (max > 0)
5390    add_jump(compiler, &backtrack->topbacktracks, 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));
5391    
5392    if (!ref)
5393      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
5394  compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE);  compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE);
5395  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5396    
# Line 5330  if (jump != NULL) Line 5408  if (jump != NULL)
5408    JUMPHERE(jump);    JUMPHERE(jump);
5409  JUMPHERE(zerolength);  JUMPHERE(zerolength);
5410    
5411  decrease_call_count(common);  count_match(common);
5412  return cc;  return cc;
5413  }  }
5414    
# Line 5900  common->accept = save_accept; Line 5978  common->accept = save_accept;
5978  return cc + 1 + LINK_SIZE;  return cc + 1 + LINK_SIZE;
5979  }  }
5980    
 static sljit_sw SLJIT_CALL do_searchovector(sljit_uw refno, sljit_sw* locals, pcre_uchar *name_table)  
 {  
 int condition = FALSE;  
 pcre_uchar *slotA = name_table;  
 pcre_uchar *slotB;  
 sljit_sw name_count = locals[LOCALS0 / sizeof(sljit_sw)];  
 sljit_sw name_entry_size = locals[LOCALS1 / sizeof(sljit_sw)];  
 sljit_sw no_capture;  
 int i;  
   
 locals += refno & 0xff;  
 refno >>= 8;  
 no_capture = locals[1];  
   
 for (i = 0; i < name_count; i++)  
   {  
   if (GET2(slotA, 0) == refno) break;  
   slotA += name_entry_size;  
   }  
   
 if (i < name_count)  
   {  
   /* Found a name for the number - there can be only one; duplicate names  
   for different numbers are allowed, but not vice versa. First scan down  
   for duplicates. */  
   
   slotB = slotA;  
   while (slotB > name_table)  
     {  
     slotB -= name_entry_size;  
     if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)  
       {  
       condition = locals[GET2(slotB, 0) << 1] != no_capture;  
       if (condition) break;  
       }  
     else break;  
     }  
   
   /* Scan up for duplicates */  
   if (!condition)  
     {  
     slotB = slotA;  
     for (i++; i < name_count; i++)  
       {  
       slotB += name_entry_size;  
       if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)  
         {  
         condition = locals[GET2(slotB, 0) << 1] != no_capture;  
         if (condition) break;  
         }  
       else break;  
       }  
     }  
   }  
 return condition;  
 }  
   
 static sljit_sw SLJIT_CALL do_searchgroups(sljit_uw recno, sljit_uw* locals, pcre_uchar *name_table)  
 {  
 int condition = FALSE;  
 pcre_uchar *slotA = name_table;  
 pcre_uchar *slotB;  
 sljit_uw name_count = locals[LOCALS0 / sizeof(sljit_sw)];  
 sljit_uw name_entry_size = locals[LOCALS1 / sizeof(sljit_sw)];  
 sljit_uw group_num = locals[POSSESSIVE0 / sizeof(sljit_sw)];  
 sljit_uw i;  
   
 for (i = 0; i < name_count; i++)  
   {  
   if (GET2(slotA, 0) == recno) break;  
   slotA += name_entry_size;  
   }  
   
 if (i < name_count)  
   {  
   /* Found a name for the number - there can be only one; duplicate  
   names for different numbers are allowed, but not vice versa. First  
   scan down for duplicates. */  
   
   slotB = slotA;  
   while (slotB > name_table)  
     {  
     slotB -= name_entry_size;  
     if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)  
       {  
       condition = GET2(slotB, 0) == group_num;  
       if (condition) break;  
       }  
     else break;  
     }  
   
   /* Scan up for duplicates */  
   if (!condition)  
     {  
     slotB = slotA;  
     for (i++; i < name_count; i++)  
       {  
       slotB += name_entry_size;  
       if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)  
         {  
         condition = GET2(slotB, 0) == group_num;  
         if (condition) break;  
         }  
       else break;  
       }  
     }  
   }  
 return condition;  
 }  
   
5981  static SLJIT_INLINE void match_once_common(compiler_common *common, pcre_uchar ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head)  static SLJIT_INLINE void match_once_common(compiler_common *common, pcre_uchar ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head)
5982  {  {
5983  DEFINE_COMPILER;  DEFINE_COMPILER;
# Line 6142  backtrack_common *backtrack; Line 6110  backtrack_common *backtrack;
6110  pcre_uchar opcode;  pcre_uchar opcode;
6111  int private_data_ptr = 0;  int private_data_ptr = 0;
6112  int offset = 0;  int offset = 0;
6113  int stacksize;  int i, stacksize;
6114  int repeat_ptr = 0, repeat_length = 0;  int repeat_ptr = 0, repeat_length = 0;
6115  int repeat_type = 0, repeat_count = 0;  int repeat_type = 0, repeat_count = 0;
6116  pcre_uchar *ccbegin;  pcre_uchar *ccbegin;
6117  pcre_uchar *matchingpath;  pcre_uchar *matchingpath;
6118    pcre_uchar *slot;
6119  pcre_uchar bra = OP_BRA;  pcre_uchar bra = OP_BRA;
6120  pcre_uchar ket;  pcre_uchar ket;
6121  assert_backtrack *assert;  assert_backtrack *assert;
# Line 6196  SLJIT_ASSERT(!((bra == OP_BRAZERO && ket Line 6165  SLJIT_ASSERT(!((bra == OP_BRAZERO && ket
6165  cc += GET(cc, 1);  cc += GET(cc, 1);
6166    
6167  has_alternatives = *cc == OP_ALT;  has_alternatives = *cc == OP_ALT;
6168  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))  if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND))
6169    {    has_alternatives = (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF) ? FALSE : TRUE;
   has_alternatives = (*matchingpath == OP_RREF) ? FALSE : TRUE;  
   if (*matchingpath == OP_NRREF)  
     {  
     stacksize = GET2(matchingpath, 1);  
     if (common->currententry == NULL || stacksize == RREF_ANY)  
       has_alternatives = FALSE;  
     else if (common->currententry->start == 0)  
       has_alternatives = stacksize != 0;  
     else  
       has_alternatives = stacksize != (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);  
     }  
   }  
6170    
6171  if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))  if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
6172    opcode = OP_SCOND;    opcode = OP_SCOND;
# Line 6446  if (opcode == OP_COND || opcode == OP_SC Line 6403  if (opcode == OP_COND || opcode == OP_SC
6403        CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));        CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
6404      matchingpath += 1 + IMM2_SIZE;      matchingpath += 1 + IMM2_SIZE;
6405      }      }
6406    else if (*matchingpath == OP_NCREF)    else if (*matchingpath == OP_DNCREF)
6407      {      {
6408      SLJIT_ASSERT(has_alternatives);      SLJIT_ASSERT(has_alternatives);
     stacksize = GET2(matchingpath, 1);  
     jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));  
6409    
6410      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);      i = GET2(matchingpath, 1 + IMM2_SIZE);
6411      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);      slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;
6412      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);      OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
6413      OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, SLJIT_IMM, (stacksize << 8) | (common->ovector_start / sizeof(sljit_sw)));      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
6414      GET_LOCAL_BASE(SLJIT_SCRATCH_REG2, 0, 0);      OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
6415      OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, common->name_table);      slot += common->name_entry_size;
6416      sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector));      i--;
6417      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);      while (i-- > 0)
6418      add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG1, 0, SLJIT_IMM, 0));        {
6419          OP2(SLJIT_SUB, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
6420      JUMPHERE(jump);        OP2(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, STR_PTR, 0);
6421      matchingpath += 1 + IMM2_SIZE;        slot += common->name_entry_size;
6422          }
6423        OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
6424        add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_C_ZERO));
6425        matchingpath += 1 + 2 * IMM2_SIZE;
6426      }      }
6427    else if (*matchingpath == OP_RREF || *matchingpath == OP_NRREF)    else if (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF)
6428      {      {
6429      /* Never has other case. */      /* Never has other case. */
6430      BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;      BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;
6431        SLJIT_ASSERT(!has_alternatives);
6432    
6433      stacksize = GET2(matchingpath, 1);      if (*matchingpath == OP_RREF)
     if (common->currententry == NULL)  
       stacksize = 0;  
     else if (stacksize == RREF_ANY)  
       stacksize = 1;  
     else if (common->currententry->start == 0)  
       stacksize = stacksize == 0;  
     else  
       stacksize = stacksize == (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);  
   
     if (*matchingpath == OP_RREF || stacksize || common->currententry == NULL)  
6434        {        {
6435        SLJIT_ASSERT(!has_alternatives);        stacksize = GET2(matchingpath, 1);
6436          if (common->currententry == NULL)
6437            stacksize = 0;
6438          else if (stacksize == RREF_ANY)
6439            stacksize = 1;
6440          else if (common->currententry->start == 0)
6441            stacksize = stacksize == 0;
6442          else
6443            stacksize = stacksize == (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
6444    
6445        if (stacksize != 0)        if (stacksize != 0)
6446          matchingpath += 1 + IMM2_SIZE;          matchingpath += 1 + IMM2_SIZE;
6447          }
6448        else
6449          {
6450          if (common->currententry == NULL || common->currententry->start == 0)
6451            stacksize = 0;
6452        else        else
6453          {          {
6454            stacksize = GET2(matchingpath, 1 + IMM2_SIZE);
6455            slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;
6456            i = (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
6457            while (stacksize > 0)
6458              {
6459              if ((int)GET2(slot, 0) == i)
6460                break;
6461              slot += common->name_entry_size;
6462              stacksize--;
6463              }
6464            }
6465    
6466          if (stacksize != 0)
6467            matchingpath += 1 + 2 * IMM2_SIZE;
6468          }
6469    
6470          /* The stacksize == 0 is a common "else" case. */
6471          if (stacksize == 0)
6472            {
6473          if (*cc == OP_ALT)          if (*cc == OP_ALT)
6474            {            {
6475            matchingpath = cc + 1 + LINK_SIZE;            matchingpath = cc + 1 + LINK_SIZE;
# Line 6495  if (opcode == OP_COND || opcode == OP_SC Line 6478  if (opcode == OP_COND || opcode == OP_SC
6478          else          else
6479            matchingpath = cc;            matchingpath = cc;
6480          }          }
       }  
     else  
       {  
       SLJIT_ASSERT(has_alternatives);  
   
       stacksize = GET2(matchingpath, 1);  
       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), 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_SCRATCH_REG1, 0, SLJIT_IMM, stacksize);  
       GET_LOCAL_BASE(SLJIT_SCRATCH_REG2, 0, 0);  
       OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, common->name_table);  
       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);  
       add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG1, 0, SLJIT_IMM, 0));  
       matchingpath += 1 + IMM2_SIZE;  
       }  
6481      }      }
6482    else    else
6483      {      {
# Line 6663  if (bra == OP_BRAMINZERO) Line 6628  if (bra == OP_BRAMINZERO)
6628    }    }
6629    
6630  if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)  if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
6631    decrease_call_count(common);    count_match(common);
6632    
6633  /* Skip the other alternatives. */  /* Skip the other alternatives. */
6634  while (*cc == OP_ALT)  while (*cc == OP_ALT)
# Line 6950  if (!zero) Line 6915  if (!zero)
6915    
6916  /* None of them matched. */  /* None of them matched. */
6917  set_jumps(emptymatch, LABEL());  set_jumps(emptymatch, LABEL());
6918  decrease_call_count(common);  count_match(common);
6919  return cc + 1 + LINK_SIZE;  return cc + 1 + LINK_SIZE;
6920  }  }
6921    
# Line 7260  switch(opcode) Line 7225  switch(opcode)
7225    break;    break;
7226    }    }
7227    
7228  decrease_call_count(common);  count_match(common);
7229  return end;  return end;
7230  }  }
7231    
# Line 7552  while (cc < ccend) Line 7517  while (cc < ccend)
7517      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)
7518        cc = compile_ref_iterator_matchingpath(common, cc, parent);        cc = compile_ref_iterator_matchingpath(common, cc, parent);
7519      else      else
7520        cc = compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);        {
7521          compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);
7522          cc += 1 + IMM2_SIZE;
7523          }
7524        break;
7525    
7526        case OP_DNREF:
7527        case OP_DNREFI:
7528        if (cc[1 + 2 * IMM2_SIZE] >= OP_CRSTAR && cc[1 + 2 * IMM2_SIZE] <= OP_CRMINRANGE)
7529          cc = compile_ref_iterator_matchingpath(common, cc, parent);
7530        else
7531          {
7532          compile_dnref_search(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
7533          compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);
7534          cc += 1 + 2 * IMM2_SIZE;
7535          }
7536      break;      break;
7537    
7538      case OP_RECURSE:      case OP_RECURSE:
# Line 7587  while (cc < ccend) Line 7567  while (cc < ccend)
7567        }        }
7568      BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL();      BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL();
7569      if (cc[1] > OP_ASSERTBACK_NOT)      if (cc[1] > OP_ASSERTBACK_NOT)
7570        decrease_call_count(common);        count_match(common);
7571      break;      break;
7572    
7573      case OP_ONCE:      case OP_ONCE:
# Line 7846  static SLJIT_INLINE void compile_ref_ite Line 7826  static SLJIT_INLINE void compile_ref_ite
7826  {  {
7827  DEFINE_COMPILER;  DEFINE_COMPILER;
7828  pcre_uchar *cc = current->cc;  pcre_uchar *cc = current->cc;
7829    BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
7830  pcre_uchar type;  pcre_uchar type;
7831    
7832  type = cc[1 + IMM2_SIZE];  type = cc[ref ? 1 + IMM2_SIZE : 1 + 2 * IMM2_SIZE];
7833    
7834  if ((type & 0x1) == 0)  if ((type & 0x1) == 0)
7835    {    {
7836      /* Maximize case. */
7837    set_jumps(current->topbacktracks, LABEL());    set_jumps(current->topbacktracks, LABEL());
7838    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
7839    free_stack(common, 1);    free_stack(common, 1);
# Line 7861  if ((type & 0x1) == 0) Line 7844  if ((type & 0x1) == 0)
7844  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
7845  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);
7846  set_jumps(current->topbacktracks, LABEL());  set_jumps(current->topbacktracks, LABEL());
7847  free_stack(common, 2);  free_stack(common, ref ? 2 : 3);
7848  }  }
7849    
7850  static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current)  static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current)
# Line 8225  if (has_alternatives) Line 8208  if (has_alternatives)
8208          return;          return;
8209        }        }
8210    
8211      /* Instructions after the current alternative is succesfully matched. */      /* Instructions after the current alternative is successfully matched. */
8212      /* There is a similar code in compile_bracket_matchingpath. */      /* There is a similar code in compile_bracket_matchingpath. */
8213      if (opcode == OP_ONCE)      if (opcode == OP_ONCE)
8214        match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);        match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);
# Line 8662  while (current) Line 8645  while (current)
8645    
8646      case OP_REF:      case OP_REF:
8647      case OP_REFI:      case OP_REFI:
8648        case OP_DNREF:
8649        case OP_DNREFI:
8650      compile_ref_iterator_backtrackingpath(common, current);      compile_ref_iterator_backtrackingpath(common, current);
8651      break;      break;
8652    
# Line 8956  else Line 8941  else
8941  common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;  common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
8942  common->ctypes = (sljit_sw)(tables + ctypes_offset);  common->ctypes = (sljit_sw)(tables + ctypes_offset);
8943  common->digits[0] = -2;  common->digits[0] = -2;
8944  common->name_table = (sljit_sw)((pcre_uchar *)re + re->name_table_offset);  common->name_table = ((pcre_uchar *)re) + re->name_table_offset;
8945  common->name_count = re->name_count;  common->name_count = re->name_count;
8946  common->name_entry_size = re->name_entry_size;  common->name_entry_size = re->name_entry_size;
8947  common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;  common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
# Line 8970  common->use_ucp = (re->options & PCRE_UC Line 8955  common->use_ucp = (re->options & PCRE_UC
8955  ccend = bracketend(rootbacktrack.cc);  ccend = bracketend(rootbacktrack.cc);
8956    
8957  /* Calculate the local space size on the stack. */  /* Calculate the local space size on the stack. */
8958  common->ovector_start = CALL_LIMIT + sizeof(sljit_sw);  common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw);
8959  common->optimized_cbracket = (pcre_uint8 *)SLJIT_MALLOC(re->top_bracket + 1);  common->optimized_cbracket = (pcre_uint8 *)SLJIT_MALLOC(re->top_bracket + 1);
8960  if (!common->optimized_cbracket)  if (!common->optimized_cbracket)
8961    return;    return;
# Line 9102  OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1 Line 9087  OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1
9087  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
9088  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
9089  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
9090  OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, call_limit));  OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match));
9091  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
9092  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));
9093  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LIMIT_MATCH, TMP1, 0);
9094    
9095  if (mode == JIT_PARTIAL_SOFT_COMPILE)  if (mode == JIT_PARTIAL_SOFT_COMPILE)
9096    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
# Line 9147  if (common->req_char_ptr != 0) Line 9132  if (common->req_char_ptr != 0)
9132  /* Store the current STR_PTR in OVECTOR(0). */  /* Store the current STR_PTR in OVECTOR(0). */
9133  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);
9134  /* Copy the limit of allowed recursions. */  /* Copy the limit of allowed recursions. */
9135  OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT);  OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LIMIT_MATCH);
9136  if (common->capture_last_ptr != 0)  if (common->capture_last_ptr != 0)
9137    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, -1);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, -1);
9138    
# Line 9425  else Line 9410  else
9410      }      }
9411    memset(functions, 0, sizeof(executable_functions));    memset(functions, 0, sizeof(executable_functions));
9412    functions->top_bracket = (re->top_bracket + 1) * 2;    functions->top_bracket = (re->top_bracket + 1) * 2;
9413      functions->limit_match = (re->flags & PCRE_MLSET) != 0 ? re->limit_match : 0;
9414    extra->executable_jit = functions;    extra->executable_jit = functions;
9415    extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;    extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;
9416    }    }
# Line 9479  arguments.begin = subject; Line 9465  arguments.begin = subject;
9465  arguments.end = subject + length;  arguments.end = subject + length;
9466  arguments.mark_ptr = NULL;  arguments.mark_ptr = NULL;
9467  /* JIT decreases this value less frequently than the interpreter. */  /* JIT decreases this value less frequently than the interpreter. */
9468  arguments.call_limit = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : extra_data->match_limit;  arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (pcre_uint32)(extra_data->match_limit);
9469    if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match)
9470      arguments.limit_match = functions->limit_match;
9471  arguments.notbol = (options & PCRE_NOTBOL) != 0;  arguments.notbol = (options & PCRE_NOTBOL) != 0;
9472  arguments.noteol = (options & PCRE_NOTEOL) != 0;  arguments.noteol = (options & PCRE_NOTEOL) != 0;
9473  arguments.notempty = (options & PCRE_NOTEMPTY) != 0;  arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
# Line 9570  arguments.begin = subject_ptr; Line 9558  arguments.begin = subject_ptr;
9558  arguments.end = subject_ptr + length;  arguments.end = subject_ptr + length;
9559  arguments.mark_ptr = NULL;  arguments.mark_ptr = NULL;
9560  /* JIT decreases this value less frequently than the interpreter. */  /* JIT decreases this value less frequently than the interpreter. */
9561  arguments.call_limit = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : extra_data->match_limit;  arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (pcre_uint32)(extra_data->match_limit);
9562    if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match)
9563      arguments.limit_match = functions->limit_match;
9564  arguments.notbol = (options & PCRE_NOTBOL) != 0;  arguments.notbol = (options & PCRE_NOTBOL) != 0;
9565  arguments.noteol = (options & PCRE_NOTEOL) != 0;  arguments.noteol = (options & PCRE_NOTEOL) != 0;
9566  arguments.notempty = (options & PCRE_NOTEMPTY) != 0;  arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
# Line 9689  if (extra != NULL && Line 9679  if (extra != NULL &&
9679    }    }
9680  }  }
9681    
9682    #if defined COMPILE_PCRE8
9683    PCRE_EXP_DECL void
9684    pcre_jit_free_unused_memory(void)
9685    #elif defined COMPILE_PCRE16
9686    PCRE_EXP_DECL void
9687    pcre16_jit_free_unused_memory(void)
9688    #elif defined COMPILE_PCRE32
9689    PCRE_EXP_DECL void
9690    pcre32_jit_free_unused_memory(void)
9691    #endif
9692    {
9693    sljit_free_unused_memory_exec();
9694    }
9695    
9696  #else  /* SUPPORT_JIT */  #else  /* SUPPORT_JIT */
9697    
9698  /* These are dummy functions to avoid linking errors when JIT support is not  /* These are dummy functions to avoid linking errors when JIT support is not
# Line 9740  pcre32_assign_jit_stack(pcre32_extra *ex Line 9744  pcre32_assign_jit_stack(pcre32_extra *ex
9744  (void)userdata;  (void)userdata;
9745  }  }
9746    
9747    #if defined COMPILE_PCRE8
9748    PCRE_EXP_DECL void
9749    pcre_jit_free_unused_memory(void)
9750    #elif defined COMPILE_PCRE16
9751    PCRE_EXP_DECL void
9752    pcre16_jit_free_unused_memory(void)
9753    #elif defined COMPILE_PCRE32
9754    PCRE_EXP_DECL void
9755    pcre32_jit_free_unused_memory(void)
9756    #endif
9757    {
9758    }
9759    
9760  #endif  #endif
9761    
9762  /* End of pcre_jit_compile.c */  /* End of pcre_jit_compile.c */

Legend:
Removed from v.1308  
changed lines
  Added in v.1377

  ViewVC Help
Powered by ViewVC 1.1.5