/[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 1282 by zherczeg, Fri Mar 15 08:01:41 2013 UTC revision 1308 by zherczeg, Tue Apr 2 06:58:55 2013 UTC
# Line 196  typedef struct stub_list { Line 196  typedef struct stub_list {
196    struct stub_list *next;    struct stub_list *next;
197  } stub_list;  } stub_list;
198    
 enum bytecode_flag_types {  
   flag_optimized_cbracket = 1,  
   flag_then_start = 2,  
 };  
   
199  enum frame_types {  enum frame_types {
200    no_frame = -1,    no_frame = -1,
201    no_stack = -2    no_stack = -2
202  };  };
203    
204  enum control_types {  enum control_types {
205    type_commit = 0,    type_mark = 0,
206    type_prune = 1,    type_then_trap = 1
   type_skip = 2,  
   type_skip_arg = 3,  
   type_mark = 4,  
   type_then_trap = 5  
207  };  };
208    
209  typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);  typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);
# Line 322  typedef struct compiler_common { Line 313  typedef struct compiler_common {
313    /* First byte code. */    /* First byte code. */
314    pcre_uchar *start;    pcre_uchar *start;
315    /* Maps private data offset to each opcode. */    /* Maps private data offset to each opcode. */
316    int *private_data_ptrs;    sljit_si *private_data_ptrs;
317    /* Tells whether the capturing bracket is optimized. */    /* Tells whether the capturing bracket is optimized. */
318    pcre_uint8 *optimized_cbracket;    pcre_uint8 *optimized_cbracket;
319    /* Tells whether the starting offset is a target of then. */    /* Tells whether the starting offset is a target of then. */
# Line 365  typedef struct compiler_common { Line 356  typedef struct compiler_common {
356    BOOL has_then;    BOOL has_then;
357    /* Needs to know the start position anytime. */    /* Needs to know the start position anytime. */
358    BOOL needs_start_ptr;    BOOL needs_start_ptr;
359    /* Currently in recurse or assert. */    /* Currently in recurse or negative assert. */
360    BOOL local_exit;    BOOL local_exit;
361      /* Currently in a positive assert. */
362      BOOL positive_assert;
363    /* Newline control. */    /* Newline control. */
364    int nltype;    int nltype;
365    int newline;    int newline;
# Line 391  typedef struct compiler_common { Line 384  typedef struct compiler_common {
384    recurse_entry *currententry;    recurse_entry *currententry;
385    jump_list *partialmatch;    jump_list *partialmatch;
386    jump_list *quit;    jump_list *quit;
387      jump_list *positive_assert_quit;
388    jump_list *forced_quit;    jump_list *forced_quit;
389    jump_list *accept;    jump_list *accept;
390    jump_list *calllimit;    jump_list *calllimit;
# Line 540  return cc; Line 534  return cc;
534    
535  /* Functions whose might need modification for all new supported opcodes:  /* Functions whose might need modification for all new supported opcodes:
536   next_opcode   next_opcode
537   get_private_data_length   check_opcode_types
538   set_private_data_ptrs   set_private_data_ptrs
539   get_framesize   get_framesize
540   init_frame   init_frame
# Line 739  switch(*cc) Line 733  switch(*cc)
733    }    }
734  }  }
735    
736  #define CASE_ITERATOR_PRIVATE_DATA_1 \  static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
     case OP_MINSTAR: \  
     case OP_MINPLUS: \  
     case OP_QUERY: \  
     case OP_MINQUERY: \  
     case OP_MINSTARI: \  
     case OP_MINPLUSI: \  
     case OP_QUERYI: \  
     case OP_MINQUERYI: \  
     case OP_NOTMINSTAR: \  
     case OP_NOTMINPLUS: \  
     case OP_NOTQUERY: \  
     case OP_NOTMINQUERY: \  
     case OP_NOTMINSTARI: \  
     case OP_NOTMINPLUSI: \  
     case OP_NOTQUERYI: \  
     case OP_NOTMINQUERYI:  
   
 #define CASE_ITERATOR_PRIVATE_DATA_2A \  
     case OP_STAR: \  
     case OP_PLUS: \  
     case OP_STARI: \  
     case OP_PLUSI: \  
     case OP_NOTSTAR: \  
     case OP_NOTPLUS: \  
     case OP_NOTSTARI: \  
     case OP_NOTPLUSI:  
   
 #define CASE_ITERATOR_PRIVATE_DATA_2B \  
     case OP_UPTO: \  
     case OP_MINUPTO: \  
     case OP_UPTOI: \  
     case OP_MINUPTOI: \  
     case OP_NOTUPTO: \  
     case OP_NOTMINUPTO: \  
     case OP_NOTUPTOI: \  
     case OP_NOTMINUPTOI:  
   
 #define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \  
     case OP_TYPEMINSTAR: \  
     case OP_TYPEMINPLUS: \  
     case OP_TYPEQUERY: \  
     case OP_TYPEMINQUERY:  
   
 #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \  
     case OP_TYPESTAR: \  
     case OP_TYPEPLUS:  
   
 #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \  
     case OP_TYPEUPTO: \  
     case OP_TYPEMINUPTO:  
   
 static int get_class_iterator_size(pcre_uchar *cc)  
 {  
 switch(*cc)  
   {  
   case OP_CRSTAR:  
   case OP_CRPLUS:  
   return 2;  
   
   case OP_CRMINSTAR:  
   case OP_CRMINPLUS:  
   case OP_CRQUERY:  
   case OP_CRMINQUERY:  
   return 1;  
   
   case OP_CRRANGE:  
   case OP_CRMINRANGE:  
   if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE))  
     return 0;  
   return 2;  
   
   default:  
   return 0;  
   }  
 }  
   
 static int get_private_data_length(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)  
737  {  {
 int private_data_length = 0;  
 pcre_uchar *alternative;  
738  pcre_uchar *name;  pcre_uchar *name;
739  pcre_uchar *end = NULL;  pcre_uchar *name2;
740  int space, size, i;  int i, cbra_index;
 pcre_uint32 bracketlen;  
741    
742  /* 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. */
743  while (cc < ccend)  while (cc < ccend)
744    {    {
   space = 0;  
   size = 0;  
   bracketlen = 0;  
745    switch(*cc)    switch(*cc)
746      {      {
747      case OP_SET_SOM:      case OP_SET_SOM:
# Line 844  while (cc < ccend) Line 755  while (cc < ccend)
755      cc += 1 + IMM2_SIZE;      cc += 1 + IMM2_SIZE;
756      break;      break;
757    
     case OP_ASSERT:  
     case OP_ASSERT_NOT:  
     case OP_ASSERTBACK:  
     case OP_ASSERTBACK_NOT:  
     case OP_ONCE:  
     case OP_ONCE_NC:  
     case OP_BRAPOS:  
     case OP_SBRA:  
     case OP_SBRAPOS:  
     private_data_length += sizeof(sljit_sw);  
     bracketlen = 1 + LINK_SIZE;  
     break;  
   
758      case OP_CBRAPOS:      case OP_CBRAPOS:
759      case OP_SCBRAPOS:      case OP_SCBRAPOS:
     private_data_length += sizeof(sljit_sw);  
760      common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;      common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;
761      bracketlen = 1 + LINK_SIZE + IMM2_SIZE;      cc += 1 + LINK_SIZE + IMM2_SIZE;
762      break;      break;
763    
764      case OP_COND:      case OP_COND:
# Line 869  while (cc < ccend) Line 766  while (cc < ccend)
766      /* Only AUTO_CALLOUT can insert this opcode. We do      /* Only AUTO_CALLOUT can insert this opcode. We do
767         not intend to support this case. */         not intend to support this case. */
768      if (cc[1 + LINK_SIZE] == OP_CALLOUT)      if (cc[1 + LINK_SIZE] == OP_CALLOUT)
769        return -1;        return FALSE;
770        cc += 1 + LINK_SIZE;
     if (*cc == OP_COND)  
       {  
       /* Might be a hidden SCOND. */  
       alternative = cc + GET(cc, 1);  
       if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)  
         private_data_length += sizeof(sljit_sw);  
       }  
     else  
       private_data_length += sizeof(sljit_sw);  
     bracketlen = 1 + LINK_SIZE;  
771      break;      break;
772    
773      case OP_CREF:      case OP_CREF:
# Line 890  while (cc < ccend) Line 777  while (cc < ccend)
777      break;      break;
778    
779      case OP_NCREF:      case OP_NCREF:
780      bracketlen = GET2(cc, 1);      cbra_index = GET2(cc, 1);
781      name = (pcre_uchar *)common->name_table;      name = (pcre_uchar *)common->name_table;
782      alternative = name;      name2 = name;
783      for (i = 0; i < common->name_count; i++)      for (i = 0; i < common->name_count; i++)
784        {        {
785        if (GET2(name, 0) == bracketlen) break;        if (GET2(name, 0) == cbra_index) break;
786        name += common->name_entry_size;        name += common->name_entry_size;
787        }        }
788      SLJIT_ASSERT(i != common->name_count);      SLJIT_ASSERT(i != common->name_count);
789    
790      for (i = 0; i < common->name_count; i++)      for (i = 0; i < common->name_count; i++)
791        {        {
792        if (STRCMP_UC_UC(alternative + IMM2_SIZE, name + IMM2_SIZE) == 0)        if (STRCMP_UC_UC(name2 + IMM2_SIZE, name + IMM2_SIZE) == 0)
793          common->optimized_cbracket[GET2(alternative, 0)] = 0;          common->optimized_cbracket[GET2(name2, 0)] = 0;
794        alternative += common->name_entry_size;        name2 += common->name_entry_size;
795        }        }
     bracketlen = 0;  
796      cc += 1 + IMM2_SIZE;      cc += 1 + IMM2_SIZE;
797      break;      break;
798    
     case OP_BRA:  
     bracketlen = 1 + LINK_SIZE;  
     break;  
   
     case OP_CBRA:  
     case OP_SCBRA:  
     bracketlen = 1 + LINK_SIZE + IMM2_SIZE;  
     break;  
   
     CASE_ITERATOR_PRIVATE_DATA_1  
     space = 1;  
     size = -2;  
     break;  
   
     CASE_ITERATOR_PRIVATE_DATA_2A  
     space = 2;  
     size = -2;  
     break;  
   
     CASE_ITERATOR_PRIVATE_DATA_2B  
     space = 2;  
     size = -(2 + IMM2_SIZE);  
     break;  
   
     CASE_ITERATOR_TYPE_PRIVATE_DATA_1  
     space = 1;  
     size = 1;  
     break;  
   
     CASE_ITERATOR_TYPE_PRIVATE_DATA_2A  
     if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI)  
       space = 2;  
     size = 1;  
     break;  
   
     CASE_ITERATOR_TYPE_PRIVATE_DATA_2B  
     if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI)  
       space = 2;  
     size = 1 + IMM2_SIZE;  
     break;  
   
     case OP_CLASS:  
     case OP_NCLASS:  
     size += 1 + 32 / sizeof(pcre_uchar);  
     space = get_class_iterator_size(cc + size);  
     break;  
   
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8  
     case OP_XCLASS:  
     size = GET(cc, 1);  
     space = get_class_iterator_size(cc + size);  
     break;  
 #endif  
   
799      case OP_RECURSE:      case OP_RECURSE:
800      /* Set its value only once. */      /* Set its value only once. */
801      if (common->recursive_head_ptr == 0)      if (common->recursive_head_ptr == 0)
# Line 985  while (cc < ccend) Line 817  while (cc < ccend)
817    
818      case OP_THEN_ARG:      case OP_THEN_ARG:
819      common->has_then = TRUE;      common->has_then = TRUE;
820        common->control_head_ptr = 1;
821      /* Fall through. */      /* Fall through. */
822    
823      case OP_PRUNE_ARG:      case OP_PRUNE_ARG:
824      common->needs_start_ptr = TRUE;      common->needs_start_ptr = TRUE;
     common->control_head_ptr = 1;  
825      /* Fall through. */      /* Fall through. */
826    
827      case OP_MARK:      case OP_MARK:
# Line 1003  while (cc < ccend) Line 835  while (cc < ccend)
835    
836      case OP_THEN:      case OP_THEN:
837      common->has_then = TRUE;      common->has_then = TRUE;
838        common->control_head_ptr = 1;
839      /* Fall through. */      /* Fall through. */
840    
841      case OP_PRUNE:      case OP_PRUNE:
842      case OP_SKIP:      case OP_SKIP:
843      common->needs_start_ptr = TRUE;      common->needs_start_ptr = TRUE;
     common->control_head_ptr = 1;  
844      cc += 1;      cc += 1;
845      break;      break;
846    
# Line 1021  while (cc < ccend) Line 853  while (cc < ccend)
853      default:      default:
854      cc = next_opcode(common, cc);      cc = next_opcode(common, cc);
855      if (cc == NULL)      if (cc == NULL)
856        return -1;        return FALSE;
857      break;      break;
858      }      }
859      }
860    return TRUE;
861    }
862    
863    if (space > 0 && cc >= end)  static int get_class_iterator_size(pcre_uchar *cc)
864      private_data_length += sizeof(sljit_sw) * space;  {
865    switch(*cc)
866      {
867      case OP_CRSTAR:
868      case OP_CRPLUS:
869      return 2;
870    
871    if (size != 0)    case OP_CRMINSTAR:
872      case OP_CRMINPLUS:
873      case OP_CRQUERY:
874      case OP_CRMINQUERY:
875      return 1;
876    
877      case OP_CRRANGE:
878      case OP_CRMINRANGE:
879      if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE))
880        return 0;
881      return 2;
882    
883      default:
884      return 0;
885      }
886    }
887    
888    static BOOL detect_repeat(compiler_common *common, pcre_uchar *begin)
889    {
890    pcre_uchar *end = bracketend(begin);
891    pcre_uchar *next;
892    pcre_uchar *next_end;
893    pcre_uchar *max_end;
894    pcre_uchar type;
895    sljit_uw length = end - begin;
896    int min, max, i;
897    
898    /* Detect fixed iterations first. */
899    if (end[-(1 + LINK_SIZE)] != OP_KET)
900      return FALSE;
901    
902    /* Already detected repeat. */
903    if (common->private_data_ptrs[end - common->start - LINK_SIZE] != 0)
904      return TRUE;
905    
906    next = end;
907    min = 1;
908    while (1)
909      {
910      if (*next != *begin)
911        break;
912      next_end = bracketend(next);
913      if (next_end - next != length || memcmp(begin, next, IN_UCHARS(length)) != 0)
914        break;
915      next = next_end;
916      min++;
917      }
918    
919    if (min == 2)
920      return FALSE;
921    
922    max = 0;
923    max_end = next;
924    if (*next == OP_BRAZERO || *next == OP_BRAMINZERO)
925      {
926      type = *next;
927      while (1)
928      {      {
929      if (size < 0)      if (next[0] != type || next[1] != OP_BRA || next[2 + LINK_SIZE] != *begin)
930        {        break;
931        cc += -size;      next_end = bracketend(next + 2 + LINK_SIZE);
932  #ifdef SUPPORT_UTF      if (next_end - next != (length + 2 + LINK_SIZE) || memcmp(begin, next + 2 + LINK_SIZE, IN_UCHARS(length)) != 0)
933        if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);        break;
934  #endif      next = next_end;
935        }      max++;
     else  
       cc += size;  
936      }      }
937    
938    if (bracketlen != 0)    if (next[0] == type && next[1] == *begin && max >= 1)
939      {      {
940      if (cc >= end)      next_end = bracketend(next + 1);
941        if (next_end - next == (length + 1) && memcmp(begin, next + 1, IN_UCHARS(length)) == 0)
942        {        {
943        end = bracketend(cc);        for (i = 0; i < max; i++, next_end += 1 + LINK_SIZE)
944        if (end[-1 - LINK_SIZE] == OP_KET)          if (*next_end != OP_KET)
945          end = NULL;            break;
946    
947          if (i == max)
948            {
949            common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end;
950            common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO;
951            /* +2 the original and the last. */
952            common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2;
953            if (min == 1)
954              return TRUE;
955            min--;
956            max_end -= (1 + LINK_SIZE) + GET(max_end, -LINK_SIZE);
957            }
958        }        }
     cc += bracketlen;  
959      }      }
960    }    }
961  return private_data_length;  
962    if (min >= 3)
963      {
964      common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end;
965      common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT;
966      common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min;
967      return TRUE;
968      }
969    
970    return FALSE;
971  }  }
972    
973  static void set_private_data_ptrs(compiler_common *common, int private_data_ptr, pcre_uchar *ccend)  #define CASE_ITERATOR_PRIVATE_DATA_1 \
974        case OP_MINSTAR: \
975        case OP_MINPLUS: \
976        case OP_QUERY: \
977        case OP_MINQUERY: \
978        case OP_MINSTARI: \
979        case OP_MINPLUSI: \
980        case OP_QUERYI: \
981        case OP_MINQUERYI: \
982        case OP_NOTMINSTAR: \
983        case OP_NOTMINPLUS: \
984        case OP_NOTQUERY: \
985        case OP_NOTMINQUERY: \
986        case OP_NOTMINSTARI: \
987        case OP_NOTMINPLUSI: \
988        case OP_NOTQUERYI: \
989        case OP_NOTMINQUERYI:
990    
991    #define CASE_ITERATOR_PRIVATE_DATA_2A \
992        case OP_STAR: \
993        case OP_PLUS: \
994        case OP_STARI: \
995        case OP_PLUSI: \
996        case OP_NOTSTAR: \
997        case OP_NOTPLUS: \
998        case OP_NOTSTARI: \
999        case OP_NOTPLUSI:
1000    
1001    #define CASE_ITERATOR_PRIVATE_DATA_2B \
1002        case OP_UPTO: \
1003        case OP_MINUPTO: \
1004        case OP_UPTOI: \
1005        case OP_MINUPTOI: \
1006        case OP_NOTUPTO: \
1007        case OP_NOTMINUPTO: \
1008        case OP_NOTUPTOI: \
1009        case OP_NOTMINUPTOI:
1010    
1011    #define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \
1012        case OP_TYPEMINSTAR: \
1013        case OP_TYPEMINPLUS: \
1014        case OP_TYPEQUERY: \
1015        case OP_TYPEMINQUERY:
1016    
1017    #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \
1018        case OP_TYPESTAR: \
1019        case OP_TYPEPLUS:
1020    
1021    #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \
1022        case OP_TYPEUPTO: \
1023        case OP_TYPEMINUPTO:
1024    
1025    static void set_private_data_ptrs(compiler_common *common, int *private_data_start, pcre_uchar *ccend)
1026  {  {
1027  pcre_uchar *cc = common->start;  pcre_uchar *cc = common->start;
1028  pcre_uchar *alternative;  pcre_uchar *alternative;
1029  pcre_uchar *end = NULL;  pcre_uchar *end = NULL;
1030    int private_data_ptr = *private_data_start;
1031  int space, size, bracketlen;  int space, size, bracketlen;
1032    
1033  while (cc < ccend)  while (cc < ccend)
# Line 1067  while (cc < ccend) Line 1035  while (cc < ccend)
1035    space = 0;    space = 0;
1036    size = 0;    size = 0;
1037    bracketlen = 0;    bracketlen = 0;
1038      if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE)
1039        return;
1040    
1041      if (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)
1042        if (detect_repeat(common, cc))
1043          {
1044          /* These brackets are converted to repeats, so no global
1045          based single character repeat is allowed. */
1046          if (cc >= end)
1047            end = bracketend(cc);
1048          }
1049    
1050    switch(*cc)    switch(*cc)
1051      {      {
1052        case OP_KET:
1053        if (common->private_data_ptrs[cc + 1 - common->start] != 0)
1054          {
1055          common->private_data_ptrs[cc - common->start] = private_data_ptr;
1056          private_data_ptr += sizeof(sljit_sw);
1057          cc += common->private_data_ptrs[cc + 1 - common->start];
1058          }
1059        cc += 1 + LINK_SIZE;
1060        break;
1061    
1062      case OP_ASSERT:      case OP_ASSERT:
1063      case OP_ASSERT_NOT:      case OP_ASSERT_NOT:
1064      case OP_ASSERTBACK:      case OP_ASSERTBACK:
# Line 1162  while (cc < ccend) Line 1152  while (cc < ccend)
1152      break;      break;
1153      }      }
1154    
1155      /* Character iterators, which are not inside a repeated bracket,
1156         gets a private slot instead of allocating it on the stack. */
1157    if (space > 0 && cc >= end)    if (space > 0 && cc >= end)
1158      {      {
1159      common->private_data_ptrs[cc - common->start] = private_data_ptr;      common->private_data_ptrs[cc - common->start] = private_data_ptr;
# Line 1192  while (cc < ccend) Line 1184  while (cc < ccend)
1184      cc += bracketlen;      cc += bracketlen;
1185      }      }
1186    }    }
1187    *private_data_start = private_data_ptr;
1188  }  }
1189    
1190  /* Returns with a frame_types (always < 0) if no need for frame. */  /* Returns with a frame_types (always < 0) if no need for frame. */
# Line 1288  while (cc < ccend) Line 1281  while (cc < ccend)
1281      cc += 1 + LINK_SIZE + IMM2_SIZE;      cc += 1 + LINK_SIZE + IMM2_SIZE;
1282      break;      break;
1283    
     case OP_PRUNE:  
     case OP_SKIP:  
     case OP_SKIP_ARG:  
     case OP_COMMIT:  
     if (common->control_head_ptr != 0)  
       *needs_control_head = TRUE;  
     /* Fall through. */  
   
