@@ -112,6 +112,77 @@ static struct {
112
112
#define BIGDECIMAL_POSITIVE_P (bd ) ((bd)->sign > 0)
113
113
#define BIGDECIMAL_NEGATIVE_P (bd ) ((bd)->sign < 0)
114
114
115
+ /*
116
+ * ================== Memory allocation ============================
117
+ */
118
+
119
+ #ifdef BIGDECIMAL_DEBUG
120
+ static size_t rbd_allocation_count = 0 ; /* Memory allocation counter */
121
+ static inline void
122
+ atomic_allocation_count_inc (void )
123
+ {
124
+ RUBY_ATOMIC_SIZE_INC (rbd_allocation_count );
125
+ }
126
+ static inline void
127
+ atomic_allocation_count_dec_nounderflow (void )
128
+ {
129
+ if (rbd_allocation_count == 0 ) return ;
130
+ RUBY_ATOMIC_SIZE_DEC (rbd_allocation_count );
131
+ }
132
+ static void
133
+ check_allocation_count_nonzero (void )
134
+ {
135
+ if (rbd_allocation_count != 0 ) return ;
136
+ rb_bug ("[bigdecimal][rbd_free_struct] Too many memory free calls" );
137
+ }
138
+ #else
139
+ # define atomic_allocation_count_inc () /* nothing */
140
+ # define atomic_allocation_count_dec_nounderflow () /* nothing */
141
+ # define check_allocation_count_nonzero () /* nothing */
142
+ #endif /* BIGDECIMAL_DEBUG */
143
+
144
+ PUREFUNC (static inline size_t rbd_struct_size (size_t const ));
145
+
146
+ static inline size_t
147
+ rbd_struct_size (size_t const internal_digits )
148
+ {
149
+ return offsetof(Real , frac ) + sizeof (DECDIG ) * internal_digits ;
150
+ }
151
+
152
+ static inline Real *
153
+ rbd_allocate_struct (size_t const internal_digits )
154
+ {
155
+ size_t const size = rbd_struct_size (internal_digits );
156
+ Real * real = ruby_xcalloc (1 , size );
157
+ atomic_allocation_count_inc ();
158
+ return real ;
159
+ }
160
+
161
+ static VALUE BigDecimal_wrap_struct (VALUE obj , Real * vp );
162
+
163
+ static inline Real *
164
+ rbd_reallocate_struct (Real * real , size_t const internal_digits )
165
+ {
166
+ size_t const size = rbd_struct_size (internal_digits );
167
+ VALUE obj = real ? real -> obj : 0 ;
168
+ Real * new_real = (Real * )ruby_xrealloc (real , size );
169
+ if (obj ) {
170
+ new_real -> obj = 0 ;
171
+ BigDecimal_wrap_struct (obj , new_real );
172
+ }
173
+ return new_real ;
174
+ }
175
+
176
+ static void
177
+ rbd_free_struct (Real * real )
178
+ {
179
+ if (real != NULL ) {
180
+ check_allocation_count_nonzero ();
181
+ ruby_xfree (real );
182
+ atomic_allocation_count_dec_nounderflow ();
183
+ }
184
+ }
185
+
115
186
/*
116
187
* ================== Ruby Interface part ==========================
117
188
*/
@@ -145,7 +216,7 @@ static VALUE BigDecimal_negative_zero(void);
145
216
static void
146
217
BigDecimal_delete (void * pv )
147
218
{
148
- VpFree (pv );
219
+ rbd_free_struct (pv );
149
220
}
150
221
151
222
static size_t
@@ -980,26 +1051,12 @@ VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
980
1051
return VpNewRbClass (mx , str , rb_cBigDecimal , true, raise_exception );
981
1052
}
982
1053
983
- #define VpAllocReal (prec ) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(DECDIG))
984
-
985
- static Real *
986
- VpReallocReal (Real * pv , size_t prec )
987
- {
988
- VALUE obj = pv ? pv -> obj : 0 ;
989
- Real * new_pv = (Real * )VpMemRealloc (pv , offsetof(Real , frac ) + prec * sizeof (DECDIG ));
990
- if (obj ) {
991
- new_pv -> obj = 0 ;
992
- BigDecimal_wrap_struct (obj , new_pv );
993
- }
994
- return new_pv ;
995
- }
996
-
997
1054
static Real *
998
1055
VpCopy (Real * pv , Real const * const x )
999
1056
{
1000
1057
assert (x != NULL );
1001
1058
1002
- pv = VpReallocReal (pv , x -> MaxPrec );
1059
+ pv = rbd_reallocate_struct (pv , x -> MaxPrec );
1003
1060
pv -> MaxPrec = x -> MaxPrec ;
1004
1061
pv -> Prec = x -> Prec ;
1005
1062
pv -> exponent = x -> exponent ;
@@ -1825,7 +1882,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
1825
1882
1826
1883
if (!VpIsZero (c ) && (VpGetSign (a ) * VpGetSign (b ) < 0 )) {
1827
1884
/* result adjustment for negative case */
1828
- res = VpReallocReal (res , d -> MaxPrec );
1885
+ res = rbd_reallocate_struct (res , d -> MaxPrec );
1829
1886
res -> MaxPrec = d -> MaxPrec ;
1830
1887
VpAddSub (res , d , VpOne (), -1 );
1831
1888
GUARD_OBJ (d , VpCreateRbObject (GetAddSubPrec (c , b ) * 2 * BASE_FIG , "0" , true));
@@ -3116,15 +3173,15 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
3116
3173
3117
3174
Real * vp ;
3118
3175
if (uval == 0 ) {
3119
- vp = VpAllocReal (1 );
3176
+ vp = rbd_allocate_struct (1 );
3120
3177
vp -> MaxPrec = 1 ;
3121
3178
vp -> Prec = 1 ;
3122
3179
vp -> exponent = 1 ;
3123
3180
VpSetZero (vp , 1 );
3124
3181
vp -> frac [0 ] = 0 ;
3125
3182
}
3126
3183
else if (uval < BASE ) {
3127
- vp = VpAllocReal (1 );
3184
+ vp = rbd_allocate_struct (1 );
3128
3185
vp -> MaxPrec = 1 ;
3129
3186
vp -> Prec = 1 ;
3130
3187
vp -> exponent = 1 ;
@@ -3150,7 +3207,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
3150
3207
}
3151
3208
3152
3209
const size_t exp = len + ntz ;
3153
- vp = VpAllocReal (len );
3210
+ vp = rbd_allocate_struct (len );
3154
3211
vp -> MaxPrec = len ;
3155
3212
vp -> Prec = len ;
3156
3213
vp -> exponent = exp ;
@@ -4494,42 +4551,6 @@ static int VpRdup(Real *m, size_t ind_m);
4494
4551
static int gnAlloc = 0 ; /* Memory allocation counter */
4495
4552
#endif /* BIGDECIMAL_DEBUG */
4496
4553
4497
- VP_EXPORT void *
4498
- VpMemAlloc (size_t mb )
4499
- {
4500
- void * p = xmalloc (mb );
4501
- memset (p , 0 , mb );
4502
- #ifdef BIGDECIMAL_DEBUG
4503
- gnAlloc ++ ; /* Count allocation call */
4504
- #endif /* BIGDECIMAL_DEBUG */
4505
- return p ;
4506
- }
4507
-
4508
- VP_EXPORT void *
4509
- VpMemRealloc (void * ptr , size_t mb )
4510
- {
4511
- return xrealloc (ptr , mb );
4512
- }
4513
-
4514
- VP_EXPORT void
4515
- VpFree (Real * pv )
4516
- {
4517
- if (pv != NULL ) {
4518
- xfree (pv );
4519
- #ifdef BIGDECIMAL_DEBUG
4520
- gnAlloc -- ; /* Decrement allocation count */
4521
- if (gnAlloc == 0 ) {
4522
- printf (" *************** All memories allocated freed ****************\n" );
4523
- /*getchar();*/
4524
- }
4525
- if (gnAlloc < 0 ) {
4526
- printf (" ??????????? Too many memory free calls(%d) ?????????????\n" , gnAlloc );
4527
- /*getchar();*/
4528
- }
4529
- #endif /* BIGDECIMAL_DEBUG */
4530
- }
4531
- }
4532
-
4533
4554
/*
4534
4555
* EXCEPTION Handling.
4535
4556
*/
@@ -5009,7 +5030,7 @@ bigdecimal_parse_special_string(const char *str)
5009
5030
p = str + table [i ].len ;
5010
5031
while (* p && ISSPACE (* p )) ++ p ;
5011
5032
if (* p == '\0' ) {
5012
- Real * vp = VpAllocReal (1 );
5033
+ Real * vp = rbd_allocate_struct (1 );
5013
5034
vp -> MaxPrec = 1 ;
5014
5035
switch (table [i ].sign ) {
5015
5036
default :
@@ -5079,7 +5100,7 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
5079
5100
/* necessary to be able to store */
5080
5101
/* at least mx digits. */
5081
5102
/* szVal==NULL ==> allocate zero value. */
5082
- vp = VpAllocReal (mx );
5103
+ vp = rbd_allocate_struct (mx );
5083
5104
vp -> MaxPrec = mx ; /* set max precision */
5084
5105
VpSetZero (vp , 1 ); /* initialize vp to zero. */
5085
5106
return vp ;
@@ -5254,7 +5275,7 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
5254
5275
if (mx == 0 ) mx = 1 ;
5255
5276
nalloc = Max (nalloc , mx );
5256
5277
mx = nalloc ;
5257
- vp = VpAllocReal (mx );
5278
+ vp = rbd_allocate_struct (mx );
5258
5279
vp -> MaxPrec = mx ; /* set max precision */
5259
5280
VpSetZero (vp , sign );
5260
5281
VpCtoV (vp , psz , ni , psz + ipf , nf , psz + ipe , ne );
@@ -5828,8 +5849,8 @@ VpMult(Real *c, Real *a, Real *b)
5828
5849
5829
5850
c -> exponent = a -> exponent ; /* set exponent */
5830
5851
if (!AddExponent (c , b -> exponent )) {
5831
- if (w ) VpFree (c );
5832
- return 0 ;
5852
+ if (w ) rbd_free_struct (c );
5853
+ return 0 ;
5833
5854
}
5834
5855
VpSetSign (c , VpGetSign (a ) * VpGetSign (b )); /* set sign */
5835
5856
carry = 0 ;
@@ -5879,10 +5900,10 @@ VpMult(Real *c, Real *a, Real *b)
5879
5900
}
5880
5901
}
5881
5902
if (w != NULL ) { /* free work variable */
5882
- VpNmlz (c );
5883
- VpAsgn (w , c , 1 );
5884
- VpFree (c );
5885
- c = w ;
5903
+ VpNmlz (c );
5904
+ VpAsgn (w , c , 1 );
5905
+ rbd_free_struct (c );
5906
+ c = w ;
5886
5907
}
5887
5908
else {
5888
5909
VpLimitRound (c ,0 );
@@ -7047,8 +7068,8 @@ VpSqrt(Real *y, Real *x)
7047
7068
y -> MaxPrec = y_prec ;
7048
7069
7049
7070
Exit :
7050
- VpFree (f );
7051
- VpFree (r );
7071
+ rbd_free_struct (f );
7072
+ rbd_free_struct (r );
7052
7073
return 1 ;
7053
7074
}
7054
7075
@@ -7470,8 +7491,8 @@ VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
7470
7491
printf (" n=%" PRIdVALUE "\n" , n );
7471
7492
}
7472
7493
#endif /* BIGDECIMAL_DEBUG */
7473
- VpFree (w2 );
7474
- VpFree (w1 );
7494
+ rbd_free_struct (w2 );
7495
+ rbd_free_struct (w1 );
7475
7496
return 1 ;
7476
7497
}
7477
7498
0 commit comments