/[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 1624 by zherczeg, Fri Feb 5 13:47:43 2016 UTC revision 1629 by zherczeg, Tue Feb 9 14:22:55 2016 UTC
# Line 277  typedef struct braminzero_backtrack { Line 277  typedef struct braminzero_backtrack {
277    struct sljit_label *matchingpath;    struct sljit_label *matchingpath;
278  } braminzero_backtrack;  } braminzero_backtrack;
279    
280  typedef struct iterator_backtrack {  typedef struct char_iterator_backtrack {
281    backtrack_common common;    backtrack_common common;
282    /* Next iteration. */    /* Next iteration. */
283    struct sljit_label *matchingpath;    struct sljit_label *matchingpath;
284  } iterator_backtrack;  } char_iterator_backtrack;
285    
286    typedef struct ref_iterator_backtrack {
287      backtrack_common common;
288      /* Next iteration. */
289      struct sljit_label *matchingpath;
290    } ref_iterator_backtrack;
291    
292  typedef struct recurse_entry {  typedef struct recurse_entry {
293    struct recurse_entry *next;    struct recurse_entry *next;
# Line 325  typedef struct compiler_common { Line 331  typedef struct compiler_common {
331    /* Chain list of read-only data ptrs. */    /* Chain list of read-only data ptrs. */
332    void *read_only_data_head;    void *read_only_data_head;
333    /* Tells whether the capturing bracket is optimized. */    /* Tells whether the capturing bracket is optimized. */
334    pcre_uint8 *optimized_cbracket;    sljit_ub *optimized_cbracket;
335    /* Tells whether the starting offset is a target of then. */    /* Tells whether the starting offset is a target of then. */
336    pcre_uint8 *then_offsets;    sljit_ub *then_offsets;
337    /* Current position where a THEN must jump. */    /* Current position where a THEN must jump. */
338    then_trap_backtrack *then_trap;    then_trap_backtrack *then_trap;
339    /* Starting offset of private data for capturing brackets. */    /* Starting offset of private data for capturing brackets. */
340    int cbra_ptr;    sljit_si cbra_ptr;
341    /* Output vector starting point. Must be divisible by 2. */    /* Output vector starting point. Must be divisible by 2. */
342    int ovector_start;    sljit_si ovector_start;
343      /* Points to the starting character of the current match. */
344      sljit_si start_ptr;
345    /* Last known position of the requested byte. */    /* Last known position of the requested byte. */
346    int req_char_ptr;    sljit_si req_char_ptr;
347    /* Head of the last recursion. */    /* Head of the last recursion. */
348    int recursive_head_ptr;    sljit_si recursive_head_ptr;
349    /* First inspected character for partial matching. */    /* First inspected character for partial matching.
350    int start_used_ptr;       (Needed for avoiding zero length partial matches.) */
351      sljit_si start_used_ptr;
352    /* Starting pointer for partial soft matches. */    /* Starting pointer for partial soft matches. */
353    int hit_start;    sljit_si hit_start;
354    /* End pointer of the first line. */    /* End pointer of the first line. */
355    int first_line_end;    sljit_si first_line_end;
356    /* Points to the marked string. */    /* Points to the marked string. */
357    int mark_ptr;    sljit_si mark_ptr;
358    /* Recursive control verb management chain. */    /* Recursive control verb management chain. */
359    int control_head_ptr;    sljit_si control_head_ptr;
360    /* Points to the last matched capture block index. */    /* Points to the last matched capture block index. */
361    int capture_last_ptr;    sljit_si capture_last_ptr;
   /* Points to the starting position of the current match. */  
   int start_ptr;  
362    
363    /* Flipped and lower case tables. */    /* Flipped and lower case tables. */
364    const pcre_uint8 *fcc;    const sljit_ub *fcc;
365    sljit_sw lcc;    sljit_sw lcc;
366    /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */    /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */
367    int mode;    int mode;
# Line 366  typedef struct compiler_common { Line 373  typedef struct compiler_common {
373    BOOL has_skip_arg;    BOOL has_skip_arg;
374    /* (*THEN) is found in the pattern. */    /* (*THEN) is found in the pattern. */
375    BOOL has_then;    BOOL has_then;
   /* Needs to know the start position anytime. */  
   BOOL needs_start_ptr;  
376    /* Currently in recurse or negative assert. */    /* Currently in recurse or negative assert. */
377    BOOL local_exit;    BOOL local_exit;
378    /* Currently in a positive assert. */    /* Currently in a positive assert. */
379    BOOL positive_assert;    BOOL positive_assert;
380    /* Newline control. */    /* Newline control. */
381    int nltype;    int nltype;
382    pcre_uint32 nlmax;    sljit_ui nlmax;
383    pcre_uint32 nlmin;    sljit_ui nlmin;
384    int newline;    int newline;
385    int bsr_nltype;    int bsr_nltype;
386    pcre_uint32 bsr_nlmax;    sljit_ui bsr_nlmax;
387    pcre_uint32 bsr_nlmin;    sljit_ui bsr_nlmin;
388    /* Dollar endonly. */    /* Dollar endonly. */
389    int endonly;    int endonly;
390    /* Tables. */    /* Tables. */
# Line 419  typedef struct compiler_common { Line 424  typedef struct compiler_common {
424    BOOL utf;    BOOL utf;
425  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
426    BOOL use_ucp;    BOOL use_ucp;
427      jump_list *getucd;
428  #endif  #endif
429  #ifdef COMPILE_PCRE8  #ifdef COMPILE_PCRE8
430    jump_list *utfreadchar;    jump_list *utfreadchar;
# Line 426  typedef struct compiler_common { Line 432  typedef struct compiler_common {
432    jump_list *utfreadtype8;    jump_list *utfreadtype8;
433  #endif  #endif
434  #endif /* SUPPORT_UTF */  #endif /* SUPPORT_UTF */
 #ifdef SUPPORT_UCP  
   jump_list *getucd;  
 #endif  
435  } compiler_common;  } compiler_common;
436    
437  /* For byte_sequence_compare. */  /* For byte_sequence_compare. */
# Line 856  while (cc < ccend) Line 859  while (cc < ccend)
859      /* Fall through. */      /* Fall through. */
860    
861      case OP_PRUNE_ARG:      case OP_PRUNE_ARG:
     common->needs_start_ptr = TRUE;  
     /* Fall through. */  
   