1284      default:      default:
1285      stack_restore = TRUE;      stack_restore = TRUE;
1286      /* Fall through. */      /* Fall through. */
# Line 1511  while (cc < ccend) Line 1496  while (cc < ccend)
1496    size = 0;    size = 0;
1497    switch(*cc)    switch(*cc)
1498      {      {
1499        case OP_KET:
1500        if (PRIVATE_DATA(cc) != 0)
1501          private_data_length++;
1502        cc += 1 + LINK_SIZE;
1503        break;
1504    
1505      case OP_ASSERT:      case OP_ASSERT:
1506      case OP_ASSERT_NOT:      case OP_ASSERT_NOT:
1507      case OP_ASSERTBACK:      case OP_ASSERTBACK:
# Line 1679  do Line 1670  do
1670    
1671      switch(*cc)      switch(*cc)
1672        {        {
1673          case OP_KET:
1674          if (PRIVATE_DATA(cc) != 0)
1675            {
1676            count = 1;
1677            srcw[0] = PRIVATE_DATA(cc);
1678            }
1679          cc += 1 + LINK_SIZE;
1680          break;
1681    
1682        case OP_ASSERT:        case OP_ASSERT:
1683        case OP_ASSERT_NOT:        case OP_ASSERT_NOT:
1684        case OP_ASSERTBACK:        case OP_ASSERTBACK:
# Line 2105  else Line 2105  else
2105  OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);  OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);
2106  if (common->mark_ptr != 0)  if (common->mark_ptr != 0)
2107    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0);
2108  SLJIT_ASSERT(common->control_head_ptr != 0);  if (common->control_head_ptr != 0)
2109  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0);
2110  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));
2111  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr);  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr);
2112  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base));  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base));
2113  }  }
2114    
2115  static sljit_sw SLJIT_CALL do_check_control_chain(sljit_sw *current)  static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg)
2116  {  {
2117  sljit_sw return_value = 0;  while (current != NULL)
 const pcre_uchar *skip_arg = NULL;  
   
 SLJIT_ASSERT(current != NULL);  
 do  
2118    {    {
2119    switch (current[-2])    switch (current[-2])
2120      {      {
     case type_commit:  
     /* Commit overwrites all. */  
     return -1;  
   
     case type_prune:  
2121      case type_then_trap:      case type_then_trap:
2122      break;      break;
2123    
     case type_skip:  
     /* Overwrites prune, but not other skips. */  
     if (return_value == 0 && skip_arg == NULL)  
       return_value = current[-3];  
     break;  
   
     case type_skip_arg:  
     if (return_value == 0 && skip_arg == NULL)  
       skip_arg = (pcre_uchar *)current[-3];  
     break;  
   
2124      case type_mark:      case type_mark:
2125      if (return_value == 0 && skip_arg != NULL)      if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0)
2126        if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0)        return current[-4];
         return_value = current[-4];  
2127      break;      break;
2128    
2129      default:      default:
# Line 2153  do Line 2132  do
2132      }      }
2133    current = (sljit_sw*)current[-1];    current = (sljit_sw*)current[-1];
2134    }    }
2135  while (current != NULL);  return -1;
 return (return_value != 0 || skip_arg == NULL) ? return_value : -2;  
 }  
   
 static sljit_sw SLJIT_CALL do_search_then_trap(sljit_sw *current, sljit_sw start)  
 {  
 do  
   {  
   switch (current[-2])  
     {  
     case type_commit:  
     /* Commit overwrites all. */  
     return 0;  
   
     case type_then_trap:  
     if (current[-3] == start)  
       return (sljit_sw)current;  
     break;  
   
     case type_prune:  
     case type_skip:  
     case type_skip_arg:  
     case type_mark:  
     break;  
   
     default:  
     SLJIT_ASSERT_STOP();  
     break;  
     }  
   current = (sljit_sw*)current[-1];  
   SLJIT_ASSERT(current != NULL);  
   }  
 while (TRUE);  
2136  }  }
2137    
2138  static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)  static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
# Line 5571  jump_list **target = (conditional) ? &ba Line 5518  jump_list **target = (conditional) ? &ba
5518  jump_list **found;  jump_list **found;
5519  /* Saving previous accept variables. */  /* Saving previous accept variables. */
5520  BOOL save_local_exit = common->local_exit;  BOOL save_local_exit = common->local_exit;
5521    BOOL save_positive_assert = common->positive_assert;
5522  then_trap_backtrack *save_then_trap = common->then_trap;  then_trap_backtrack *save_then_trap = common->then_trap;
5523  struct sljit_label *save_quit_label = common->quit_label;  struct sljit_label *save_quit_label = common->quit_label;
5524  struct sljit_label *save_accept_label = common->accept_label;  struct sljit_label *save_accept_label = common->accept_label;
5525  jump_list *save_quit = common->quit;  jump_list *save_quit = common->quit;
5526    jump_list *save_positive_assert_quit = common->positive_assert_quit;
5527  jump_list *save_accept = common->accept;  jump_list *save_accept = common->accept;
5528  struct sljit_jump *jump;  struct sljit_jump *jump;
5529  struct sljit_jump *brajump = NULL;  struct sljit_jump *brajump = NULL;
# Line 5644  else Line 5593  else
5593    }    }
5594    
5595  memset(&altbacktrack, 0, sizeof(backtrack_common));  memset(&altbacktrack, 0, sizeof(backtrack_common));
5596  common->local_exit = TRUE;  if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
5597  common->quit_label = NULL;    {
5598  common->quit = NULL;    /* Negative assert is stronger than positive assert. */
5599      common->local_exit = TRUE;
5600      common->quit_label = NULL;
5601      common->quit = NULL;
5602      common->positive_assert = FALSE;
5603      }
5604    else
5605      common->positive_assert = TRUE;
5606    common->positive_assert_quit = NULL;
5607    
5608  while (1)  while (1)
5609    {    {
5610    common->accept_label = NULL;    common->accept_label = NULL;
# Line 5661  while (1) Line 5619  while (1)
5619    compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);    compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);
5620    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
5621      {      {
5622      common->local_exit = save_local_exit;      if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
5623          {
5624          common->local_exit = save_local_exit;
5625          common->quit_label = save_quit_label;
5626          common->quit = save_quit;
5627          }
5628        common->positive_assert = save_positive_assert;
5629      common->then_trap = save_then_trap;      common->then_trap = save_then_trap;
     common->quit_label = save_quit_label;  
5630      common->accept_label = save_accept_label;      common->accept_label = save_accept_label;
5631      common->quit = save_quit;      common->positive_assert_quit = save_positive_assert_quit;
5632      common->accept = save_accept;      common->accept = save_accept;
5633      return NULL;      return NULL;
5634      }      }
# Line 5730  while (1) Line 5693  while (1)
5693    compile_backtrackingpath(common, altbacktrack.top);    compile_backtrackingpath(common, altbacktrack.top);
5694    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
5695      {      {
5696      common->local_exit = save_local_exit;      if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
5697          {
5698          common->local_exit = save_local_exit;
5699          common->quit_label = save_quit_label;
5700          common->quit = save_quit;
5701          }
5702        common->positive_assert = save_positive_assert;
5703      common->then_trap = save_then_trap;      common->then_trap = save_then_trap;
     common->quit_label = save_quit_label;  
5704      common->accept_label = save_accept_label;      common->accept_label = save_accept_label;
5705      common->quit = save_quit;      common->positive_assert_quit = save_positive_assert_quit;
5706      common->accept = save_accept;      common->accept = save_accept;
5707      return NULL;      return NULL;
5708      }      }
# Line 5747  while (1) Line 5715  while (1)
5715    cc += GET(cc, 1);    cc += GET(cc, 1);
5716    }    }
5717    
5718    if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
5719      {
5720      SLJIT_ASSERT(common->positive_assert_quit == NULL);
5721      /* Makes the check less complicated below. */
5722      common->positive_assert_quit = common->quit;
5723      }
5724    
5725  /* None of them matched. */  /* None of them matched. */
5726  if (common->quit != NULL)  if (common->positive_assert_quit != NULL)
5727    {    {
5728    jump = JUMP(SLJIT_JUMP);    jump = JUMP(SLJIT_JUMP);
5729    set_jumps(common->quit, LABEL());    set_jumps(common->positive_assert_quit, LABEL());
5730    SLJIT_ASSERT(framesize != no_stack);    SLJIT_ASSERT(framesize != no_stack);
5731    if (framesize < 0)    if (framesize < 0)
5732      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));
# Line 5911  else Line 5886  else
5886      }      }
5887    }    }
5888    
5889  common->local_exit = save_local_exit;  if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
5890      {
5891      common->local_exit = save_local_exit;
5892      common->quit_label = save_quit_label;
5893      common->quit = save_quit;
5894      }
5895    common->positive_assert = save_positive_assert;
5896  common->then_trap = save_then_trap;  common->then_trap = save_then_trap;
 common->quit_label = save_quit_label;  
