summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2011-05-26 22:29:40 -0600
committerFather Chrysostomos <sprout@cpan.org>2011-06-02 14:49:28 -0700
commit8649b6777c6afbfcd29e5924f6d476660d7a83c2 (patch)
tree842b23bea5ceb65106c24853be9603807b4c38db
parent58fb19a69351732d73c81aa098d16734663f45de (diff)
downloadperl-8649b6777c6afbfcd29e5924f6d476660d7a83c2.tar.gz
regcomp.c: Fix memory leak regression
There was a remaining memory leak in the new inversion lists data structure under threading. This solves it by changing the implementation to use a SVpPV instead of doing our own memory management. Then the already existing code for handling SVs returns the memory when done.
-rw-r--r--embed.fnc1
-rw-r--r--embed.h1
-rw-r--r--proto.h6
-rw-r--r--regcomp.c106
4 files changed, 15 insertions, 99 deletions
diff --git a/embed.fnc b/embed.fnc
index 161729e91a..bce167e992 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -1310,7 +1310,6 @@ EsM |void |invlist_extend |NN HV* const invlist|const UV len
EsMR |HV* |invlist_intersection |NN HV* const a|NN HV* const b
EiMR |UV |invlist_len |NN HV* const invlist
EiMR |UV |invlist_max |NN HV* const invlist
-EiM |void |invlist_set_array |NN HV* const invlist|NN const UV* const array
EiM |void |invlist_set_len |NN HV* const invlist|const UV len
EiM |void |invlist_set_max |NN HV* const invlist|const UV max
EiM |void |invlist_trim |NN HV* const invlist
diff --git a/embed.h b/embed.h
index 9ff64404f6..04b32d1808 100644
--- a/embed.h
+++ b/embed.h
@@ -882,7 +882,6 @@
#define invlist_intersection(a,b) S_invlist_intersection(aTHX_ a,b)
#define invlist_len(a) S_invlist_len(aTHX_ a)
#define invlist_max(a) S_invlist_max(aTHX_ a)
-#define invlist_set_array(a,b) S_invlist_set_array(aTHX_ a,b)
#define invlist_set_len(a,b) S_invlist_set_len(aTHX_ a,b)
#define invlist_set_max(a,b) S_invlist_set_max(aTHX_ a,b)
#define invlist_trim(a) S_invlist_trim(aTHX_ a)
diff --git a/proto.h b/proto.h
index 845658b658..0b46a79114 100644
--- a/proto.h
+++ b/proto.h
@@ -6048,12 +6048,6 @@ PERL_STATIC_INLINE UV S_invlist_max(pTHX_ HV* const invlist)
#define PERL_ARGS_ASSERT_INVLIST_MAX \
assert(invlist)
-PERL_STATIC_INLINE void S_invlist_set_array(pTHX_ HV* const invlist, const UV* const array)
- __attribute__nonnull__(pTHX_1)
- __attribute__nonnull__(pTHX_2);
-#define PERL_ARGS_ASSERT_INVLIST_SET_ARRAY \
- assert(invlist); assert(array)
-
PERL_STATIC_INLINE void S_invlist_set_len(pTHX_ HV* const invlist, const UV len)
__attribute__nonnull__(pTHX_1);
#define PERL_ARGS_ASSERT_INVLIST_SET_LEN \
diff --git a/regcomp.c b/regcomp.c
index 1a8f70d1a3..94f28c7058 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -5830,13 +5830,15 @@ S_reg_scan_name(pTHX_ RExC_state_t *pRExC_state, U32 flags)
* this file. An inversion list is here implemented as a malloc'd C array with
* some added info. More will be coming when functionality is added later.
*
+ * It is currently implemented as an HV to the outside world, but is actually
+ * an SV pointing to an array of UVs that the SV thinks are bytes. This allows
+ * us to have an array of UV whose memory management is automatically handled
+ * by the existing facilities for SV's.
+ *
* Some of the methods should always be private to the implementation, and some
* should eventually be made public */
#define INVLIST_INITIAL_LEN 10
-#define INVLIST_ARRAY_KEY "array"
-#define INVLIST_MAX_KEY "max"
-#define INVLIST_LEN_KEY "len"
PERL_STATIC_INLINE UV*
S_invlist_array(pTHX_ HV* const invlist)
@@ -5845,30 +5847,9 @@ S_invlist_array(pTHX_ HV* const invlist)
* length changes, this needs to be called in case malloc or realloc moved
* it */
- SV** list_ptr = hv_fetchs(invlist, INVLIST_ARRAY_KEY, FALSE);
-
PERL_ARGS_ASSERT_INVLIST_ARRAY;
- if (list_ptr == NULL) {
- Perl_croak(aTHX_ "panic: inversion list without a '%s' element",
- INVLIST_ARRAY_KEY);
- }
-
- return INT2PTR(UV *, SvUV(*list_ptr));
-}
-
-PERL_STATIC_INLINE void
-S_invlist_set_array(pTHX_ HV* const invlist, const UV* const array)
-{
- PERL_ARGS_ASSERT_INVLIST_SET_ARRAY;
-
- /* Sets the array stored in the inversion list to the memory beginning with
- * the parameter */
-
- if (hv_stores(invlist, INVLIST_ARRAY_KEY, newSVuv(PTR2UV(array))) == NULL) {
- Perl_croak(aTHX_ "panic: can't store '%s' entry in inversion list",
- INVLIST_ARRAY_KEY);
- }
+ return (UV *) SvPVX(invlist);
}
PERL_STATIC_INLINE UV
@@ -5876,16 +5857,9 @@ S_invlist_len(pTHX_ HV* const invlist)
{
/* Returns the current number of elements in the inversion list's array */
- SV** len_ptr = hv_fetchs(invlist, INVLIST_LEN_KEY, FALSE);
-
PERL_ARGS_ASSERT_INVLIST_LEN;
- if (len_ptr == NULL) {
- Perl_croak(aTHX_ "panic: inversion list without a '%s' element",
- INVLIST_LEN_KEY);
- }
-
- return SvUV(*len_ptr);
+ return SvCUR(invlist) / sizeof(UV);
}
PERL_STATIC_INLINE UV
@@ -5894,16 +5868,9 @@ S_invlist_max(pTHX_ HV* const invlist)
/* Returns the maximum number of elements storable in the inversion list's
* array, without having to realloc() */
- SV** max_ptr = hv_fetchs(invlist, INVLIST_MAX_KEY, FALSE);
-
PERL_ARGS_ASSERT_INVLIST_MAX;
- if (max_ptr == NULL) {
- Perl_croak(aTHX_ "panic: inversion list without a '%s' element",
- INVLIST_MAX_KEY);
- }
-
- return SvUV(*max_ptr);
+ return SvLEN(invlist) / sizeof(UV);
}
PERL_STATIC_INLINE void
@@ -5913,14 +5880,7 @@ S_invlist_set_len(pTHX_ HV* const invlist, const UV len)
PERL_ARGS_ASSERT_INVLIST_SET_LEN;
- if (len != 0 && len > invlist_max(invlist)) {
- Perl_croak(aTHX_ "panic: Can't make '%s=%"UVuf"' more than %s=%"UVuf" in inversion list", INVLIST_LEN_KEY, len, INVLIST_MAX_KEY, invlist_max(invlist));
- }
-
- if (hv_stores(invlist, INVLIST_LEN_KEY, newSVuv(len)) == NULL) {
- Perl_croak(aTHX_ "panic: can't store '%s' entry in inversion list",
- INVLIST_LEN_KEY);
- }
+ SvCUR_set(invlist, len * sizeof(UV));
}
PERL_STATIC_INLINE void
@@ -5933,13 +5893,10 @@ S_invlist_set_max(pTHX_ HV* const invlist, const UV max)
PERL_ARGS_ASSERT_INVLIST_SET_MAX;
if (max < invlist_len(invlist)) {
- Perl_croak(aTHX_ "panic: Can't make '%s=%"UVuf"' less than %s=%"UVuf" in inversion list", INVLIST_MAX_KEY, invlist_len(invlist), INVLIST_LEN_KEY, invlist_max(invlist));
+ Perl_croak(aTHX_ "panic: Can't make max size '%"UVuf"' less than current length %"UVuf" in inversion list", invlist_max(invlist), invlist_len(invlist));
}
- if (hv_stores(invlist, INVLIST_MAX_KEY, newSVuv(max)) == NULL) {
- Perl_croak(aTHX_ "panic: can't store '%s' entry in inversion list",
- INVLIST_LEN_KEY);
- }
+ SvLEN_set(invlist, max * sizeof(UV));
}
#ifndef PERL_IN_XSUB_RE
@@ -5951,22 +5908,12 @@ Perl__new_invlist(pTHX_ IV initial_size)
* space to store 'initial_size' elements. If that number is negative, a
* system default is used instead */
- HV* invlist = newHV();
- UV* list;
-
if (initial_size < 0) {
initial_size = INVLIST_INITIAL_LEN;
}
/* Allocate the initial space */
- Newx(list, initial_size, UV);
- invlist_set_array(invlist, list);
-
- /* set_len has to come before set_max, as the latter inspects the len */
- invlist_set_len(invlist, 0);
- invlist_set_max(invlist, initial_size);
-
- return invlist;
+ return (HV *) newSV(initial_size * sizeof(UV));
}
#endif
@@ -5975,42 +5922,19 @@ S_invlist_destroy(pTHX_ HV* const invlist)
{
/* Inversion list destructor */
- SV** list_ptr = hv_fetchs(invlist, INVLIST_ARRAY_KEY, FALSE);
-
PERL_ARGS_ASSERT_INVLIST_DESTROY;
- if (list_ptr != NULL) {
- UV *list = INT2PTR(UV *, SvUV(*list_ptr)); /* PERL_POISON needs lvalue */
- Safefree(list);
- }
SvREFCNT_dec(invlist);
}
STATIC void
S_invlist_extend(pTHX_ HV* const invlist, const UV new_max)
{
- /* Change the maximum size of an inversion list (up or down) */
-
- UV* orig_array;
- UV* array;
- const UV old_max = invlist_max(invlist);
+ /* Grow the maximum size of an inversion list */
PERL_ARGS_ASSERT_INVLIST_EXTEND;
- if (old_max == new_max) { /* If a no-op */
- return;
- }
-
- array = orig_array = invlist_array(invlist);
- Renew(array, new_max, UV);
-
- /* If the size change moved the list in memory, set the new one */
- if (array != orig_array) {
- invlist_set_array(invlist, array);
- }
-
- invlist_set_max(invlist, new_max);
-
+ SvGROW((SV *)invlist, new_max * sizeof(UV));
}
PERL_STATIC_INLINE void
@@ -6021,7 +5945,7 @@ S_invlist_trim(pTHX_ HV* const invlist)
/* Change the length of the inversion list to how many entries it currently
* has */
- invlist_extend(invlist, invlist_len(invlist));
+ SvPV_shrink_to_cur((SV *) invlist);
}
/* An element is in an inversion list iff its index is even numbered: 0, 2, 4,