/[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 1305 by zherczeg, Fri Mar 29 09:01:20 2013 UTC revision 1306 by zherczeg, Mon Apr 1 17:04:17 2013 UTC
# Line 313  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 534  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 733  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)  
737  {  {
 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)  
 {  
 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 838  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 863  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 884  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 1015  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 1061  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_BRA || *cc == OP_CBRA || *cc == OP_ONCE || *cc == OP_ONCE_NC)
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 1156  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 1186  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 6129  pcre_uchar opcode; Line 6128  pcre_uchar opcode;
6128  int private_data_ptr = 0;  int private_data_ptr = 0;
6129  int offset = 0;  int offset = 0;
6130  int stacksize;  int stacksize;
6131    int repeat_ptr = 0, repeat_length = 0;
6132    int repeat_type = 0, repeat_count = 0;
6133  pcre_uchar *ccbegin;  pcre_uchar *ccbegin;
6134  pcre_uchar *matchingpath;  pcre_uchar *matchingpath;
6135  pcre_uchar bra = OP_BRA;  pcre_uchar bra = OP_BRA;
# Line 6152  if (*cc == OP_BRAZERO || *cc == OP_BRAMI Line 6153  if (*cc == OP_BRAZERO || *cc == OP_BRAMI
6153    
6154  opcode = *cc;  opcode = *cc;
6155  ccbegin = cc;  ccbegin = cc;
6156  matchingpath = ccbegin + 1 + LINK_SIZE;  matchingpath = bracketend(cc) - 1 - LINK_SIZE;
6157    ket = *matchingpath;
6158    if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0)
6159      {
6160      repeat_ptr = PRIVATE_DATA(matchingpath);
6161      repeat_length = PRIVATE_DATA(matchingpath + 1);
6162      repeat_type = PRIVATE_DATA(matchingpath + 2);
6163      repeat_count = PRIVATE_DATA(matchingpath + 3);
6164      SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0);
6165      if (repeat_type == OP_UPTO)
6166        ket = OP_KETRMAX;
6167      if (repeat_type == OP_MINUPTO)
6168        ket = OP_KETRMIN;
6169      }
6170    
6171  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)
6172    {    {
6173    /* Drop this bracket_backtrack. */    /* Drop this bracket_backtrack. */
6174    parent->top = backtrack->prev;    parent->top = backtrack->prev;
6175    return bracketend(cc);    return matchingpath + 1 + LINK_SIZE + repeat_length;
6176    }    }
6177    
6178  ket = *(bracketend(cc) - 1 - LINK_SIZE);  matchingpath = ccbegin + 1 + LINK_SIZE;
6179  SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);  SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
6180  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)));
6181  cc += GET(cc, 1);  cc += GET(cc, 1);
# Line 6275  if (bra == OP_BRAMINZERO) Line 6289  if (bra == OP_BRAMINZERO)
6289      }      }
6290    }    }
6291    
6292    if (repeat_type != 0)
6293      {
6294      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, repeat_count);
6295      if (repeat_type == OP_EXACT)
6296        rmaxlabel = LABEL();
6297      }
6298    
6299  if (ket == OP_KETRMIN)  if (ket == OP_KETRMIN)
6300    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();
6301    
6302  if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
6303    {    {
6304    rmaxlabel = LABEL();    rmaxlabel = LABEL();
6305    if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)    if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA && repeat_type == 0)
6306      BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmaxlabel;      BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmaxlabel;
6307    }    }
6308    
# Line 6500  if (opcode == OP_ONCE) Line 6521  if (opcode == OP_ONCE)
6521    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);
6522    
6523  stacksize = 0;  stacksize = 0;
6524    if (repeat_type == OP_MINUPTO)
6525      {
6526      /* We need to preserve the counter. TMP2 will be used below. */
6527      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
6528      stacksize++;
6529      }
6530  if (ket != OP_KET || bra != OP_BRA)  if (ket != OP_KET || bra != OP_BRA)
6531    stacksize++;    stacksize++;
6532  if (offset != 0)  if (offset != 0)
# Line 6516  if (stacksize > 0) Line 6543  if (stacksize > 0)
6543    allocate_stack(common, stacksize);    allocate_stack(common, stacksize);
6544    
6545  stacksize = 0;  stacksize = 0;
6546    if (repeat_type == OP_MINUPTO)
6547      {
6548      /* TMP2 was set above. */
6549      OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);
6550      stacksize++;
6551      }
6552    
6553  if (ket != OP_KET || bra != OP_BRA)  if (ket != OP_KET || bra != OP_BRA)
6554    {    {
6555    if (ket != OP_KET)    if (ket != OP_KET)
# Line 6545  if (offset != 0 && common->optimized_cbr Line 6579  if (offset != 0 && common->optimized_cbr
6579    
6580  if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
6581    {    {
6582    if (opcode == OP_ONCE || opcode >= OP_SBRA)    if (repeat_type != 0)
6583        {
6584        if (has_alternatives)
6585          BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
6586        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
6587        JUMPTO(SLJIT_C_NOT_ZERO, rmaxlabel);
6588        /* Drop STR_PTR for greedy plus quantifier. */
6589        if (opcode != OP_ONCE)
6590          free_stack(common, 1);
6591        }
6592      else if (opcode == OP_ONCE || opcode >= OP_SBRA)
6593      {      {
6594      if (has_alternatives)      if (has_alternatives)
6595        BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();        BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
# Line 6566  if (ket == OP_KETRMAX) Line 6610  if (ket == OP_KETRMAX)
6610    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();
6611    }    }
6612    
6613    if (repeat_type == OP_EXACT)
6614      {
6615      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
6616      JUMPTO(SLJIT_C_NOT_ZERO, rmaxlabel);
6617      }
6618    else if (repeat_type == OP_UPTO)
6619      {
6620      /* We need to preserve the counter. */
6621      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
6622      allocate_stack(common, 1);
6623      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
6624      }
6625    
6626  if (bra == OP_BRAZERO)  if (bra == OP_BRAZERO)
6627    BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();    BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();
6628    
# Line 6601  cc += 1 + LINK_SIZE; Line 6658  cc += 1 + LINK_SIZE;
6658  /* Temporarily encoding the needs_control_head in framesize. */  /* Temporarily encoding the needs_control_head in framesize. */
6659  if (opcode == OP_ONCE)  if (opcode == OP_ONCE)
6660    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);
6661  return cc;  return cc + repeat_length;
6662  }  }
6663    
6664  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 7888  if (bra == OP_BRAZERO) Line 7945  if (bra == OP_BRAZERO)
7945  static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)  static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)
7946  {  {
7947  DEFINE_COMPILER;  DEFINE_COMPILER;
7948  int opcode;  int opcode, stacksize, count;
7949  int offset = 0;  int offset = 0;
7950  int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;  int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;
7951  int stacksize;  int repeat_ptr = 0, repeat_type = 0, repeat_count = 0;
 int count;  
7952  pcre_uchar *cc = current->cc;  pcre_uchar *cc = current->cc;
7953  pcre_uchar *ccbegin;  pcre_uchar *ccbegin;
7954  pcre_uchar *ccprev;  pcre_uchar *ccprev;
# Line 7907  struct sljit_jump *brazero = NULL; Line 7963  struct sljit_jump *brazero = NULL;
7963  struct sljit_jump *once = NULL;  struct sljit_jump *once = NULL;
7964  struct sljit_jump *cond = NULL;  struct sljit_jump *cond = NULL;
7965  struct sljit_label *rminlabel = NULL;  struct sljit_label *rminlabel = NULL;
7966    struct sljit_label *exact_label = NULL;
7967    
7968  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
7969    {    {
# Line 7915  if (*cc == OP_BRAZERO || *cc == OP_BRAMI Line 7972  if (*cc == OP_BRAZERO || *cc == OP_BRAMI
7972    }    }
7973    
7974  opcode = *cc;  opcode = *cc;
7975    ccbegin = bracketend(cc) - 1 - LINK_SIZE;
7976    ket = *ccbegin;
7977    if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0)
7978      {
7979      repeat_ptr = PRIVATE_DATA(ccbegin);
7980      repeat_type = PRIVATE_DATA(ccbegin + 2);
7981      repeat_count = PRIVATE_DATA(ccbegin + 3);
7982      SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0);
7983      if (repeat_type == OP_UPTO)
7984        ket = OP_KETRMAX;
7985      if (repeat_type == OP_MINUPTO)
7986        ket = OP_KETRMIN;
7987      }
7988  ccbegin = cc;  ccbegin = cc;
 ket = *(bracketend(ccbegin) - 1 - LINK_SIZE);  