5897  common->accept_label = save_accept_label;  common->accept_label = save_accept_label;
5898  common->quit = save_quit;  common->positive_assert_quit = save_positive_assert_quit;
5899  common->accept = save_accept;  common->accept = save_accept;
5900  return cc + 1 + LINK_SIZE;  return cc + 1 + LINK_SIZE;
5901  }  }
# Line 6163  pcre_uchar opcode; Line 6143  pcre_uchar opcode;
6143  int private_data_ptr = 0;  int private_data_ptr = 0;
6144  int offset = 0;  int offset = 0;
6145  int stacksize;  int stacksize;
6146    int repeat_ptr = 0, repeat_length = 0;
6147    int repeat_type = 0, repeat_count = 0;
6148  pcre_uchar *ccbegin;  pcre_uchar *ccbegin;
6149  pcre_uchar *matchingpath;  pcre_uchar *matchingpath;
6150  pcre_uchar bra = OP_BRA;  pcre_uchar bra = OP_BRA;
# Line 6172  BOOL has_alternatives; Line 6154  BOOL has_alternatives;
6154  BOOL needs_control_head = FALSE;  BOOL needs_control_head = FALSE;
6155  struct sljit_jump *jump;  struct sljit_jump *jump;
6156  struct sljit_jump *skip;  struct sljit_jump *skip;
6157  struct sljit_label *rmaxlabel = NULL;  struct sljit_label *rmax_label = NULL;
6158  struct sljit_jump *braminzerojump = NULL;  struct sljit_jump *braminzero = NULL;
6159    
6160  PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);  PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);
6161    
# Line 6186  if (*cc == OP_BRAZERO || *cc == OP_BRAMI Line 6168  if (*cc == OP_BRAZERO || *cc == OP_BRAMI
6168    
6169  opcode = *cc;  opcode = *cc;
6170  ccbegin = cc;  ccbegin = cc;
6171  matchingpath = ccbegin + 1 + LINK_SIZE;  matchingpath = bracketend(cc) - 1 - LINK_SIZE;
6172    ket = *matchingpath;
6173    if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0)
6174      {
6175      repeat_ptr = PRIVATE_DATA(matchingpath);
6176      repeat_length = PRIVATE_DATA(matchingpath + 1);
6177      repeat_type = PRIVATE_DATA(matchingpath + 2);
6178      repeat_count = PRIVATE_DATA(matchingpath + 3);
6179      SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0);
6180      if (repeat_type == OP_UPTO)
6181        ket = OP_KETRMAX;
6182      if (repeat_type == OP_MINUPTO)
6183        ket = OP_KETRMIN;
6184      }
6185    
6186  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)
6187    {    {
6188    /* Drop this bracket_backtrack. */    /* Drop this bracket_backtrack. */
6189    parent->top = backtrack->prev;    parent->top = backtrack->prev;
6190    return bracketend(cc);    return matchingpath + 1 + LINK_SIZE + repeat_length;
6191    }    }
6192    
6193  ket = *(bracketend(cc) - 1 - LINK_SIZE);  matchingpath = ccbegin + 1 + LINK_SIZE;
6194  SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);  SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
6195  SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));  SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
6196  cc += GET(cc, 1);  cc += GET(cc, 1);
# Line 6275  if (bra == OP_BRAMINZERO) Line 6270  if (bra == OP_BRAMINZERO)
6270    if (ket != OP_KETRMIN)    if (ket != OP_KETRMIN)
6271      {      {
6272      free_stack(common, 1);      free_stack(common, 1);
6273      braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);      braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
6274      }      }
6275    else    else
6276      {      {
# Line 6290  if (bra == OP_BRAMINZERO) Line 6285  if (bra == OP_BRAMINZERO)
6285        if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)        if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
6286          {          {
6287          /* When we come from outside, private_data_ptr contains the previous STR_PTR. */          /* When we come from outside, private_data_ptr contains the previous STR_PTR. */
6288          braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);          braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
6289          }          }
6290        else        else
6291          {          {
6292          /* Except when the whole stack frame must be saved. */          /* Except when the whole stack frame must be saved. */
6293          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
6294          braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw));          braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw));
6295          }          }
6296        JUMPHERE(skip);        JUMPHERE(skip);
6297        }        }
# Line 6309  if (bra == OP_BRAMINZERO) Line 6304  if (bra == OP_BRAMINZERO)
6304      }      }
6305    }    }
6306    
6307    if (repeat_type != 0)
6308      {
6309      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, repeat_count);
6310      if (repeat_type == OP_EXACT)
6311        rmax_label = LABEL();
6312      }
6313    
6314  if (ket == OP_KETRMIN)  if (ket == OP_KETRMIN)
6315    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();
6316    
6317  if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
6318    {    {
6319    rmaxlabel = LABEL();    rmax_label = LABEL();
6320    if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)    if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA && repeat_type == 0)
6321      BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmaxlabel;      BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmax_label;
6322    }    }
6323    
6324  /* Handling capturing brackets and alternatives. */  /* Handling capturing brackets and alternatives. */
# Line 6534  if (opcode == OP_ONCE) Line 6536  if (opcode == OP_ONCE)
6536    match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);    match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);
6537    
6538  stacksize = 0;  stacksize = 0;
6539    if (repeat_type == OP_MINUPTO)
6540      {
6541      /* We need to preserve the counter. TMP2 will be used below. */
6542      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
6543      stacksize++;
6544      }
6545  if (ket != OP_KET || bra != OP_BRA)  if (ket != OP_KET || bra != OP_BRA)
6546    stacksize++;    stacksize++;
6547  if (offset != 0)  if (offset != 0)
# Line 6550  if (stacksize > 0) Line 6558  if (stacksize > 0)
6558    allocate_stack(common, stacksize);    allocate_stack(common, stacksize);
6559    
6560  stacksize = 0;  stacksize = 0;
6561    if (repeat_type == OP_MINUPTO)
6562      {
6563      /* TMP2 was set above. */
6564      OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);
6565      stacksize++;
6566      }
6567    
6568  if (ket != OP_KET || bra != OP_BRA)  if (ket != OP_KET || bra != OP_BRA)
6569    {    {
6570    if (ket != OP_KET)    if (ket != OP_KET)
# Line 6579  if (offset != 0 && common->optimized_cbr Line 6594  if (offset != 0 && common->optimized_cbr
6594    
6595  if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
6596    {    {
6597    if (opcode == OP_ONCE || opcode >= OP_SBRA)    if (repeat_type != 0)
6598        {
6599        if (has_alternatives)
6600          BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
6601        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
6602        JUMPTO(SLJIT_C_NOT_ZERO, rmax_label);
6603        /* Drop STR_PTR for greedy plus quantifier. */
6604        if (opcode != OP_ONCE)
6605          free_stack(common, 1);
6606        }
6607      else if (opcode == OP_ONCE || opcode >= OP_SBRA)
6608      {      {
6609      if (has_alternatives)      if (has_alternatives)
6610        BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();        BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
6611      /* Checking zero-length iteration. */      /* Checking zero-length iteration. */
6612      if (opcode != OP_ONCE)      if (opcode != OP_ONCE)
6613        {        {
6614        CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0, rmaxlabel);        CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0, rmax_label);
6615        /* Drop STR_PTR for greedy plus quantifier. */        /* Drop STR_PTR for greedy plus quantifier. */
6616        if (bra != OP_BRAZERO)        if (bra != OP_BRAZERO)
6617          free_stack(common, 1);          free_stack(common, 1);
6618        }        }
6619      else      else
6620        /* TMP2 must contain the starting STR_PTR. */        /* TMP2 must contain the starting STR_PTR. */
6621        CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);        CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label);
6622      }      }
6623    else    else
6624      JUMPTO(SLJIT_JUMP, rmaxlabel);      JUMPTO(SLJIT_JUMP, rmax_label);
6625    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();
6626    }    }
6627    
6628    if (repeat_type == OP_EXACT)
6629      {
6630      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
6631      JUMPTO(SLJIT_C_NOT_ZERO, rmax_label);
6632      }
6633    else if (repeat_type == OP_UPTO)
6634      {
6635      /* We need to preserve the counter. */
6636      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
6637      allocate_stack(common, 1);
6638      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
6639      }
6640    
6641  if (bra == OP_BRAZERO)  if (bra == OP_BRAZERO)
6642    BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();    BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();
6643    
# Line 6607  if (bra == OP_BRAMINZERO) Line 6645  if (bra == OP_BRAMINZERO)
6645    {    {
6646    /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */    /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */
6647    JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath);    JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath);
6648    if (braminzerojump != NULL)    if (braminzero != NULL)
6649      {      {
6650      JUMPHERE(braminzerojump);      JUMPHERE(braminzero);
6651      /* We need to release the end pointer to perform the      /* We need to release the end pointer to perform the
6652      backtrack for the zero-length iteration. When      backtrack for the zero-length iteration. When
6653      framesize is < 0, OP_ONCE will do the release itself. */      framesize is < 0, OP_ONCE will do the release itself. */
# Line 6635  cc += 1 + LINK_SIZE; Line 6673  cc += 1 + LINK_SIZE;
6673  /* Temporarily encoding the needs_control_head in framesize. */  /* Temporarily encoding the needs_control_head in framesize. */
6674  if (opcode == OP_ONCE)  if (opcode == OP_ONCE)
6675    BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);    BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
6676  return cc;  return cc + repeat_length;
6677  }  }
6678    
6679  static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)  static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
# Line 7296  backtrack_common *backtrack; Line 7334  backtrack_common *backtrack;
7334  pcre_uchar opcode = *cc;  pcre_uchar opcode = *cc;
7335  pcre_uchar *ccend = cc + 1;  pcre_uchar *ccend = cc + 1;
7336    
 SLJIT_ASSERT(common->control_head_ptr != 0 || *cc == OP_COMMIT);  
   