862      case OP_MARK:      case OP_MARK:
863      if (common->mark_ptr == 0)      if (common->mark_ptr == 0)
864        {        {
# Line 875  while (cc < ccend) Line 875  while (cc < ccend)
875    
876      case OP_PRUNE:      case OP_PRUNE:
877      case OP_SKIP:      case OP_SKIP:
     common->needs_start_ptr = TRUE;  
878      cc += 1;      cc += 1;
879      break;      break;
880    
# Line 2577  else Line 2576  else
2576  JUMPHERE(jump);  JUMPHERE(jump);
2577  }  }
2578    
2579  static void peek_char(compiler_common *common, pcre_uint32 max)  static void peek_char(compiler_common *common, sljit_ui max)
2580  {  {
2581  /* Reads the character into TMP1, keeps STR_PTR.  /* Reads the character into TMP1, keeps STR_PTR.
2582  Does not check STR_END. TMP2 Destroyed. */  Does not check STR_END. TMP2 Destroyed. */
# Line 2622  if (common->utf) Line 2621  if (common->utf)
2621    
2622  #if defined SUPPORT_UTF && defined COMPILE_PCRE8  #if defined SUPPORT_UTF && defined COMPILE_PCRE8
2623    
2624  static BOOL is_char7_bitset(const pcre_uint8 *bitset, BOOL nclass)  static BOOL is_char7_bitset(const sljit_ub *bitset, BOOL nclass)
2625  {  {
2626  /* Tells whether the character codes below 128 are enough  /* Tells whether the character codes below 128 are enough
2627  to determine a match. */  to determine a match. */
2628  const pcre_uint8 value = nclass ? 0xff : 0;  const sljit_ub value = nclass ? 0xff : 0;
2629  const pcre_uint8 *end = bitset + 32;  const sljit_ub *end = bitset + 32;
2630    
2631  bitset += 16;  bitset += 16;
2632  do  do
# Line 2665  if (full_read) Line 2664  if (full_read)
2664    
2665  #endif /* SUPPORT_UTF && COMPILE_PCRE8 */  #endif /* SUPPORT_UTF && COMPILE_PCRE8 */
2666    
2667  static void read_char_range(compiler_common *common, pcre_uint32 min, pcre_uint32 max, BOOL update_str_ptr)  static void read_char_range(compiler_common *common, sljit_ui min, sljit_ui max, BOOL update_str_ptr)
2668  {  {
2669  /* Reads the precise value of a character into TMP1, if the character is  /* Reads the precise value of a character into TMP1, if the character is
2670  between min and max (c >= min && c <= max). Otherwise it returns with a value  between min and max (c >= min && c <= max). Otherwise it returns with a value
# Line 3574  while (TRUE) Line 3573  while (TRUE)
3573    }    }
3574  }  }
3575    
3576    #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
3577    
3578    static sljit_si character_to_int32(pcre_uchar chr)
3579    {
3580    sljit_si value = (sljit_si)chr;
3581    #if defined COMPILE_PCRE8
3582    #define SSE2_COMPARE_TYPE_INDEX 0
3583    return (value << 24) | (value << 16) | (value << 8) | value;
3584    #elif defined COMPILE_PCRE16
3585    #define SSE2_COMPARE_TYPE_INDEX 1
3586    return (value << 16) | value;
3587    #elif defined COMPILE_PCRE32
3588    #define SSE2_COMPARE_TYPE_INDEX 2
3589    return value;
3590    #else
3591    #error "Unsupported unit width"
3592    #endif
3593    }
3594    
3595    static SLJIT_INLINE void fast_forward_first_char2_sse2(compiler_common *common, pcre_uchar char1, pcre_uchar char2)
3596    {
3597    DEFINE_COMPILER;
3598    struct sljit_label *start;
3599    struct sljit_jump *quit[3];
3600    struct sljit_jump *nomatch;
3601    sljit_ub instruction[8];
3602    sljit_si tmp1_ind = sljit_get_register_index(TMP1);
3603    sljit_si tmp2_ind = sljit_get_register_index(TMP2);
3604    sljit_si str_ptr_ind = sljit_get_register_index(STR_PTR);
3605    BOOL load_twice = FALSE;
3606    pcre_uchar bit;
3607    
3608    bit = char1 ^ char2;
3609    if (!is_powerof2(bit))
3610      bit = 0;
3611    
3612    if ((char1 != char2) && bit == 0)
3613      load_twice = TRUE;
3614    
3615    quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
3616    
3617    /* First part (unaligned start) */
3618    
3619    OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
3620    
3621    SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1);
3622    
3623    /* MOVD xmm, r/m32 */
3624    instruction[0] = 0x66;
3625    instruction[1] = 0x0f;
3626    instruction[2] = 0x6e;
3627    instruction[3] = 0xc0 | (2 << 3) | tmp1_ind;
3628    sljit_emit_op_custom(compiler, instruction, 4);
3629    
3630    if (char1 != char2)
3631      {
3632      OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
3633    
3634      /* MOVD xmm, r/m32 */
3635      instruction[3] = 0xc0 | (3 << 3) | tmp1_ind;
3636      sljit_emit_op_custom(compiler, instruction, 4);
3637      }
3638    
3639    /* PSHUFD xmm1, xmm2/m128, imm8 */
3640    instruction[2] = 0x70;
3641    instruction[3] = 0xc0 | (2 << 3) | 2;
3642    instruction[4] = 0;
3643    sljit_emit_op_custom(compiler, instruction, 5);
3644    
3645    if (char1 != char2)
3646      {
3647      /* PSHUFD xmm1, xmm2/m128, imm8 */
3648      instruction[3] = 0xc0 | (3 << 3) | 3;
3649      instruction[4] = 0;
3650      sljit_emit_op_custom(compiler, instruction, 5);
3651      }
3652    
3653    OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 0xf);
3654    OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
3655    
3656    /* MOVDQA xmm1, xmm2/m128 */
3657    #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
3658    
3659    if (str_ptr_ind < 8)
3660      {
3661      instruction[2] = 0x6f;
3662      instruction[3] = (0 << 3) | str_ptr_ind;
3663      sljit_emit_op_custom(compiler, instruction, 4);
3664    
3665      if (load_twice)
3666        {
3667        instruction[3] = (1 << 3) | str_ptr_ind;
3668        sljit_emit_op_custom(compiler, instruction, 4);
3669        }
3670      }
3671    else
3672      {
3673      instruction[1] = 0x41;
3674      instruction[2] = 0x0f;
3675      instruction[3] = 0x6f;
3676      instruction[4] = (0 << 3) | (str_ptr_ind & 0x7);
3677      sljit_emit_op_custom(compiler, instruction, 5);
3678    
3679      if (load_twice)
3680        {
3681        instruction[4] = (1 << 3) | str_ptr_ind;
3682        sljit_emit_op_custom(compiler, instruction, 5);
3683        }
3684      instruction[1] = 0x0f;
3685      }
3686    
3687    #else
3688    
3689    instruction[2] = 0x6f;
3690    instruction[3] = (0 << 3) | str_ptr_ind;
3691    sljit_emit_op_custom(compiler, instruction, 4);
3692    
3693    if (load_twice)
3694      {
3695      instruction[3] = (1 << 3) | str_ptr_ind;
3696      sljit_emit_op_custom(compiler, instruction, 4);
3697      }
3698    
3699    #endif
3700    
3701    if (bit != 0)
3702      {
3703      /* POR xmm1, xmm2/m128 */
3704      instruction[2] = 0xeb;
3705      instruction[3] = 0xc0 | (0 << 3) | 3;
3706      sljit_emit_op_custom(compiler, instruction, 4);
3707      }
3708    
3709    /* PCMPEQB/W/D xmm1, xmm2/m128 */
3710    instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
3711    instruction[3] = 0xc0 | (0 << 3) | 2;
3712    sljit_emit_op_custom(compiler, instruction, 4);
3713    
3714    if (load_twice)
3715      {
3716      instruction[3] = 0xc0 | (1 << 3) | 3;
3717      sljit_emit_op_custom(compiler, instruction, 4);
3718      }
3719    
3720    /* PMOVMSKB reg, xmm */
3721    instruction[2] = 0xd7;
3722    instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
3723    sljit_emit_op_custom(compiler, instruction, 4);
3724    
3725    if (load_twice)
3726      {
3727      OP1(SLJIT_MOV, TMP3, 0, TMP2, 0);
3728      instruction[3] = 0xc0 | (tmp2_ind << 3) | 1;
3729      sljit_emit_op_custom(compiler, instruction, 4);
3730    
3731      OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
3732      OP1(SLJIT_MOV, TMP2, 0, TMP3, 0);
3733      }
3734    
3735    OP2(SLJIT_ASHR, TMP1, 0, TMP1, 0, TMP2, 0);
3736    
3737    /* BSF r32, r/m32 */
3738    instruction[0] = 0x0f;
3739    instruction[1] = 0xbc;
3740    instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
3741    sljit_emit_op_custom(compiler, instruction, 3);
3742    
3743    nomatch = JUMP(SLJIT_ZERO);
3744    
3745    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
3746    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
3747    quit[1] = JUMP(SLJIT_JUMP);
3748    
3749    JUMPHERE(nomatch);
3750    
3751    start = LABEL();
3752    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
3753    quit[2] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
3754    
3755    /* Second part (aligned) */
3756    
3757    instruction[0] = 0x66;
3758    instruction[1] = 0x0f;
3759    
3760    /* MOVDQA xmm1, xmm2/m128 */
3761    #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
3762    
3763    if (str_ptr_ind < 8)
3764      {
3765      instruction[2] = 0x6f;
3766      instruction[3] = (0 << 3) | str_ptr_ind;
3767      sljit_emit_op_custom(compiler, instruction, 4);
3768    
3769      if (load_twice)
3770        {
3771        instruction[3] = (1 << 3) | str_ptr_ind;
3772        sljit_emit_op_custom(compiler, instruction, 4);
3773        }
3774      }
3775    else
3776      {
3777      instruction[1] = 0x41;
3778      instruction[2] = 0x0f;
3779      instruction[3] = 0x6f;
3780      instruction[4] = (0 << 3) | (str_ptr_ind & 0x7);
3781      sljit_emit_op_custom(compiler, instruction, 5);
3782    
3783      if (load_twice)
3784        {
3785        instruction[4] = (1 << 3) | str_ptr_ind;
3786        sljit_emit_op_custom(compiler, instruction, 5);
3787        }
3788      instruction[1] = 0x0f;
3789      }
3790    
3791    #else
3792    
3793    instruction[2] = 0x6f;
3794    instruction[3] = (0 << 3) | str_ptr_ind;
3795    sljit_emit_op_custom(compiler, instruction, 4);
3796    
3797    if (load_twice)
3798      {
3799      instruction[3] = (1 << 3) | str_ptr_ind;
3800      sljit_emit_op_custom(compiler, instruction, 4);
3801      }
3802    
3803    #endif
3804    
3805    if (bit != 0)
3806      {
3807      /* POR xmm1, xmm2/m128 */
3808      instruction[2] = 0xeb;
3809      instruction[3] = 0xc0 | (0 << 3) | 3;
3810      sljit_emit_op_custom(compiler, instruction, 4);
3811      }
3812    
3813    /* PCMPEQB/W/D xmm1, xmm2/m128 */
3814    instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
3815    instruction[3] = 0xc0 | (0 << 3) | 2;
3816    sljit_emit_op_custom(compiler, instruction, 4);
3817    
3818    if (load_twice)
3819      {
3820      instruction[3] = 0xc0 | (1 << 3) | 3;
3821      sljit_emit_op_custom(compiler, instruction, 4);
3822      }
3823    
3824    /* PMOVMSKB reg, xmm */
3825    instruction[2] = 0xd7;
3826    instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
3827    sljit_emit_op_custom(compiler, instruction, 4);
3828    
3829    if (load_twice)
3830      {
3831      instruction[3] = 0xc0 | (tmp2_ind << 3) | 1;
3832      sljit_emit_op_custom(compiler, instruction, 4);
3833    
3834      OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
3835      }
3836    
3837    /* BSF r32, r/m32 */
3838    instruction[0] = 0x0f;
3839    instruction[1] = 0xbc;
3840    instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
3841    sljit_emit_op_custom(compiler, instruction, 3);
3842    
3843    JUMPTO(SLJIT_ZERO, start);
3844    
3845    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
3846    
3847    start = LABEL();
3848    SET_LABEL(quit[0], start);
3849    SET_LABEL(quit[1], start);
3850    SET_LABEL(quit[2], start);
3851    }
3852    
3853    #undef SSE2_COMPARE_TYPE_INDEX
3854    
3855    #endif
3856    
3857    static void fast_forward_first_char2(compiler_common *common, pcre_uchar char1, pcre_uchar char2, sljit_si offset)
3858    {
3859    DEFINE_COMPILER;
3860    struct sljit_label *start;
3861    struct sljit_jump *quit;
3862    struct sljit_jump *found;
3863    pcre_uchar mask;
3864    #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
3865    struct sljit_label *utf_start = NULL;
3866    struct sljit_jump *utf_quit = NULL;
3867    #endif
3868    BOOL has_first_line_end = (common->first_line_end != 0);
3869    
3870    if (offset > 0)
3871      OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
3872    
3873    if (has_first_line_end)
3874      {
3875      OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
3876    
3877      OP2(SLJIT_ADD, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end, SLJIT_IMM, IN_UCHARS(offset + 1));
3878    #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
3879      if (sljit_x86_is_cmov_available())
3880        {
3881        OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0);
3882        sljit_x86_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0);
3883        }
3884    #endif
3885        {
3886        quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP3, 0);
3887        OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
3888        JUMPHERE(quit);
3889        }
3890      }
3891    
3892    #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
3893    if (common->utf && offset > 0)
3894      utf_start = LABEL();
3895    #endif
3896    
3897    #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
3898    
3899    /* SSE2 accelerated first character search. */
3900    
3901    if (sljit_x86_is_sse2_available())
3902      {
3903      fast_forward_first_char2_sse2(common, char1, char2);
3904    
3905      SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE || offset == 0);
3906      if (common->mode == JIT_COMPILE)
3907        {
3908        /* In complete mode, we don't need to run a match when STR_PTR == STR_END. */
3909        SLJIT_ASSERT(common->forced_quit_label == NULL);
3910        OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
3911        add_jump(compiler, &common->forced_quit, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
3912    
3913    #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
3914        if (common->utf && offset > 0)
3915          {
3916          SLJIT_ASSERT(common->mode == JIT_COMPILE);
3917    
3918          OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
3919          OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
3920    #if defined COMPILE_PCRE8
3921          OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
3922          CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start);
3923    #elif defined COMPILE_PCRE16
3924          OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
3925          CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start);
3926    #else
3927    #error "Unknown code width"
3928    #endif
3929          OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
3930          }
3931    #endif
3932    
3933        if (offset > 0)
3934          OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
3935        }
3936      else if (sljit_x86_is_cmov_available())
3937        {
3938        OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
3939        sljit_x86_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, has_first_line_end ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_first_line_end ? common->first_line_end : 0);
3940        }
3941      else
3942        {
3943        quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
3944        OP1(SLJIT_MOV, STR_PTR, 0, has_first_line_end ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_first_line_end ? common->first_line_end : 0);
3945        JUMPHERE(quit);
3946        }
3947    
3948      if (has_first_line_end)
3949        OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
3950      return;
3951      }
3952    
3953    #endif
3954    
3955    quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
3956    
3957    start = LABEL();
3958    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
3959    
3960    if (char1 == char2)
3961      found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1);
3962    else
3963      {
3964      mask = char1 ^ char2;
3965      if (is_powerof2(mask))
3966        {
3967        OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);
3968        found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask);
3969        }
3970      else
3971        {
3972        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char1);
3973        OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
3974        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char2);
3975        OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
3976        found = JUMP(SLJIT_NOT_ZERO);
3977        }
3978      }
3979    
3980    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
3981    CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, start);
3982    
3983    #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
3984    if (common->utf && offset > 0)
3985      utf_quit = JUMP(SLJIT_JUMP);
3986    #endif
3987    
3988    JUMPHERE(found);
3989    
3990    #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
3991    if (common->utf && offset > 0)
3992      {
3993      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
3994      OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
3995    #if defined COMPILE_PCRE8
3996      OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
3997      CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start);
3998    #elif defined COMPILE_PCRE16
3999      OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
4000      CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start);
4001    #else
4002    #error "Unknown code width"
4003    #endif
4004      OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
4005      JUMPHERE(utf_quit);
4006      }
4007    #endif
4008    
4009    JUMPHERE(quit);
4010    
4011    if (has_first_line_end)
4012      {
4013      quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
4014      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);
4015      if (offset > 0)
4016        OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
4017      JUMPHERE(quit);
4018      OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
4019      }
4020    
4021    if (offset > 0)
4022      OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
4023    }
4024    
4025  static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common, BOOL firstline)  static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common, BOOL firstline)
4026  {  {
4027  DEFINE_COMPILER;  DEFINE_COMPILER;
# Line 3818  return TRUE; Line 4266  return TRUE;
4266  #undef MAX_N_CHARS  #undef MAX_N_CHARS
4267  #undef MAX_N_BYTES  #undef MAX_N_BYTES
4268    
4269  static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline)  static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless)
4270  {  {
4271  DEFINE_COMPILER;  pcre_uchar oc;
 struct sljit_label *start;  
 struct sljit_jump *quit;  
 struct sljit_jump *found;  
 pcre_uchar oc, bit;  
   
 if (firstline)  
   {  
   SLJIT_ASSERT(common->first_line_end != 0);  
   OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);  
   OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);  
   }  
   
 start = LABEL();  
 quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);  
 OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);  