7989  cc += GET(cc, 1);  cc += GET(cc, 1);
7990  has_alternatives = *cc == OP_ALT;  has_alternatives = *cc == OP_ALT;
7991  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
# Line 7935  if (opcode == OP_ONCE) Line 8004  if (opcode == OP_ONCE)
8004    CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;    CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;
8005    }    }
8006    
8007    if (ket != OP_KET && repeat_type != 0)
8008      {
8009      /* TMP1 is used in OP_KETRMIN below. */
8010      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
8011      free_stack(common, 1);
8012      if (repeat_type == OP_UPTO)
8013        OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0, SLJIT_IMM, 1);
8014      else
8015        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0);
8016      }
8017    
8018  if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
8019    {    {
8020    if (bra == OP_BRAZERO)    if (bra == OP_BRAZERO)
# Line 7949  else if (ket == OP_KETRMIN) Line 8029  else if (ket == OP_KETRMIN)
8029    if (bra != OP_BRAMINZERO)    if (bra != OP_BRAMINZERO)
8030      {      {
8031      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
8032      if (opcode >= OP_SBRA || opcode == OP_ONCE)      if (repeat_type != 0)
8033          {
8034          /* TMP1 was set a few lines above. */
8035          CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
8036          /* Drop STR_PTR for non-greedy plus quantifier. */
8037          if (opcode != OP_ONCE)
8038            free_stack(common, 1);
8039          }
8040        else if (opcode >= OP_SBRA || opcode == OP_ONCE)
8041        {        {
8042        /* Checking zero-length iteration. */        /* Checking zero-length iteration. */
8043        if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)        if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)
# Line 7959  else if (ket == OP_KETRMIN) Line 8047  else if (ket == OP_KETRMIN)
8047          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);
8048          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);
8049          }          }
8050          /* Drop STR_PTR for non-greedy plus quantifier. */
8051        if (opcode != OP_ONCE)        if (opcode != OP_ONCE)
8052          free_stack(common, 1);          free_stack(common, 1);
8053        }        }
# Line 7966  else if (ket == OP_KETRMIN) Line 8055  else if (ket == OP_KETRMIN)
8055        JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);        JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
8056      }      }
8057    rminlabel = LABEL();    rminlabel = LABEL();
8058      if (repeat_type != 0)
8059        OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
8060    }    }
8061  else if (bra == OP_BRAZERO)  else if (bra == OP_BRAZERO)
8062    {    {
# Line 7973  else if (bra == OP_BRAZERO) Line 8064  else if (bra == OP_BRAZERO)
8064    free_stack(common, 1);    free_stack(common, 1);
8065    brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);    brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
8066    }    }
8067    else if (repeat_type == OP_EXACT)
8068      {
8069      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
8070      exact_label = LABEL();
8071      }
8072    
8073  if (offset != 0)  if (offset != 0)
8074    {    {
# Line 8120  if (has_alternatives) Line 8216  if (has_alternatives)
8216        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);
8217    
8218      stacksize = 0;      stacksize = 0;
8219        if (repeat_type == OP_MINUPTO)
8220          {
8221          /* We need to preserve the counter. TMP2 will be used below. */
8222          OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
8223          stacksize++;
8224          }
8225      if (ket != OP_KET || bra != OP_BRA)      if (ket != OP_KET || bra != OP_BRA)
8226        stacksize++;        stacksize++;
8227      if (offset != 0)      if (offset != 0)
# Line 8133  if (has_alternatives) Line 8235  if (has_alternatives)
8235        stacksize++;        stacksize++;
8236    
8237      if (stacksize > 0)      if (stacksize > 0)
8238          allocate_stack(common, stacksize);
8239    
8240        stacksize = 0;
8241        if (repeat_type == OP_MINUPTO)
8242        {        {
8243        if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0)        /* TMP2 was set above. */
8244          allocate_stack(common, stacksize);        OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);
8245        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));  
         }  