7337  if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG)  if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG)
7338    ccend += 2 + cc[1];    ccend += 2 + cc[1];
7339    
7340  PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);  PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);
7341    
7342  if (opcode == OP_SKIP || opcode == OP_SKIP_ARG)  if (opcode == OP_SKIP)
7343    {    {
7344    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);    allocate_stack(common, 1);
7345    allocate_stack(common, 3);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0);  
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, *cc == OP_SKIP ? type_skip : type_skip_arg);  
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), (opcode == OP_SKIP) ? STR_PTR : SLJIT_IMM, (opcode == OP_SKIP) ? 0 : (sljit_sw)(cc + 2));  
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);  
7346    return ccend;    return ccend;
7347    }    }
7348    
# Line 7322  if (opcode == OP_PRUNE_ARG || opcode == Line 7354  if (opcode == OP_PRUNE_ARG || opcode ==
7354    OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
7355    }    }
7356    
 if (common->control_head_ptr != 0 && ((opcode != OP_THEN && opcode != OP_THEN_ARG) || common->then_trap == NULL))  
   {  
   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);  
   allocate_stack(common, 2);  
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0);  
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, *cc == OP_COMMIT ? type_commit : type_prune);  
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);  
   }  
   
7357  return ccend;  return ccend;
7358  }  }
7359    
# Line 7937  if (bra == OP_BRAZERO) Line 7960  if (bra == OP_BRAZERO)
7960  static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)  static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)
7961  {  {
7962  DEFINE_COMPILER;  DEFINE_COMPILER;
7963  int opcode;  int opcode, stacksize, count;
7964  int offset = 0;  int offset = 0;
7965  int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;  int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;
7966  int stacksize;  int repeat_ptr = 0, repeat_type = 0, repeat_count = 0;
 int count;  
7967  pcre_uchar *cc = current->cc;  pcre_uchar *cc = current->cc;
7968  pcre_uchar *ccbegin;  pcre_uchar *ccbegin;
7969  pcre_uchar *ccprev;  pcre_uchar *ccprev;
# Line 7955  BOOL needs_control_head = FALSE; Line 7977  BOOL needs_control_head = FALSE;
7977  struct sljit_jump *brazero = NULL;  struct sljit_jump *brazero = NULL;
7978  struct sljit_jump *once = NULL;  struct sljit_jump *once = NULL;
7979  struct sljit_jump *cond = NULL;  struct sljit_jump *cond = NULL;
7980  struct sljit_label *rminlabel = NULL;  struct sljit_label *rmin_label = NULL;
7981    struct sljit_label *exact_label = NULL;
7982    
7983  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
7984    {    {
# Line 7964  if (*cc == OP_BRAZERO || *cc == OP_BRAMI Line 7987  if (*cc == OP_BRAZERO || *cc == OP_BRAMI
7987    }    }
7988    
7989  opcode = *cc;  opcode = *cc;
7990    ccbegin = bracketend(cc) - 1 - LINK_SIZE;
7991    ket = *ccbegin;
7992    if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0)
7993      {
7994      repeat_ptr = PRIVATE_DATA(ccbegin);
7995      repeat_type = PRIVATE_DATA(ccbegin + 2);
7996      repeat_count = PRIVATE_DATA(ccbegin + 3);
7997      SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0);
7998      if (repeat_type == OP_UPTO)
7999        ket = OP_KETRMAX;
8000      if (repeat_type == OP_MINUPTO)
8001        ket = OP_KETRMIN;
8002      }
8003  ccbegin = cc;  ccbegin = cc;
 ket = *(bracketend(ccbegin) - 1 - LINK_SIZE);  