4272    
4273  oc = first_char;  oc = first_char;
4274  if (caseless)  if (caseless)
4275    {    {
4276    oc = TABLE_GET(first_char, common->fcc, first_char);    oc = TABLE_GET(first_char, common->fcc, first_char);
4277  #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)  #if defined SUPPORT_UTF && !defined COMPILE_PCRE8
4278    if (first_char > 127 && common->utf)    if (first_char > 127 && common->utf)
4279      oc = UCD_OTHERCASE(first_char);      oc = UCD_OTHERCASE(first_char);
4280  #endif  #endif
4281    }    }
 if (first_char == oc)  
   found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, first_char);  
 else  
   {  
   bit = first_char ^ oc;  
   if (is_powerof2(bit))  
     {  
     OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit);  
     found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit);  
     }  
   else  
     {  
     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char);  
     OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);  
     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);  
     OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);  
     found = JUMP(SLJIT_NOT_ZERO);  
     }  
   }  
   
 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));  
 JUMPTO(SLJIT_JUMP, start);  
 JUMPHERE(found);  
 JUMPHERE(quit);  
4282    
4283  if (firstline)  fast_forward_first_char2(common, first_char, oc, 0);
   OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);  
4284  }  }
4285    
4286  static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline)  static SLJIT_INLINE void fast_forward_newline(compiler_common *common)
4287  {  {
4288  DEFINE_COMPILER;  DEFINE_COMPILER;
4289  struct sljit_label *loop;  struct sljit_label *loop;
# Line 3886  struct sljit_jump *foundcr = NULL; Line 4294  struct sljit_jump *foundcr = NULL;
4294  struct sljit_jump *notfoundnl;  struct sljit_jump *notfoundnl;
4295  jump_list *newline = NULL;  jump_list *newline = NULL;
4296    
4297  if (firstline)  if (common->first_line_end != 0)
4298    {    {
   SLJIT_ASSERT(common->first_line_end != 0);  
4299    OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);    OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
4300    OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);    OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);
4301    }    }
# Line 3921  if (common->nltype == NLTYPE_FIXED && co Line 4328  if (common->nltype == NLTYPE_FIXED && co
4328    JUMPHERE(firstchar);    JUMPHERE(firstchar);
4329    JUMPHERE(lastchar);    JUMPHERE(lastchar);
4330    
4331    if (firstline)    if (common->first_line_end != 0)
4332      OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);      OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
4333    return;    return;
4334    }    }
# Line 3959  if (common->nltype == NLTYPE_ANY || comm Line 4366  if (common->nltype == NLTYPE_ANY || comm
4366  JUMPHERE(lastchar);  JUMPHERE(lastchar);
4367  JUMPHERE(firstchar);  JUMPHERE(firstchar);
4368    
4369  if (firstline)  if (common->first_line_end != 0)
4370    OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);    OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
4371  }  }
4372    
4373  static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks);  static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks);
4374    
4375  static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, pcre_uint8 *start_bits, BOOL firstline)  static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_ub *start_bits)
4376  {  {
4377  DEFINE_COMPILER;  DEFINE_COMPILER;
4378  struct sljit_label *start;  struct sljit_label *start;
# Line 3976  jump_list *matches = NULL; Line 4383  jump_list *matches = NULL;
4383  struct sljit_jump *jump;  struct sljit_jump *jump;
4384  #endif  #endif
4385    
4386  if (firstline)  if (common->first_line_end != 0)
4387    {    {
   SLJIT_ASSERT(common->first_line_end != 0);  
4388    OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0);    OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0);
4389    OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);    OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);
4390    }    }
# Line 4038  if (matches != NULL) Line 4444  if (matches != NULL)
4444    set_jumps(matches, LABEL());    set_jumps(matches, LABEL());
4445  JUMPHERE(quit);  JUMPHERE(quit);
4446    
4447  if (firstline)  if (common->first_line_end != 0)
4448    OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0);    OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0);
4449  }  }
4450    
# Line 4781  return cc; Line 5187  return cc;
5187      } \      } \
5188    charoffset = (value);    charoffset = (value);
5189    
5190    static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr);
5191    
5192  static void compile_xclass_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)  static void compile_xclass_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
5193  {  {
5194  DEFINE_COMPILER;  DEFINE_COMPILER;
# Line 4797  BOOL utf = common->utf; Line 5205  BOOL utf = common->utf;
5205  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
5206  BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;  BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
5207  BOOL charsaved = FALSE;  BOOL charsaved = FALSE;
5208  int typereg = TMP1, scriptreg = TMP1;  int typereg = TMP1;
5209  const pcre_uint32 *other_cases;  const sljit_ui *other_cases;
5210  sljit_uw typeoffset;  sljit_uw typeoffset;
5211  #endif  #endif
5212    
# Line 4860  while (*cc != XCL_END) Line 5268  while (*cc != XCL_END)
5268      switch(*cc)      switch(*cc)
5269        {        {
5270        case PT_ANY:        case PT_ANY:
5271          /* Any either accepts everything or ignored. */
5272          if (cc[-1] == XCL_PROP)
5273            {
5274            compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE);
5275            if (list == backtracks)
5276              add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
5277            return;
5278            }
5279        break;        break;
5280    
5281        case PT_LAMP:        case PT_LAMP:
# Line 4896  while (*cc != XCL_END) Line 5312  while (*cc != XCL_END)
5312      }      }
5313  #endif  #endif
5314    }    }
5315    SLJIT_ASSERT(compares > 0);
5316    
5317  /* We are not necessary in utf mode even in 8 bit mode. */  /* We are not necessary in utf mode even in 8 bit mode. */
5318  cc = ccbegin;  cc = ccbegin;
# Line 4929  if ((cc[-1] & XCL_HASPROP) == 0) Line 5346  if ((cc[-1] & XCL_HASPROP) == 0)
5346    }    }
5347  else if ((cc[-1] & XCL_MAP) != 0)  else if ((cc[-1] & XCL_MAP) != 0)
5348    {    {
5349    OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);    OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
5350  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
5351    charsaved = TRUE;    charsaved = TRUE;
5352  #endif  #endif
# Line 4954  else if ((cc[-1] & XCL_MAP) != 0) Line 5371  else if ((cc[-1] & XCL_MAP) != 0)
5371        JUMPHERE(jump);        JUMPHERE(jump);
5372      }      }
5373    
5374    OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);    OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
5375    cc += 32 / sizeof(pcre_uchar);    cc += 32 / sizeof(pcre_uchar);
5376    }    }
5377    
5378  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
 /* Simple register allocation. TMP1 is preferred if possible. */  
