/[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 676 by ph10, Sat Aug 27 15:53:04 2011 UTC revision 696 by zherczeg, Sun Sep 18 15:09:49 2011 UTC
# Line 119  The generated code will be the following Line 119  The generated code will be the following
119   jump to D hot path   jump to D hot path
120   C fallback path   C fallback path
121   A fallback path   A fallback path
122    
123   Notice, that the order of fallback code paths are the opposite of the fast   Notice, that the order of fallback code paths are the opposite of the fast
124   code paths. In this way the topmost value on the stack is always belong   code paths. In this way the topmost value on the stack is always belong
125   to the current fallback code path. The fallback code path must check   to the current fallback code path. The fallback code path must check
# Line 152  typedef struct jit_arguments { Line 152  typedef struct jit_arguments {
152    uschar *ptr;    uschar *ptr;
153    /* Everything else after. */    /* Everything else after. */
154    int offsetcount;    int offsetcount;
155      int calllimit;
156    uschar notbol;    uschar notbol;
157    uschar noteol;    uschar noteol;
158    uschar notempty;    uschar notempty;
# Line 169  typedef struct jump_list { Line 170  typedef struct jump_list {
170    struct jump_list *next;    struct jump_list *next;
171  } jump_list;  } jump_list;
172    
173  enum stub_types { stack_alloc, max_index };  enum stub_types { stack_alloc };
174    
175  typedef struct stub_list {  typedef struct stub_list {
176    enum stub_types type;    enum stub_types type;
# Line 280  typedef struct compiler_common { Line 281  typedef struct compiler_common {
281    recurse_entry *entries;    recurse_entry *entries;
282    recurse_entry *currententry;    recurse_entry *currententry;
283    jump_list *accept;    jump_list *accept;
284      jump_list *calllimit;
285    jump_list *stackalloc;    jump_list *stackalloc;
286    jump_list *revertframes;    jump_list *revertframes;
287    jump_list *wordboundary;    jump_list *wordboundary;
# Line 326  typedef struct compare_context { Line 328  typedef struct compare_context {
328    
329  enum {  enum {
330    frame_end = 0,    frame_end = 0,
331    frame_setmaxindex = -1,    frame_setstrbegin = -1
   frame_setstrbegin = -2  
332  };  };
333    
334  /* Used for accessing the elements of the stack. */  /* Used for accessing the elements of the stack. */
# Line 341  enum { Line 342  enum {
342  #define STACK_TOP     SLJIT_TEMPORARY_REG2  #define STACK_TOP     SLJIT_TEMPORARY_REG2
343  #define STACK_LIMIT   SLJIT_GENERAL_REG3  #define STACK_LIMIT   SLJIT_GENERAL_REG3
344  #define ARGUMENTS     SLJIT_GENERAL_EREG1  #define ARGUMENTS     SLJIT_GENERAL_EREG1
345  #define MAX_INDEX     SLJIT_GENERAL_EREG2  #define CALL_COUNT    SLJIT_GENERAL_EREG2
346  #define RETURN_ADDR   SLJIT_TEMPORARY_EREG1  #define RETURN_ADDR   SLJIT_TEMPORARY_EREG1
347    
348  /* Locals layout. */  /* Locals layout. */
# Line 355  enum { Line 356  enum {
356  #define LOCALS_HEAD      (4 * sizeof(sljit_w))  #define LOCALS_HEAD      (4 * sizeof(sljit_w))
357  /* Head of the last recursion. */  /* Head of the last recursion. */
358  #define RECURSIVE_HEAD   (5 * sizeof(sljit_w))  #define RECURSIVE_HEAD   (5 * sizeof(sljit_w))
359    /* Max limit of recursions. */
360    #define CALL_LIMIT       (7 * sizeof(sljit_w))
361  /* Last known position of the requested byte. */  /* Last known position of the requested byte. */
362  #define REQ_BYTE_PTR     (6 * sizeof(sljit_w))  #define REQ_BYTE_PTR     (8 * sizeof(sljit_w))
363  /* End pointer of the first line. */  /* End pointer of the first line. */
364  #define FIRSTLINE_END    (7 * sizeof(sljit_w))  #define FIRSTLINE_END    (9 * sizeof(sljit_w))
365  /* The output vector is stored on the stack, and contains pointers  /* The output vector is stored on the stack, and contains pointers
366  to characters. The vector data is divided into two groups: the first  to characters. The vector data is divided into two groups: the first
367  group contains the start / end character pointers, and the second is  group contains the start / end character pointers, and the second is
368  the start pointers when the end of the capturing group has not yet reached. */  the start pointers when the end of the capturing group has not yet reached. */
369  #define OVECTOR_START    (8 * sizeof(sljit_w))  #define OVECTOR_START    (10 * sizeof(sljit_w))
370  #define OVECTOR(i)       (OVECTOR_START + (i) * sizeof(sljit_w))  #define OVECTOR(i)       (OVECTOR_START + (i) * sizeof(sljit_w))
371  #define OVECTOR_PRIV(i)  (common->cbraptr + (i) * sizeof(sljit_w))  #define OVECTOR_PRIV(i)  (common->cbraptr + (i) * sizeof(sljit_w))
372  #define PRIV(cc)         (common->localptrs[(cc) - common->start])  #define PRIV(cc)         (common->localptrs[(cc) - common->start])
# Line 399  cc += 1 + LINK_SIZE; Line 402  cc += 1 + LINK_SIZE;
402  return cc;  return cc;
403  }  }
404    
405  /* Functions whose might need modification for all new supported opcodes:  /* Functions whose might need modification for all new supported opcodes:
406   next_opcode   next_opcode
407   get_localspace   get_localspace
408   set_localptrs   set_localptrs
# Line 694  uschar *end; Line 697  uschar *end;
697  int length = 0;  int length = 0;
698  BOOL possessive = FALSE;  BOOL possessive = FALSE;
699  BOOL needs_frame = FALSE;  BOOL needs_frame = FALSE;
 BOOL needs_maxindex = FALSE;  
700  BOOL setsom_found = FALSE;  BOOL setsom_found = FALSE;
701    
702  if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))  if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
703    {    {
704    length = 3 + 2;    length = 3;
   needs_maxindex = TRUE;  
705    possessive = TRUE;    possessive = TRUE;
706    }    }
707    
# Line 745  while (cc < ccend) Line 746  while (cc < ccend)
746      case OP_CBRAPOS:      case OP_CBRAPOS:
747      case OP_SCBRA:      case OP_SCBRA:
748      case OP_SCBRAPOS:      case OP_SCBRAPOS:
     if (!needs_maxindex)  
       {  
       needs_maxindex = TRUE;  
       length += 2;  
       }  
749      length += 3;      length += 3;
750      cc += 1 + LINK_SIZE + 2;      cc += 1 + LINK_SIZE + 2;
751      break;      break;
# Line 774  static void init_frame(compiler_common * Line 770  static void init_frame(compiler_common *
770  /* TMP2 must contain STACK_TOP - (-STACK(stackpos)) */  /* TMP2 must contain STACK_TOP - (-STACK(stackpos)) */
771  DEFINE_COMPILER;  DEFINE_COMPILER;
772  uschar *ccend = bracketend(cc);  uschar *ccend = bracketend(cc);
 BOOL needs_maxindex = FALSE;  
