diff options
author | Karl Williamson <public@khwilliamson.com> | 2013-07-12 15:11:26 -0600 |
---|---|---|
committer | Karl Williamson <public@khwilliamson.com> | 2013-07-16 13:58:12 -0600 |
commit | 4c60406d0e89efe615812945449c96f48bf70433 (patch) | |
tree | 6fe559069a877628fbbab7873bcfd09fa539b6e0 | |
parent | bb023b4f5363e492abb21c941380d9a69f29631b (diff) | |
download | perl-4c60406d0e89efe615812945449c96f48bf70433.tar.gz |
Remove redundant field from inversion lists
The number of elements in an inversion list is a simple calculation
based on SvCUR(). Prior to this patch there was a field that contained
that number directly, and the two values diverged, causing a bug. A
single value can't get out-of-sync with itself.
-rw-r--r-- | embed.fnc | 3 | ||||
-rw-r--r-- | embed.h | 3 | ||||
-rw-r--r-- | inline_invlist.c | 27 | ||||
-rw-r--r-- | proto.h | 18 | ||||
-rw-r--r-- | regcomp.c | 36 | ||||
-rw-r--r-- | sv.h | 1 |
6 files changed, 32 insertions, 56 deletions
@@ -1434,7 +1434,6 @@ EsM |void |_append_range_to_invlist |NN SV* const invlist|const UV start|const EiMR |UV* |_invlist_array_init |NN SV* const invlist|const bool will_have_0 EiMR |UV* |invlist_array |NN SV* const invlist EsM |void |invlist_extend |NN SV* const invlist|const UV len -EiMR |bool* |get_invlist_offset_addr|NN SV* invlist EiMR |UV |invlist_max |NN SV* const invlist EiM |void |invlist_set_len|NN SV* const invlist|const UV len|const bool offset EiMR |IV* |get_invlist_previous_index_addr|NN SV* invlist @@ -1473,7 +1472,7 @@ EXp |SV* |_core_swash_init|NN const char* pkg|NN const char* name \ #endif #if defined(PERL_IN_REGCOMP_C) || defined(PERL_IN_REGEXEC_C) || defined(PERL_IN_UTF8_C) EXMpR |SV* |_invlist_contents|NN SV* const invlist -EiMR |STRLEN*|_get_invlist_len_addr |NN SV* invlist +EiMR |bool* |get_invlist_offset_addr|NN SV* invlist EiMR |UV |_invlist_len |NN SV* const invlist EMiR |bool |_invlist_contains_cp|NN SV* const invlist|const UV cp EXpMR |IV |_invlist_search |NN SV* const invlist|const UV cp @@ -907,7 +907,6 @@ #define compute_EXACTish(a) S_compute_EXACTish(aTHX_ a) #define could_it_be_a_POSIX_class(a) S_could_it_be_a_POSIX_class(aTHX_ a) #define get_invlist_iter_addr(a) S_get_invlist_iter_addr(aTHX_ a) -#define get_invlist_offset_addr(a) S_get_invlist_offset_addr(aTHX_ a) #define get_invlist_previous_index_addr(a) S_get_invlist_previous_index_addr(aTHX_ a) #define grok_bslash_N(a,b,c,d,e,f,g) S_grok_bslash_N(aTHX_ a,b,c,d,e,f,g) #define handle_regex_sets(a,b,c,d,e) S_handle_regex_sets(aTHX_ a,b,c,d,e) @@ -949,13 +948,13 @@ #define study_chunk(a,b,c,d,e,f,g,h,i,j,k) S_study_chunk(aTHX_ a,b,c,d,e,f,g,h,i,j,k) # endif # if defined(PERL_IN_REGCOMP_C) || defined(PERL_IN_REGEXEC_C) || defined(PERL_IN_UTF8_C) -#define _get_invlist_len_addr(a) S__get_invlist_len_addr(aTHX_ a) #define _get_swash_invlist(a) Perl__get_swash_invlist(aTHX_ a) #define _invlist_contains_cp(a,b) S__invlist_contains_cp(aTHX_ a,b) #define _invlist_contents(a) Perl__invlist_contents(aTHX_ a) #define _invlist_len(a) S__invlist_len(aTHX_ a) #define _invlist_search(a,b) Perl__invlist_search(aTHX_ a,b) #define _swash_inversion_hash(a) Perl__swash_inversion_hash(aTHX_ a) +#define get_invlist_offset_addr(a) S_get_invlist_offset_addr(aTHX_ a) # endif # if defined(PERL_IN_REGCOMP_C) || defined(PERL_IN_REGEXEC_C) || defined(PERL_IN_UTF8_C) || defined(PERL_IN_TOKE_C) #define _core_swash_init(a,b,c,d,e,f,g) Perl__core_swash_init(aTHX_ a,b,c,d,e,f,g) diff --git a/inline_invlist.c b/inline_invlist.c index a29964524b..470659bea8 100644 --- a/inline_invlist.c +++ b/inline_invlist.c @@ -13,15 +13,19 @@ #define ELEMENT_RANGE_MATCHES_INVLIST(i) (! ((i) & 1)) #define PREV_RANGE_MATCHES_INVLIST(i) (! ELEMENT_RANGE_MATCHES_INVLIST(i)) -PERL_STATIC_INLINE STRLEN* -S__get_invlist_len_addr(pTHX_ SV* invlist) +/* This converts to/from our UVs to what the SV code is expecting: bytes. */ +#define TO_INTERNAL_SIZE(x) ((x) * sizeof(UV)) +#define FROM_INTERNAL_SIZE(x) ((x)/ sizeof(UV)) + +PERL_STATIC_INLINE bool* +S_get_invlist_offset_addr(pTHX_ SV* invlist) { - /* Return the address of the UV that contains the current number - * of used elements in the inversion list */ + /* Return the address of the field that says whether the inversion list is + * offset (it contains 1) or not (contains 0) */ - PERL_ARGS_ASSERT__GET_INVLIST_LEN_ADDR; + PERL_ARGS_ASSERT_GET_INVLIST_OFFSET_ADDR; - return &(((XINVLIST*) SvANY(invlist))->count); + return &(((XINVLIST*) SvANY(invlist))->is_offset); } PERL_STATIC_INLINE UV @@ -32,7 +36,9 @@ S__invlist_len(pTHX_ SV* const invlist) PERL_ARGS_ASSERT__INVLIST_LEN; - return *_get_invlist_len_addr(invlist); + return (SvCUR(invlist) == 0) + ? 0 + : FROM_INTERNAL_SIZE(SvCUR(invlist)) - *get_invlist_offset_addr(invlist); } PERL_STATIC_INLINE bool @@ -47,4 +53,11 @@ S__invlist_contains_cp(pTHX_ SV* const invlist, const UV cp) return index >= 0 && ELEMENT_RANGE_MATCHES_INVLIST(index); } +# if defined(PERL_IN_UTF8_C) || defined(PERL_IN_REGEXEC_C) + +/* These symbols are only needed later in regcomp.c */ +# undef TO_INTERNAL_SIZE +# undef FROM_INTERNAL_SIZE +# endif + #endif @@ -6509,12 +6509,6 @@ PERL_STATIC_INLINE STRLEN* S_get_invlist_iter_addr(pTHX_ SV* invlist) #define PERL_ARGS_ASSERT_GET_INVLIST_ITER_ADDR \ assert(invlist) -PERL_STATIC_INLINE bool* S_get_invlist_offset_addr(pTHX_ SV* invlist) - __attribute__warn_unused_result__ - __attribute__nonnull__(pTHX_1); -#define PERL_ARGS_ASSERT_GET_INVLIST_OFFSET_ADDR \ - assert(invlist) - PERL_STATIC_INLINE IV* S_get_invlist_previous_index_addr(pTHX_ SV* invlist) __attribute__warn_unused_result__ __attribute__nonnull__(pTHX_1); @@ -6760,12 +6754,6 @@ STATIC I32 S_study_chunk(pTHX_ struct RExC_state_t *pRExC_state, regnode **scanp #endif #if defined(PERL_IN_REGCOMP_C) || defined(PERL_IN_REGEXEC_C) || defined(PERL_IN_UTF8_C) -PERL_STATIC_INLINE STRLEN* S__get_invlist_len_addr(pTHX_ SV* invlist) - __attribute__warn_unused_result__ - __attribute__nonnull__(pTHX_1); -#define PERL_ARGS_ASSERT__GET_INVLIST_LEN_ADDR \ - assert(invlist) - PERL_CALLCONV SV* Perl__get_swash_invlist(pTHX_ SV* const swash) __attribute__warn_unused_result__ __attribute__nonnull__(pTHX_1); @@ -6802,6 +6790,12 @@ PERL_CALLCONV HV* Perl__swash_inversion_hash(pTHX_ SV* const swash) #define PERL_ARGS_ASSERT__SWASH_INVERSION_HASH \ assert(swash) +PERL_STATIC_INLINE bool* S_get_invlist_offset_addr(pTHX_ SV* invlist) + __attribute__warn_unused_result__ + __attribute__nonnull__(pTHX_1); +#define PERL_ARGS_ASSERT_GET_INVLIST_OFFSET_ADDR \ + assert(invlist) + #endif #if defined(PERL_IN_REGCOMP_C) || defined(PERL_IN_REGEXEC_C) || defined(PERL_IN_UTF8_C) || defined(PERL_IN_TOKE_C) PERL_CALLCONV SV* Perl__core_swash_init(pTHX_ const char* pkg, const char* name, SV* listsv, I32 minbits, I32 none, SV* invlist, U8* const flags_p) @@ -7067,11 +7067,6 @@ S_reg_scan_name(pTHX_ RExC_state_t *pRExC_state, U32 flags) /* The header definitions are in F<inline_invlist.c> */ -/* This converts to/from our UVs to what the SV code is expecting: bytes. */ -#define TO_INTERNAL_SIZE(x) ((x) * sizeof(UV)) -#define FROM_INTERNAL_SIZE(x) ((x)/ sizeof(UV)) - - PERL_STATIC_INLINE UV* S__invlist_array_init(pTHX_ SV* const invlist, const bool will_have_0) { @@ -7089,7 +7084,7 @@ S__invlist_array_init(pTHX_ SV* const invlist, const bool will_have_0) PERL_ARGS_ASSERT__INVLIST_ARRAY_INIT; /* Must be empty */ - assert(! *_get_invlist_len_addr(invlist)); + assert(! _invlist_len(invlist)); *zero_addr = 0; @@ -7109,7 +7104,7 @@ S_invlist_array(pTHX_ SV* const invlist) /* Must not be empty. If these fail, you probably didn't check for <len> * being non-zero before trying to get the array */ - assert(*_get_invlist_len_addr(invlist)); + assert(_invlist_len(invlist)); /* The very first element always contains zero, The array begins either * there, or if the inversion list is offset, at the element after it. @@ -7127,8 +7122,6 @@ S_invlist_set_len(pTHX_ SV* const invlist, const UV len, const bool offset) PERL_ARGS_ASSERT_INVLIST_SET_LEN; - *_get_invlist_len_addr(invlist) = len; - SvCUR_set(invlist, (len == 0) ? 0 @@ -7184,17 +7177,6 @@ S_invlist_max(pTHX_ SV* const invlist) : FROM_INTERNAL_SIZE(SvLEN(invlist)) - 1; } -PERL_STATIC_INLINE bool* -S_get_invlist_offset_addr(pTHX_ SV* invlist) -{ - /* Return the address of the field that says whether the inversion list is - * offset (it contains 1) or not (contains 0) */ - - PERL_ARGS_ASSERT_GET_INVLIST_OFFSET_ADDR; - - return &(((XINVLIST*) SvANY(invlist))->is_offset); -} - #ifndef PERL_IN_XSUB_RE SV* Perl__new_invlist(pTHX_ IV initial_size) @@ -8070,27 +8052,17 @@ Perl__invlist_invert(pTHX_ SV* const invlist) * have a zero; removes it otherwise. As described above, the data * structure is set up so that this is very efficient */ - STRLEN* len_pos = _get_invlist_len_addr(invlist); - PERL_ARGS_ASSERT__INVLIST_INVERT; assert(! invlist_is_iterating(invlist)); /* The inverse of matching nothing is matching everything */ - if (*len_pos == 0) { + if (_invlist_len(invlist) == 0) { _append_range_to_invlist(invlist, 0, UV_MAX); return; } - /* The exclusive or complents 0 to 1; and 1 to 0. If the result is 1, the - * zero element was a 0, so it is being removed, so the length decrements - * by 1; and vice-versa. SvCUR is unaffected */ - if (*get_invlist_offset_addr(invlist) ^= 1) { - (*len_pos)--; - } - else { - (*len_pos)++; - } + *get_invlist_offset_addr(invlist) = ! *get_invlist_offset_addr(invlist); } void @@ -532,7 +532,6 @@ struct xpvinvlist { _XPV_HEAD; IV prev_index; STRLEN iterator; - STRLEN count; bool is_offset; /* */ }; |