8004  cc += GET(cc, 1);  cc += GET(cc, 1);
8005  has_alternatives = *cc == OP_ALT;  has_alternatives = *cc == OP_ALT;
8006  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
# Line 7984  if (opcode == OP_ONCE) Line 8019  if (opcode == OP_ONCE)
8019    CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;    CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;
8020    }    }
8021    
8022    if (ket != OP_KET && repeat_type != 0)
8023      {
8024      /* TMP1 is used in OP_KETRMIN below. */
8025      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
8026      free_stack(common, 1);
8027      if (repeat_type == OP_UPTO)
8028        OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0, SLJIT_IMM, 1);
8029      else
8030        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0);
8031      }
8032    
8033  if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
8034    {    {
8035    if (bra == OP_BRAZERO)    if (bra == OP_BRAZERO)
# Line 7998  else if (ket == OP_KETRMIN) Line 8044  else if (ket == OP_KETRMIN)
8044    if (bra != OP_BRAMINZERO)    if (bra != OP_BRAMINZERO)
8045      {      {
8046      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
8047      if (opcode >= OP_SBRA || opcode == OP_ONCE)      if (repeat_type != 0)
8048          {
8049          /* TMP1 was set a few lines above. */
8050          CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
8051          /* Drop STR_PTR for non-greedy plus quantifier. */
8052          if (opcode != OP_ONCE)
8053            free_stack(common, 1);
8054          }
8055        else if (opcode >= OP_SBRA || opcode == OP_ONCE)
8056        {        {
8057        /* Checking zero-length iteration. */        /* Checking zero-length iteration. */
8058        if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)        if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)
# Line 8008  else if (ket == OP_KETRMIN) Line 8062  else if (ket == OP_KETRMIN)
8062          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
8063          CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);          CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
8064          }          }
8065          /* Drop STR_PTR for non-greedy plus quantifier. */
8066        if (opcode != OP_ONCE)        if (opcode != OP_ONCE)
8067          free_stack(common, 1);          free_stack(common, 1);
8068        }        }
8069      else      else
8070        JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);        JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
8071      }      }
8072    rminlabel = LABEL();    rmin_label = LABEL();
8073      if (repeat_type != 0)
8074        OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
8075    }    }
8076  else if (bra == OP_BRAZERO)  else if (bra == OP_BRAZERO)
8077    {    {
# Line 8022  else if (bra == OP_BRAZERO) Line 8079  else if (bra == OP_BRAZERO)
8079    free_stack(common, 1);    free_stack(common, 1);
8080    brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);    brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
8081    }    }
8082    else if (repeat_type == OP_EXACT)
8083      {
8084      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
8085      exact_label = LABEL();
8086      }
8087    
8088  if (offset != 0)  if (offset != 0)
8089    {    {
# Line 8169  if (has_alternatives) Line 8231  if (has_alternatives)
8231        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);
8232    
8233      stacksize = 0;      stacksize = 0;
8234        if (repeat_type == OP_MINUPTO)
8235          {
8236          /* We need to preserve the counter. TMP2 will be used below. */
8237          OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
8238          stacksize++;
8239          }
8240      if (ket != OP_KET || bra != OP_BRA)      if (ket != OP_KET || bra != OP_BRA)
8241        stacksize++;        stacksize++;
8242      if (offset != 0)      if (offset != 0)
# Line 8182  if (has_alternatives) Line 8250  if (has_alternatives)
8250        stacksize++;        stacksize++;
8251    
8252      if (stacksize > 0)      if (stacksize > 0)
8253          allocate_stack(common, stacksize);
8254    
8255        stacksize = 0;
8256        if (repeat_type == OP_MINUPTO)
8257        {        {
8258        if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0)        /* TMP2 was set above. */
8259          allocate_stack(common, stacksize);        OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);
8260        else        stacksize++;
         {  
         /* We know we have place at least for one item on the top of the stack. */  
         SLJIT_ASSERT(stacksize == 1);  
         OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));  
         }  