773  BOOL setsom_found = FALSE;  BOOL setsom_found = FALSE;
774  int offset;  int offset;
775    
# Line 821  while (cc < ccend) Line 816  while (cc < ccend)
816      case OP_CBRAPOS:      case OP_CBRAPOS:
817      case OP_SCBRA:      case OP_SCBRA:
818      case OP_SCBRAPOS:      case OP_SCBRAPOS:
     if (!needs_maxindex)  
       {  
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmaxindex);  
       stackpos += (int)sizeof(sljit_w);  
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, MAX_INDEX, 0);  
       stackpos += (int)sizeof(sljit_w);  
       needs_maxindex = TRUE;  
       }  
819      offset = (GET2(cc, 1 + LINK_SIZE)) << 1;      offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
820      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
821      stackpos += (int)sizeof(sljit_w);      stackpos += (int)sizeof(sljit_w);
# Line 1164  while (list_item) Line 1151  while (list_item)
1151      case stack_alloc:      case stack_alloc:
1152      add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));      add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));
1153      break;      break;
   
     case max_index:  
     OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, list_item->data);  
     break;  
1154      }      }
1155    JUMPTO(SLJIT_JUMP, list_item->leave);    JUMPTO(SLJIT_JUMP, list_item->leave);
1156    list_item = list_item->next;    list_item = list_item->next;
# Line 1175  while (list_item) Line 1158  while (list_item)
1158  common->stubs = NULL;  common->stubs = NULL;
1159  }  }
1160    
1161    static SLJIT_INLINE void decrease_call_count(compiler_common *common)
1162    {
1163    DEFINE_COMPILER;
1164    
1165    OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 0, SLJIT_IMM, 1);
1166    add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));
1167    }
1168    
1169  static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)  static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
1170  {  {
1171  /* May destroy all locals and registers except TMP2. */  /* May destroy all locals and registers except TMP2. */
# Line 1204  struct sljit_label *loop; Line 1195  struct sljit_label *loop;
1195  int i;  int i;
1196  /* At this point we can freely use all temporary registers. */  /* At this point we can freely use all temporary registers. */
1197  /* TMP1 returns with begin - 1. */  /* TMP1 returns with begin - 1. */
 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, 1);  
1198  OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, 1);  OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, 1);
1199  if (length < 8)  if (length < 8)
1200    {    {
# Line 1222  else Line 1212  else
1212    }    }
1213  }  }
1214    
1215  static SLJIT_INLINE void copy_ovector(compiler_common *common)  static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
1216  {  {
1217  DEFINE_COMPILER;  DEFINE_COMPILER;
1218  struct sljit_label *loop;  struct sljit_label *loop;
1219  struct sljit_jump *earlyexit;  struct sljit_jump *earlyexit;
1220    
1221  /* At this point we can freely use all registers. */  /* At this point we can freely use all registers. */
1222    OP1(SLJIT_MOV, SLJIT_GENERAL_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
1223    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0);
1224    
1225  OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0);  OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0);
1226  OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));  OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));
1227  OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));  OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
# Line 1244  OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMP Line 1237  OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMP
1237  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
1238  JUMPTO(SLJIT_C_NOT_ZERO, loop);  JUMPTO(SLJIT_C_NOT_ZERO, loop);
1239  JUMPHERE(earlyexit);  JUMPHERE(earlyexit);
1240    
1241    /* Calculate the return value, which is the maximum ovector value. */
1242    if (topbracket > 1)
1243      {
1244      OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w));
1245      OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1);
1246    
1247      /* OVECTOR(0) is never equal to SLJIT_GENERAL_REG3. */
1248      loop = LABEL();
1249      OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * sizeof(sljit_w)));
1250      OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
1251      CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_GENERAL_REG3, 0, loop);
1252      OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0);
1253      }
1254    else
1255      OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
1256  }  }
1257    
1258  static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, uschar* cc)  static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, uschar* cc)
# Line 1985  JUMPHERE(earlyexit); Line 1994  JUMPHERE(earlyexit);
1994  sljit_emit_fast_return(compiler, RETURN_ADDR, 0);  sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1995    
1996  JUMPHERE(jump);  JUMPHERE(jump);
 jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setmaxindex);  
 /* Set max index. */  
 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));  
 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));  
 JUMPTO(SLJIT_JUMP, mainloop);  
   
 JUMPHERE(jump);  