5379  if (needstype || needsscript)  if (needstype || needsscript)
5380    {    {
5381    if (needschar && !charsaved)    if (needschar && !charsaved)
5382      OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);      OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
5383    add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));  
5384    if (needschar)    OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
5385      OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
5386      OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
5387      OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
5388      OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
5389      OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
5390      OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
5391    
5392      /* Before anything else, we deal with scripts. */
5393      if (needsscript)
5394      {      {
5395      if (needstype)      OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
5396        OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
5397    
5398        ccbegin = cc;
5399    
5400        while (*cc != XCL_END)
5401        {        {
5402        OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);        if (*cc == XCL_SINGLE)
5403        typereg = RETURN_ADDR;          {
5404            cc ++;
5405            GETCHARINCTEST(c, cc);
5406            }
5407          else if (*cc == XCL_RANGE)
5408            {
5409            cc ++;
5410            GETCHARINCTEST(c, cc);
5411            GETCHARINCTEST(c, cc);
5412            }
5413          else
5414            {
5415            SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
5416            cc++;
5417            if (*cc == PT_SC)
5418              {
5419              compares--;
5420              invertcmp = (compares == 0 && list != backtracks);
5421              if (cc[-1] == XCL_NOTPROP)
5422                invertcmp ^= 0x1;
5423              jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]);
5424              add_jump(compiler, compares > 0 ? list : backtracks, jump);
5425              }
5426            cc += 2;
5427            }
5428        }        }
5429    
5430      if (needsscript)      cc = ccbegin;
5431        scriptreg = TMP3;      }
     OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);  
     }  
   else if (needstype && needsscript)  
     scriptreg = TMP3;  
   /* In all other cases only one of them was specified, and that can goes to TMP1. */  