8246        }        }
8247    
     stacksize = 0;  
8248      if (ket != OP_KET || bra != OP_BRA)      if (ket != OP_KET || bra != OP_BRA)
8249        {        {
8250        if (ket != OP_KET)        if (ket != OP_KET)
# Line 8255  else if (opcode == OP_ONCE) Line 8355  else if (opcode == OP_ONCE)
8355      }      }
8356    }    }
8357    
8358  if (ket == OP_KETRMAX)  if (repeat_type == OP_EXACT)
8359      {
8360      OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
8361      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0);
8362      CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label);
8363      }
8364    else if (ket == OP_KETRMAX)
8365    {    {
8366    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
8367    if (bra != OP_BRAZERO)    if (bra != OP_BRAZERO)
8368      free_stack(common, 1);      free_stack(common, 1);
8369    
8370    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);
8371    if (bra == OP_BRAZERO)    if (bra == OP_BRAZERO)
8372      {      {
# Line 8863  SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA Line 8970  SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA
8970  common->capture_last_ptr = common->ovector_start;  common->capture_last_ptr = common->ovector_start;
8971  common->ovector_start += sizeof(sljit_sw);  common->ovector_start += sizeof(sljit_sw);
8972  #endif  #endif
8973  private_data_size = get_private_data_length(common, rootbacktrack.cc, ccend);  if (!check_opcode_types(common, rootbacktrack.cc, ccend))
 if (private_data_size < 0)  
8974    {    {
8975    SLJIT_FREE(common->optimized_cbracket);    SLJIT_FREE(common->optimized_cbracket);
8976    return;    return;
# Line 8926  if (common->capture_last_ptr != 0) Line 9032  if (common->capture_last_ptr != 0)
9032    
9033  SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));  SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
9034  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);
9035  private_data_size += common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);  
9036  if (private_data_size > SLJIT_MAX_LOCAL_SIZE)  common->private_data_ptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(sljit_si));
9037    if (!common->private_data_ptrs)
9038    {    {
9039    SLJIT_FREE(common->optimized_cbracket);    SLJIT_FREE(common->optimized_cbracket);
9040    return;    return;
9041    }    }
9042    memset(common->private_data_ptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int));
9043    
9044  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);
9045  if (!common->private_data_ptrs)  set_private_data_ptrs(common, &private_data_size, ccend);
9046    if (private_data_size > SLJIT_MAX_LOCAL_SIZE)
9047    {    {
9048      SLJIT_FREE(common->private_data_ptrs);
9049    SLJIT_FREE(common->optimized_cbracket);    SLJIT_FREE(common->optimized_cbracket);
9050    return;    return;
9051    }    }
 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);  
9052    
9053  if (common->has_then)  if (common->has_then)
9054    {    {

Legend:
Removed from v.1305  
changed lines
  Added in v.1306

  ViewVC Help
Powered by ViewVC 1.1.5