8261        }        }
8262    
     stacksize = 0;  
8263      if (ket != OP_KET || bra != OP_BRA)      if (ket != OP_KET || bra != OP_BRA)
8264        {        {
8265        if (ket != OP_KET)        if (ket != OP_KET)
# Line 8304  else if (opcode == OP_ONCE) Line 8370  else if (opcode == OP_ONCE)
8370      }      }
8371    }    }
8372    
8373  if (ket == OP_KETRMAX)  if (repeat_type == OP_EXACT)
8374      {
8375      OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
8376      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0);
8377      CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label);
8378      }
8379    else if (ket == OP_KETRMAX)
8380    {    {
8381    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
8382    if (bra != OP_BRAZERO)    if (bra != OP_BRAZERO)
8383      free_stack(common, 1);      free_stack(common, 1);
8384    
8385    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
8386    if (bra == OP_BRAZERO)    if (bra == OP_BRAZERO)
8387      {      {
# Line 8327  else if (ket == OP_KETRMIN) Line 8400  else if (ket == OP_KETRMIN)
8400    affect badly the free_stack(2) above. */    affect badly the free_stack(2) above. */
8401    if (opcode != OP_ONCE)    if (opcode != OP_ONCE)
8402      free_stack(common, 1);      free_stack(common, 1);
8403    CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rminlabel);    CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label);
8404    if (opcode == OP_ONCE)    if (opcode == OP_ONCE)
8405      free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);      free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);
8406    else if (bra == OP_BRAMINZERO)    else if (bra == OP_BRAMINZERO)
# Line 8408  static SLJIT_INLINE void compile_control Line 8481  static SLJIT_INLINE void compile_control
8481  {  {
8482  DEFINE_COMPILER;  DEFINE_COMPILER;
8483  pcre_uchar opcode = *current->cc;  pcre_uchar opcode = *current->cc;
8484    struct sljit_label *loop;
8485    struct sljit_jump *jump;
8486    
8487  SLJIT_ASSERT(common->control_head_ptr != 0);  if (opcode == OP_THEN || opcode == OP_THEN_ARG)
   
 if ((opcode == OP_THEN || opcode == OP_THEN_ARG) && common->then_trap != NULL)  
8488    {    {
8489    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);    if (common->then_trap != NULL)
8490    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);      {
8491    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, common->then_trap->start);      SLJIT_ASSERT(common->control_head_ptr != 0);
   sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_then_trap));  
   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);  