1997  jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin);  jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin);
1998  /* Set max index. */  /* Set string begin. */
1999  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
2000  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2001  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
# Line 2370  do Line 2372  do
2372        }        }
2373      context->byteptr = 0;      context->byteptr = 0;
2374      }      }
2375    
2376  #else  #else
2377    
2378    /* Unaligned read is unsupported. */    /* Unaligned read is unsupported. */
# Line 3218  do Line 3220  do
3220        else if (cc[1] >= 0xc0)        else if (cc[1] >= 0xc0)
3221          size += _pcre_utf8_table4[cc[1] & 0x3f];          size += _pcre_utf8_table4[cc[1] & 0x3f];
3222        }        }
3223      else      else
3224  #endif  #endif
3225      if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)      if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3226        size = 0;        size = 0;
# Line 3455  if (!minimize) Line 3457  if (!minimize)
3457    
3458    JUMPHERE(zerolength);    JUMPHERE(zerolength);
3459    FALLBACK_AS(iterator_fallback)->hotpath = LABEL();    FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
3460    
3461      decrease_call_count(common);
3462    return cc;    return cc;
3463    }    }
3464    
# Line 3492  else if (max > 0) Line 3496  else if (max > 0)
3496  if (jump != NULL)  if (jump != NULL)
3497    JUMPHERE(jump);    JUMPHERE(jump);
3498  JUMPHERE(zerolength);  JUMPHERE(zerolength);
3499    
3500    decrease_call_count(common);
3501  return cc;  return cc;
3502  }  }
3503    
# Line 3827  return cc + 1 + LINK_SIZE; Line 3833  return cc + 1 + LINK_SIZE;
3833      A - Push the current STR_PTR. Needed for restoring the STR_PTR      A - Push the current STR_PTR. Needed for restoring the STR_PTR
3834          before the next alternative. Not pushed if there are no alternatives.          before the next alternative. Not pushed if there are no alternatives.
3835      M - Any values pushed by the current alternative. Can be empty, or anything.      M - Any values pushed by the current alternative. Can be empty, or anything.
3836      C - Push the previous OVECTOR(i), OVECTOR(i+1), MAX_INDEX and OVECTOR_PRIV(i) to the stack.      C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.
3837      L - Push the previous local (pointed by localptr) to the stack      L - Push the previous local (pointed by localptr) to the stack
3838     () - opional values stored on the stack     () - opional values stored on the stack
3839    ()* - optonal, can be stored multiple times    ()* - optonal, can be stored multiple times
# Line 4054  if (opcode == OP_ONCE) Line 4060  if (opcode == OP_ONCE)
4060  else if (opcode == OP_CBRA || opcode == OP_SCBRA)  else if (opcode == OP_CBRA || opcode == OP_SCBRA)
4061    {    {
4062    /* Saving the previous values. */    /* Saving the previous values. */
4063    allocate_stack(common, 4);    allocate_stack(common, 3);
4064    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
4065    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4066    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4067    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4068    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), MAX_INDEX, 0);  
4069    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4070    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), TMP1, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
   /* Update MAX_INDEX if necessary. */  
   add_stub(common, max_index, (offset >> 1) + 1, CMP(SLJIT_C_LESS, MAX_INDEX, 0, SLJIT_IMM, (offset >> 1) + 1));  
