Skip to content

Commit 6b6fde9

Browse files
ext/bcmath: If size of BC_VECTOR array is within 64 bytes, stack area is now used (#18065)
1 parent 843d2a9 commit 6b6fde9

File tree

4 files changed

+34
-11
lines changed

4 files changed

+34
-11
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ PHP NEWS
55
- BCMath:
66
. Simplify `bc_divide()` code. (SakiTakamachi)
77
. If the result is 0, n_scale is set to 0. (SakiTakamachi)
8+
. If size of BC_VECTOR array is within 64 bytes, stack area is now used.
9+
(SakiTakamachi)
810

911
- CLI:
1012
. Add --ini=diff to print INI settings changed from the builtin default.

ext/bcmath/libbcmath/src/div.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,15 @@ static void bc_do_div(
260260
size_t quot_arr_size = numerator_arr_size - divisor_arr_size + 1;
261261
size_t quot_real_arr_size = MIN(quot_arr_size, (quot_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE);
262262

263-
BC_VECTOR *numerator_vectors = safe_emalloc(numerator_arr_size + divisor_arr_size + quot_arr_size, sizeof(BC_VECTOR), 0);
263+
BC_VECTOR stack_vectors[BC_STACK_VECTOR_SIZE];
264+
size_t allocation_arr_size = numerator_arr_size + divisor_arr_size + quot_arr_size;
265+
266+
BC_VECTOR *numerator_vectors;
267+
if (allocation_arr_size <= BC_STACK_VECTOR_SIZE) {
268+
numerator_vectors = stack_vectors;
269+
} else {
270+
numerator_vectors = safe_emalloc(allocation_arr_size, sizeof(BC_VECTOR), 0);
271+
}
264272
BC_VECTOR *divisor_vectors = numerator_vectors + numerator_arr_size;
265273
BC_VECTOR *quot_vectors = divisor_vectors + divisor_arr_size;
266274

@@ -302,7 +310,9 @@ static void bc_do_div(
302310
quot_vectors[i] /= BASE;
303311
}
304312

305-
efree(numerator_vectors);
313+
if (allocation_arr_size > BC_STACK_VECTOR_SIZE) {
314+
efree(numerator_vectors);
315+
}
306316
}
307317

308318
static inline void bc_divide_by_one(bc_num numerator, bc_num *quot, size_t quot_scale)

ext/bcmath/libbcmath/src/private.h

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
# define BC_LITTLE_ENDIAN 1
6565
#endif
6666

67+
/* 64-bytes for 64-bit */
68+
#define BC_STACK_VECTOR_SIZE 8
69+
6770
/*
6871
* Adding more than this many times may cause uint32_t/uint64_t to overflow.
6972
* Typically this is 1844 for 64bit and 42 for 32bit.

ext/bcmath/libbcmath/src/recmul.c

+17-9
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,21 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc
149149
size_t n2_arr_size = (n2len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE;
150150
size_t prod_arr_size = (prodlen + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE;
151151

152-
/*
153-
* let's say that N is the max of n1len and n2len (and a multiple of BC_VECTOR_SIZE for simplicity),
154-
* then this sum is <= N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE - 1
155-
* which is equal to N - 1 if BC_VECTOR_SIZE is 4, and N/2 - 1 if BC_VECTOR_SIZE is 8.
156-
*/
157-
BC_VECTOR *buf = safe_emalloc(n1_arr_size + n2_arr_size + prod_arr_size, sizeof(BC_VECTOR), 0);
152+
BC_VECTOR stack_vectors[BC_STACK_VECTOR_SIZE];
153+
size_t allocation_arr_size = n1_arr_size + n2_arr_size + prod_arr_size;
158154

159-
BC_VECTOR *n1_vector = buf;
160-
BC_VECTOR *n2_vector = buf + n1_arr_size;
155+
BC_VECTOR *n1_vector;
156+
if (allocation_arr_size <= BC_STACK_VECTOR_SIZE) {
157+
n1_vector = stack_vectors;
158+
} else {
159+
/*
160+
* let's say that N is the max of n1len and n2len (and a multiple of BC_VECTOR_SIZE for simplicity),
161+
* then this sum is <= N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE - 1
162+
* which is equal to N - 1 if BC_VECTOR_SIZE is 4, and N/2 - 1 if BC_VECTOR_SIZE is 8.
163+
*/
164+
n1_vector = safe_emalloc(allocation_arr_size, sizeof(BC_VECTOR), 0);
165+
}
166+
BC_VECTOR *n2_vector = n1_vector + n1_arr_size;
161167
BC_VECTOR *prod_vector = n2_vector + n2_arr_size;
162168

163169
for (i = 0; i < prod_arr_size; i++) {
@@ -188,7 +194,9 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc
188194

189195
bc_mul_finish_from_vector(prod_vector, prod_arr_size, prodlen, prod);
190196

191-
efree(buf);
197+
if (allocation_arr_size > BC_STACK_VECTOR_SIZE) {
198+
efree(n1_vector);
199+
}
192200
}
193201

194202
/** This is bc_standard_mul implementation for square */

0 commit comments

Comments
 (0)