8492    
8493    OP1(SLJIT_MOV, TMP2, 0, TMP1, 0);      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
8494    OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);      OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap);
8495        OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start);
8496        jump = JUMP(SLJIT_JUMP);
8497    
8498        loop = LABEL();
8499        OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw));
8500        JUMPHERE(jump);
8501        CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop);
8502        CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop);
8503        add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));
8504        return;
8505        }
8506      else if (common->positive_assert)
8507        {
8508        add_jump(compiler, &common->positive_assert_quit, JUMP(SLJIT_JUMP));
8509        return;
8510        }
8511      }
8512    
8513    if (common->local_exit)
8514      {
8515    if (common->quit_label == NULL)    if (common->quit_label == NULL)
8516      add_jump(compiler, &common->quit, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0));      add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));
8517    else    else
8518      CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->quit_label);      JUMPTO(SLJIT_JUMP, common->quit_label);
   
   OP1(SLJIT_MOV, STACK_TOP, 0, TMP2, 0);  
   add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));  
8519    return;    return;
8520    }    }
8521    
8522  if (!common->local_exit)  if (opcode == OP_SKIP_ARG)
8523    {    {
8524      SLJIT_ASSERT(common->control_head_ptr != 0);
8525    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
8526    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
8527    sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_check_control_chain));    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2));
8528      sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark));
8529    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
8530    
8531    OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);    OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
8532    add_jump(compiler, &common->reset_match, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1));    add_jump(compiler, &common->reset_match, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1));
8533      return;
   OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);  