4071    }    }
4072  else if (opcode == OP_SBRA || opcode == OP_SCOND)  else if (opcode == OP_SBRA || opcode == OP_SCOND)
4073    {    {
# Line 4212  if (bra == OP_BRAMINZERO) Line 4215  if (bra == OP_BRAMINZERO)
4215    /* Continue to the normal fallback. */    /* Continue to the normal fallback. */
4216    }    }
4217    
4218    if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
4219      decrease_call_count(common);
4220    
4221  /* Skip the other alternatives. */  /* Skip the other alternatives. */
4222  while (*cc == OP_ALT)  while (*cc == OP_ALT)
4223    cc += GET(cc, 1);    cc += GET(cc, 1);
# Line 4270  framesize = get_framesize(common, cc, FA Line 4276  framesize = get_framesize(common, cc, FA
4276  FALLBACK_AS(bracketpos_fallback)->framesize = framesize;  FALLBACK_AS(bracketpos_fallback)->framesize = framesize;
4277  if (framesize < 0)  if (framesize < 0)
4278    {    {
4279    stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 3 : 1;    stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1;
4280    if (!zero)    if (!zero)
4281      stacksize++;      stacksize++;
4282    FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;    FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;
# Line 4283  if (framesize < 0) Line 4289  if (framesize < 0)
4289      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4290      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4291      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), MAX_INDEX, 0);  
4292      }      }
4293    else    else
4294      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
# Line 4341  while (*cc != OP_KETRPOS) Line 4346  while (*cc != OP_KETRPOS)
4346        {        {
4347        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
4348        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);  
       add_stub(common, max_index, (offset >> 1) + 1, CMP(SLJIT_C_LESS, MAX_INDEX, 0, SLJIT_IMM, (offset >> 1) + 1));  
4349        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
4350          OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
4351        }        }
4352      else      else
4353        {        {
# Line 4366  while (*cc != OP_KETRPOS) Line 4370  while (*cc != OP_KETRPOS)
4370        if (!zero)        if (!zero)
4371          OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);          OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4372        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);  
       add_stub(common, max_index, (offset >> 1) + 1, CMP(SLJIT_C_LESS, MAX_INDEX, 0, SLJIT_IMM, (offset >> 1) + 1));  