5432    
5433    if (needsscript)    if (needschar)
5434        {
5435        OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
5436        }
5437    
5438      if (needstype)
5439      {      {
5440      if (scriptreg == TMP1)      if (!needschar)
5441        {        {
5442        OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));        OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
5443        OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3);        OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
5444        }        }
5445      else      else
5446        {        {
5447        OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);        OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
5448        OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));        OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
5449        OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0);        typereg = RETURN_ADDR;
5450        }        }
5451      }      }
5452    }    }
# Line 5070  while (*cc != XCL_END) Line 5524  while (*cc != XCL_END)
5524      switch(*cc)      switch(*cc)
5525        {        {
5526        case PT_ANY:        case PT_ANY:
5527        if (list != backtracks)        if (!invertcmp)
5528          {          jump = JUMP(SLJIT_JUMP);
         if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))  
           continue;  
         }  
       else if (cc[-1] == XCL_NOTPROP)  
         continue;  
       jump = JUMP(SLJIT_JUMP);  
5529        break;        break;
5530    
5531        case PT_LAMP:        case PT_LAMP:
# Line 5101  while (*cc != XCL_END) Line 5549  while (*cc != XCL_END)
5549        break;        break;
5550    
5551        case PT_SC:        case PT_SC:
5552        jump = CMP(SLJIT_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]);        compares++;
5553          /* Do nothing. */
5554        break;        break;
5555    
5556        case PT_SPACE:        case PT_SPACE:
# Line 5267  while (*cc != XCL_END) Line 5716  while (*cc != XCL_END)
5716        OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);        OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
5717        jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);        jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
5718        break;        break;
5719    
5720          default:
5721          SLJIT_ASSERT_STOP();
5722          break;
5723        }        }
5724      cc += 2;      cc += 2;
5725      }      }
# Line 6128  pcre_uchar *ccbegin = cc; Line 6581  pcre_uchar *ccbegin = cc;
6581  int min = 0, max = 0;  int min = 0, max = 0;
6582  BOOL minimize;  BOOL minimize;
6583    
6584  PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);  PUSH_BACKTRACK(sizeof(ref_iterator_backtrack), cc, NULL);
6585    
6586  if (ref)  if (ref)
6587    offset = GET2(cc, 1) << 1;    offset = GET2(cc, 1) << 1;
# Line 6248  if (!minimize) Line 6701  if (!minimize)
6701      }      }
6702    
6703    JUMPHERE(zerolength);    JUMPHERE(zerolength);
6704    BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();    BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();
6705    
6706    count_match(common);    count_match(common);
6707    return cc;    return cc;
# Line 6294  else Line 6747  else
6747      }      }
6748    }    }
6749    
6750  BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();  BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();
6751  if (max > 0)  if (max > 0)
6752    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
6753    
# Line 6308  if (min > 1) Line 6761  if (min > 1)
6761    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
6762    OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);    OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
6763    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
6764    CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(iterator_backtrack)->matchingpath);    CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(ref_iterator_backtrack)->matchingpath);
6765    }    }
6766  else if (max > 0)  else if (max > 0)
6767    OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);    OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
# Line 7598  while (*cc == OP_ALT) Line 8051  while (*cc == OP_ALT)
8051    cc += GET(cc, 1);    cc += GET(cc, 1);
8052  cc += 1 + LINK_SIZE;  cc += 1 + LINK_SIZE;
8053    
 /* Temporarily encoding the needs_control_head in framesize. */  