8534    }    }
8535    
8536  /* Commit or in recurse or accept. */  if (opcode == OP_SKIP)
8537  if (common->quit_label == NULL)    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));  
8538  else  else
8539    JUMPTO(SLJIT_JUMP, common->quit_label);    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_IMM, 0);
8540    add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP));
8541  }  }
8542    
8543  static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current)  static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current)
# Line 8632  while (current) Line 8721  while (current)
8721      case OP_PRUNE:      case OP_PRUNE:
8722      case OP_PRUNE_ARG:      case OP_PRUNE_ARG:
8723      case OP_SKIP:      case OP_SKIP:
     compile_control_verb_backtrackingpath(common, current);  
     break;  
   
8724      case OP_SKIP_ARG:      case OP_SKIP_ARG:
8725      if (!common->local_exit)      compile_control_verb_backtrackingpath(common, current);
       {  
       SLJIT_ASSERT(common->control_head_ptr != 0);  
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);  
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);  
       sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_check_control_chain));  
       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);  
   
       OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);  
       add_jump(compiler, &common->reset_match, CMP(SLJIT_C_LESS, STR_PTR, 0, SLJIT_IMM, -2));  
   
       /* May not find suitable mark. */  
       OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);  
       if (common->quit_label == NULL)  
         add_jump(compiler, &common->quit, CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, -1));  
       else  
         CMPTO(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, -1, common->quit_label);  
   
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));  
       free_stack(common, 3);  
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0);  
       }  
     else  
       {  
       /* In recurse or accept. */  
       if (common->quit_label == NULL)  
         add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));  
       else  
         JUMPTO(SLJIT_JUMP, common->quit_label);  
       }  
8726      break;      break;
8727    
8728      case OP_COMMIT:      case OP_COMMIT:
# Line 8928  SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA Line 8985  SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA
8985  common->capture_last_ptr = common->ovector_start;  common->capture_last_ptr = common->ovector_start;
8986  common->ovector_start += sizeof(sljit_sw);  common->ovector_start += sizeof(sljit_sw);
8987  #endif  #endif
8988  private_data_size = get_private_data_length(common, rootbacktrack.cc, ccend);  if (!check_opcode_types(common, rootbacktrack.cc, ccend))
 if (private_data_size < 0)  
8989    {    {
8990    SLJIT_FREE(common->optimized_cbracket);    SLJIT_FREE(common->optimized_cbracket);
8991    return;    return;
# Line 8991  if (common->capture_last_ptr != 0) Line 9047  if (common->capture_last_ptr != 0)
9047    
9048  SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));  SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
9049  common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);  common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);
9050  private_data_size += common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);  
9051  if (private_data_size > SLJIT_MAX_LOCAL_SIZE)  common->private_data_ptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(sljit_si));
9052    if (!common->private_data_ptrs)
9053    {    {
9054    SLJIT_FREE(common->optimized_cbracket);    SLJIT_FREE(common->optimized_cbracket);
9055    return;    return;
9056    }    }
9057    memset(common->private_data_ptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int));
9058    
9059  common->private_data_ptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(int));  private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);
9060  if (!common->private_data_ptrs)  set_private_data_ptrs(common, &private_data_size, ccend);
9061    if (private_data_size > SLJIT_MAX_LOCAL_SIZE)
9062    {    {
9063      SLJIT_FREE(common->private_data_ptrs);
9064    SLJIT_FREE(common->optimized_cbracket);    SLJIT_FREE(common->optimized_cbracket);
9065    return;    return;
9066    }    }
 memset(common->private_data_ptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int));  
 set_private_data_ptrs(common, common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw), ccend);  
9067    
9068  if (common->has_then)  if (common->has_then)
9069    {    {

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

  ViewVC Help
Powered by ViewVC 1.1.5