4373        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
4374          OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
4375        }        }
4376      else      else
4377        {        {
# Line 4436  if (!zero) Line 4439  if (!zero)
4439    
4440  /* None of them matched. */  /* None of them matched. */
4441  set_jumps(emptymatch, LABEL());  set_jumps(emptymatch, LABEL());
4442    decrease_call_count(common);
4443  return cc + 1 + LINK_SIZE;  return cc + 1 + LINK_SIZE;
4444  }  }
4445    
# Line 4696  switch(opcode) Line 4700  switch(opcode)
4700    break;    break;
4701    }    }
4702    
4703    decrease_call_count(common);
4704  return end;  return end;
4705  }  }
4706    
# Line 4746  return cc + 1; Line 4751  return cc + 1;
4751  static SLJIT_INLINE uschar *compile_close_hotpath(compiler_common *common, uschar *cc)  static SLJIT_INLINE uschar *compile_close_hotpath(compiler_common *common, uschar *cc)
4752  {  {
4753  DEFINE_COMPILER;  DEFINE_COMPILER;
 struct sljit_jump *jump;  
4754  int offset = GET2(cc, 1);  int offset = GET2(cc, 1);
4755    
4756  /* Data will be discarded anyway... */  /* Data will be discarded anyway... */
# Line 4755  if (common->currententry != NULL) Line 4759  if (common->currententry != NULL)
4759    
4760  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset));  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset));
4761  offset <<= 1;  offset <<= 1;
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);  
4762  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
4763  offset = (offset >> 1) + 1;  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
 jump = CMP(SLJIT_C_GREATER_EQUAL, MAX_INDEX, 0, SLJIT_IMM, offset);  
 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, offset);  
 JUMPHERE(jump);  
4764  return cc + 3;  return cc + 3;
4765  }  }
4766    
# Line 4939  while (cc < ccend) Line 4939  while (cc < ccend)
4939        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);
4940        }        }
4941      FALLBACK_AS(braminzero_fallback)->hotpath = LABEL();      FALLBACK_AS(braminzero_fallback)->hotpath = LABEL();
4942        if (cc[1] > OP_ASSERTBACK_NOT)
4943          decrease_call_count(common);
4944      break;      break;
4945    
4946      case OP_ONCE:      case OP_ONCE:
# Line 5525  if (offset != 0) Line 5527  if (offset != 0)
5527    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5528    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
5529    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
5530    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(3));    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(2));
5531    OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_MEM1(STACK_TOP), STACK(2));    free_stack(common, 3);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);  
   free_stack(common, 4);  