8054  if (opcode == OP_ONCE)  if (opcode == OP_ONCE)
8055      {
8056      /* We temporarily encode the needs_control_head in the lowest bit.
8057         Note: on the target architectures of SLJIT the ((x << 1) >> 1) returns
8058         the same value for small signed numbers (including negative numbers). */
8059    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);
8060      }
8061  return cc + repeat_length;  return cc + repeat_length;
8062  }  }
8063    
# Line 8002  int offset0 = (private_data_ptr == 0) ? Line 8459  int offset0 = (private_data_ptr == 0) ?
8459  int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);  int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);
8460  int tmp_base, tmp_offset;  int tmp_base, tmp_offset;
8461    
8462  PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);  PUSH_BACKTRACK(sizeof(char_iterator_backtrack), cc, NULL);
8463    
8464  cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &min, &end);  cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &min, &end);
8465    
8466  switch(type)  if (type != OP_EXTUNI)
8467    {    {
   case OP_NOT_DIGIT:  
   case OP_DIGIT:  
   case OP_NOT_WHITESPACE:  
   case OP_WHITESPACE:  
   case OP_NOT_WORDCHAR:  
   case OP_WORDCHAR:  
   case OP_ANY:  
   case OP_ALLANY:  
   case OP_ANYBYTE:  
   case OP_ANYNL:  
   case OP_NOT_HSPACE:  
   case OP_HSPACE:  
   case OP_NOT_VSPACE:  
   case OP_VSPACE:  
   case OP_CHAR:  
   case OP_CHARI:  
   case OP_NOT:  
   case OP_NOTI:  
   case OP_CLASS:  
   case OP_NCLASS:  
8468    tmp_base = TMP3;    tmp_base = TMP3;
8469    tmp_offset = 0;    tmp_offset = 0;
8470    break;    }
8471    else
8472    default:    {
   SLJIT_ASSERT_STOP();  
   /* Fall through. */  
   
   case OP_EXTUNI:  
   case OP_XCLASS:  
   case OP_NOTPROP:  
   case OP_PROP:  
8473    tmp_base = SLJIT_MEM1(SLJIT_SP);    tmp_base = SLJIT_MEM1(SLJIT_SP);
8474    tmp_offset = POSSESSIVE0;    tmp_offset = POSSESSIVE0;
   break;  
8475    }    }
8476    
8477  switch(opcode)  switch(opcode)
# Line 8122  switch(opcode) Line 8551  switch(opcode)
8551        add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS, base, offset1, SLJIT_IMM, min + 1));        add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS, base, offset1, SLJIT_IMM, min + 1));
8552      OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);      OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
8553      }      }
8554    BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();    BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
8555    break;    break;
8556    
8557    case OP_MINSTAR:    case OP_MINSTAR:
# Line 8132  switch(opcode) Line 8561  switch(opcode)
8561    if (private_data_ptr == 0)    if (private_data_ptr == 0)
8562      allocate_stack(common, 1);      allocate_stack(common, 1);
8563    OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);    OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
8564    BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();    BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
8565    break;    break;
8566    
8567    case OP_MINUPTO:    case OP_MINUPTO:
# Line 8143  switch(opcode) Line 8572  switch(opcode)
8572    OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, 1);    OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, 1);
8573    if (opcode == OP_CRMINRANGE)    if (opcode == OP_CRMINRANGE)
8574      add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));      add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
8575    BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();    BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
8576    break;    break;
8577    
8578    case OP_QUERY:    case OP_QUERY:
# Line 8153  switch(opcode) Line 8582  switch(opcode)
8582    OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);    OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
8583    if (opcode == OP_QUERY)    if (opcode == OP_QUERY)
8584      compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE);      compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE);
8585    BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();    BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
8586    break;    break;
8587    
8588    case OP_EXACT:    case OP_EXACT:
# Line 8712  switch(opcode) Line 9141  switch(opcode)
9141      set_jumps(current->topbacktracks, LABEL());      set_jumps(current->topbacktracks, LABEL());
9142      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
9143      free_stack(common, 1);      free_stack(common, 1);
9144      CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);      CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath);
9145      }      }
9146    else    else
9147      {      {
# Line 8732  switch(opcode) Line 9161  switch(opcode)
9161        }        }
9162      skip_char_back(common);      skip_char_back(common);
9163      OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);      OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
9164      JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);      JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
9165      if (opcode == OP_CRRANGE)      if (opcode == OP_CRRANGE)
9166        set_jumps(current->topbacktracks, LABEL());        set_jumps(current->topbacktracks, LABEL());
9167      JUMPHERE(jump);      JUMPHERE(jump);
# Line 8748  switch(opcode) Line 9177  switch(opcode)
9177    OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);    OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
9178    compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);    compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);
9179    OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);    OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
9180    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);    JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
9181    set_jumps(jumplist, LABEL());    set_jumps(jumplist, LABEL());
9182    if (private_data_ptr == 0)    if (private_data_ptr == 0)
9183      free_stack(common, 1);      free_stack(common, 1);
# Line 8775  switch(opcode) Line 9204  switch(opcode)
9204      CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min + 1, label);      CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min + 1, label);
9205    
9206    if (opcode == OP_CRMINRANGE && max == 0)    if (opcode == OP_CRMINRANGE && max == 0)
9207      JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);      JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
9208    else    else
9209      CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, max + 2, CURRENT_AS(iterator_backtrack)->matchingpath);      CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, max + 2, CURRENT_AS(char_iterator_backtrack)->matchingpath);
9210    
9211    set_jumps(jumplist, LABEL());    set_jumps(jumplist, LABEL());
9212    if (private_data_ptr == 0)    if (private_data_ptr == 0)
# Line 8787  switch(opcode) Line 9216  switch(opcode)
9216    case OP_QUERY:    case OP_QUERY:
9217    OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);    OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
9218    OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);    OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
9219    CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);    CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath);
9220    jump = JUMP(SLJIT_JUMP);    jump = JUMP(SLJIT_JUMP);
9221    set_jumps(current->topbacktracks, LABEL());    set_jumps(current->topbacktracks, LABEL());
9222    OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);    OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
9223    OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);    OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
9224    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);    JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
9225    JUMPHERE(jump);    JUMPHERE(jump);
9226    if (private_data_ptr == 0)    if (private_data_ptr == 0)
9227      free_stack(common, 1);      free_stack(common, 1);
# Line 8803  switch(opcode) Line 9232  switch(opcode)
9232    OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);    OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
9233    jump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);    jump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
9234    compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);    compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);
9235    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);    JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
9236    set_jumps(jumplist, LABEL());    set_jumps(jumplist, LABEL());
9237    JUMPHERE(jump);    JUMPHERE(jump);
9238    if (private_data_ptr == 0)    if (private_data_ptr == 0)
# Line 8842  if ((type & 0x1) == 0) Line 9271  if ((type & 0x1) == 0)
9271    set_jumps(current->topbacktracks, LABEL());    set_jumps(current->topbacktracks, LABEL());
9272    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
9273    free_stack(common, 1);    free_stack(common, 1);
9274    CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);    CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath);
9275    return;    return;
9276    }    }
9277    
9278  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
9279  CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);  CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath);
9280  set_jumps(current->topbacktracks, LABEL());  set_jumps(current->topbacktracks, LABEL());
9281  free_stack(common, ref ? 2 : 3);  free_stack(common, ref ? 2 : 3);
9282  }  }
# Line 10030  if (mode != JIT_COMPILE) Line 10459  if (mode != JIT_COMPILE)
10459      common->hit_start = common->ovector_start;      common->hit_start = common->ovector_start;
10460      common->ovector_start += 2 * sizeof(sljit_sw);      common->ovector_start += 2 * sizeof(sljit_sw);
10461      }      }
   else  
     {  
     SLJIT_ASSERT(mode == JIT_PARTIAL_HARD_COMPILE);  
     common->needs_start_ptr = TRUE;  
     }  