5532    }    }
5533  else if (opcode == OP_SBRA || opcode == OP_SCOND)  else if (opcode == OP_SBRA || opcode == OP_SCOND)
5534    {    {
# Line 5617  if (CURRENT_AS(bracketpos_fallback)->fra Line 5617  if (CURRENT_AS(bracketpos_fallback)->fra
5617      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5618      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
5619      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
     OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_MEM1(STACK_TOP), STACK(2));  
5620      }      }
5621    set_jumps(current->topfallbacks, LABEL());    set_jumps(current->topfallbacks, LABEL());
5622    free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize);    free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize);
# Line 5915  fallback_common rootfallback; Line 5914  fallback_common rootfallback;
5914  compiler_common common_data;  compiler_common common_data;
5915  compiler_common *common = &common_data;  compiler_common *common = &common_data;
5916  const unsigned char *tables = re->tables;  const unsigned char *tables = re->tables;
5917  pcre_study_data *study = (extra->flags & PCRE_EXTRA_STUDY_DATA) != 0 ? extra->study_data : NULL;  pcre_study_data *study;
5918  uschar *ccend;  uschar *ccend;
5919  executable_function *function;  executable_function *function;
5920  void *executable_func;  void *executable_func;
# Line 5927  struct sljit_jump *alloc_error; Line 5926  struct sljit_jump *alloc_error;
5926  struct sljit_jump *reqbyte_notfound = NULL;  struct sljit_jump *reqbyte_notfound = NULL;
5927  struct sljit_jump *empty_match;  struct sljit_jump *empty_match;
5928    
5929    SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0);
5930    study = extra->study_data;
5931    
5932  if (!tables)  if (!tables)
5933    tables = _pcre_default_tables;    tables = _pcre_default_tables;
5934    
# Line 5941  common->lcc = (sljit_w)(tables + lcc_off Line 5943  common->lcc = (sljit_w)(tables + lcc_off
5943  common->nltype = NLTYPE_FIXED;  common->nltype = NLTYPE_FIXED;
5944  switch(re->options & PCRE_NEWLINE_BITS)  switch(re->options & PCRE_NEWLINE_BITS)
5945    {    {
5946    case 0: common->newline = NEWLINE; break;   /* Compile-time default */    case 0:
5947      /* Compile-time default */
5948      switch (NEWLINE)
5949        {
5950        case -1: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
5951        case -2: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
5952        default: common->newline = NEWLINE; break;
5953        }
5954      break;
5955    case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break;    case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break;
5956    case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break;    case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break;
5957    case PCRE_NEWLINE_CR+    case PCRE_NEWLINE_CR+
# Line 5969  common->stubs = NULL; Line 5979  common->stubs = NULL;
5979  common->entries = NULL;  common->entries = NULL;
5980  common->currententry = NULL;  common->currententry = NULL;
5981  common->accept = NULL;  common->accept = NULL;
5982    common->calllimit = NULL;
5983  common->stackalloc = NULL;  common->stackalloc = NULL;
5984  common->revertframes = NULL;  common->revertframes = NULL;
5985  common->wordboundary = NULL;  common->wordboundary = NULL;
# Line 6025  OP1(SLJIT_MOV, TMP1, 0, SLJIT_GENERAL_RE Line 6036  OP1(SLJIT_MOV, TMP1, 0, SLJIT_GENERAL_RE
6036  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
6037  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
6038  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
6039    OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, calllimit));
6040  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
6041  OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));  OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
6042    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0);
6043    
6044  /* Main part of the matching */  /* Main part of the matching */
6045  if ((re->options & PCRE_ANCHORED) == 0)  if ((re->options & PCRE_ANCHORED) == 0)
# Line 6045  if ((re->flags & PCRE_REQCHSET) != 0) Line 6058  if ((re->flags & PCRE_REQCHSET) != 0)
6058    
6059  /* Store the current STR_PTR in OVECTOR(0). */  /* Store the current STR_PTR in OVECTOR(0). */
6060  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
6061    /* Copy the limit of allowed recursions. */
6062    OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT);
6063    
6064  compile_hotpath(common, rootfallback.cc, ccend, &rootfallback);  compile_hotpath(common, rootfallback.cc, ccend, &rootfallback);
6065  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
# Line 6062  if (common->accept != NULL) Line 6077  if (common->accept != NULL)
6077    set_jumps(common->accept, common->acceptlabel);    set_jumps(common->accept, common->acceptlabel);
6078    
6079  /* This means we have a match. Update the ovector. */  /* This means we have a match. Update the ovector. */
6080  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0);  copy_ovector(common, re->top_bracket + 1);
   
6081  leave = LABEL();  leave = LABEL();
 copy_ovector(common);  
 OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, MAX_INDEX, 0);  
6082  sljit_emit_return(compiler, SLJIT_UNUSED, 0);  sljit_emit_return(compiler, SLJIT_UNUSED, 0);
6083    
6084  empty_match_fallback = LABEL();  empty_match_fallback = LABEL();
# Line 6115  if (reqbyte_notfound != NULL) Line 6127  if (reqbyte_notfound != NULL)
6127    JUMPHERE(reqbyte_notfound);    JUMPHERE(reqbyte_notfound);
6128  /* Copy OVECTOR(1) to OVECTOR(0) */  /* Copy OVECTOR(1) to OVECTOR(0) */
6129  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
6130  OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);  OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
6131  JUMPTO(SLJIT_JUMP, leave);  JUMPTO(SLJIT_JUMP, leave);
6132    
6133  flush_stubs(common);  flush_stubs(common);
# Line 6168  sljit_emit_fast_return(compiler, SLJIT_M Line 6180  sljit_emit_fast_return(compiler, SLJIT_M
6180  /* Allocation failed. */  /* Allocation failed. */
6181  JUMPHERE(alloc_error);  JUMPHERE(alloc_error);
6182  /* We break the return address cache here, but this is a really rare case. */  /* We break the return address cache here, but this is a really rare case. */
6183  OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);  OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);
6184    JUMPTO(SLJIT_JUMP, leave);
6185    
6186    /* Call limit reached. */
6187    set_jumps(common->calllimit, LABEL());
6188    OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
6189  JUMPTO(SLJIT_JUMP, leave);  JUMPTO(SLJIT_JUMP, leave);
6190    
6191  if (common->revertframes != NULL)  if (common->revertframes != NULL)
# Line 6268  return convert_executable_func.call_exec Line 6285  return convert_executable_func.call_exec
6285    
6286  int  int
6287  _pcre_jit_exec(const real_pcre *re, void *executable_func,  _pcre_jit_exec(const real_pcre *re, void *executable_func,
6288    PCRE_SPTR subject, int length, int start_offset, int options, int *offsets,    PCRE_SPTR subject, int length, int start_offset, int options,
6289    int offsetcount)    int match_limit, int *offsets, int offsetcount)
6290  {  {
6291  executable_function *function = (executable_function*)executable_func;  executable_function *function = (executable_function*)executable_func;
6292  union {  union {
# Line 6285  arguments.stack = NULL; Line 6302  arguments.stack = NULL;
6302  arguments.str = subject + start_offset;  arguments.str = subject + start_offset;
6303  arguments.begin = subject;  arguments.begin = subject;
6304  arguments.end = subject + length;  arguments.end = subject + length;
6305    arguments.calllimit = match_limit; /* JIT decreases this value less times. */
6306  arguments.notbol = (options & PCRE_NOTBOL) != 0;  arguments.notbol = (options & PCRE_NOTBOL) != 0;
6307  arguments.noteol = (options & PCRE_NOTEOL) != 0;  arguments.noteol = (options & PCRE_NOTEOL) != 0;
6308  arguments.notempty = (options & PCRE_NOTEMPTY) != 0;  arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
# Line 6351  PCRE_EXP_DECL void Line 6369  PCRE_EXP_DECL void
6369  pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)  pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
6370  {  {
6371  executable_function *function;  executable_function *function;
6372  if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL)  if (extra != NULL &&
6373        (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
6374        extra->executable_jit != NULL)
6375    {    {
6376    function = (executable_function*)extra->executable_jit;    function = (executable_function*)extra->executable_jit;
6377    function->callback = callback;    function->callback = callback;
# Line 6361  if ((extra->flags & PCRE_EXTRA_EXECUTABL Line 6381  if ((extra->flags & PCRE_EXTRA_EXECUTABL
6381    
6382  #else  /* SUPPORT_JIT */  #else  /* SUPPORT_JIT */
6383    
6384  /* These are dummy functions to avoid linking errors when JIT support is not  /* These are dummy functions to avoid linking errors when JIT support is not
6385  being compiled. */  being compiled. */
6386    
6387  PCRE_EXP_DECL pcre_jit_stack *  PCRE_EXP_DECL pcre_jit_stack *

Legend:
Removed from v.676  
changed lines
  Added in v.696

  ViewVC Help
Powered by ViewVC 1.1.5