10462    }    }
10463  if ((re->options & PCRE_FIRSTLINE) != 0)  if ((re->options & PCRE_FIRSTLINE) != 0)
10464    {    {
# Line 10049  if (common->control_head_ptr != 0) Line 10473  if (common->control_head_ptr != 0)
10473    common->control_head_ptr = common->ovector_start;    common->control_head_ptr = common->ovector_start;
10474    common->ovector_start += sizeof(sljit_sw);    common->ovector_start += sizeof(sljit_sw);
10475    }    }
10476  if (common->needs_start_ptr && common->has_set_som)  if (common->has_set_som)
10477    {    {
10478    /* Saving the real start pointer is necessary. */    /* Saving the real start pointer is necessary. */
10479    common->start_ptr = common->ovector_start;    common->start_ptr = common->ovector_start;
10480    common->ovector_start += sizeof(sljit_sw);    common->ovector_start += sizeof(sljit_sw);
10481    }    }
 else  
   common->needs_start_ptr = FALSE;  
10482    
10483  /* Aligning ovector to even number of sljit words. */  /* Aligning ovector to even number of sljit words. */
10484  if ((common->ovector_start & sizeof(sljit_sw)) != 0)  if ((common->ovector_start & sizeof(sljit_sw)) != 0)
# Line 10143  if ((re->options & PCRE_ANCHORED) == 0) Line 10565  if ((re->options & PCRE_ANCHORED) == 0)
10565      if (mode == JIT_COMPILE && fast_forward_first_n_chars(common, (re->options & PCRE_FIRSTLINE) != 0))      if (mode == JIT_COMPILE && fast_forward_first_n_chars(common, (re->options & PCRE_FIRSTLINE) != 0))
10566        ;        ;
10567      else if ((re->flags & PCRE_FIRSTSET) != 0)      else if ((re->flags & PCRE_FIRSTSET) != 0)
10568        fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0);        fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0);
10569      else if ((re->flags & PCRE_STARTLINE) != 0)      else if ((re->flags & PCRE_STARTLINE) != 0)
10570        fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0);        fast_forward_newline(common);
10571      else if (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)      else if (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
10572        fast_forward_start_bits(common, study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);        fast_forward_start_bits(common, study->start_bits);
10573      }      }
10574    }    }
10575  else  else
# Line 10169  OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM Line 10591  OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM
10591  if (common->capture_last_ptr != 0)  if (common->capture_last_ptr != 0)
10592    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, -1);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, -1);
10593    
10594  if (common->needs_start_ptr)  if (common->start_ptr != OVECTOR(0))
   {  
   SLJIT_ASSERT(common->start_ptr != OVECTOR(0));  
10595    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0);    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0);
   }  
 else  
   SLJIT_ASSERT(common->start_ptr == OVECTOR(0));  
10596    
10597  /* Copy the beginning of the string. */  /* Copy the beginning of the string. */
10598  if (mode == JIT_PARTIAL_SOFT_COMPILE)  if (mode == JIT_PARTIAL_SOFT_COMPILE)

Legend:
Removed from v.1624  
changed lines
  Added in v.1629

  ViewVC Help
Powered by ViewVC 1.1.5