8000 ext/gmp: Create custom Fast ZPP specifier to parse into mpz_ptr · divinity76/php-src@290f696 · GitHub
[go: up one dir, main page]

Skip to content

Commit 290f696

Browse files
committed
ext/gmp: Create custom Fast ZPP specifier to parse into mpz_ptr
We define module globals to be used with ZPP, which also avoids excessive initializing and clearing of variables, something recommended by the GMP documentation.
1 parent 2313a46 commit 290f696

File tree

2 files changed

+51
-4
lines changed

2 files changed

+51
-4
lines changed

ext/gmp/gmp.c

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
ZEND_DECLARE_MODULE_GLOBALS(gmp)
5757
static ZEND_GINIT_FUNCTION(gmp);
58+
static ZEND_GSHUTDOWN_FUNCTION(gmp);
5859

5960
/* {{{ gmp_module_entry */
6061
zend_module_entry gmp_module_entry = {
@@ -69,7 +70,7 @@ zend_module_entry gmp_module_entry = {
6970
PHP_GMP_VERSION,
7071
ZEND_MODULE_GLOBALS(gmp),
7172
ZEND_GINIT(gmp),
72-
NULL,
73+
ZEND_GSHUTDOWN(gmp),
7374
NULL,
7475
STANDARD_MODULE_PROPERTIES_EX
7576
};
@@ -179,14 +180,49 @@ if (IS_GMP(zval)) { \
179180
gmpnumber = temp.num; \
180181
}
181182

182-
#define INIT_GMP_RETVAL(gmpnumber) \
183-
gmp_create(return_value, &gmpnumber)
184-
185183
static void gmp_strval(zval *result, mpz_t gmpnum, int base);
186184
static zend_result convert_zstr_to_gmp(mpz_t gmp_number, const zend_string *val, zend_long base, uint32_t arg_pos);
187185
static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos);
188186
static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg, bool is_operator);
189187

188+
static bool gmp_zend_parse_arg_into_mpz(
189+
zval *arg,
190+
mpz_ptr *destination_mpz_ptr,
191+
uint32_t arg_num
192+
) {
193+
if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
194+
if (EXPECTED(instanceof_function(Z_OBJCE_P(arg), gmp_ce))) {
195+
*destination_mpz_ptr = GET_GMP_FROM_ZVAL(arg);
196+
return true;
197+
}
198+
return false;
199+
}
200+
201+
*destination_mpz_ptr = GMPG(zpp_arg[arg_num-1]);
202+
if (Z_TYPE_P(arg) == IS_STRING) {
203+
return convert_zstr_to_gmp(*destination_mpz_ptr, Z_STR_P(arg), /* base */ 0, arg_num) != FAILURE;
204+
}
205+
206+
if (Z_TYPE_P(arg) == IS_LONG) {
207+
mpz_set_si(*destination_mpz_ptr, Z_LVAL_P(arg));
208+
return true;
209+
}
210+
return false;
211+
}
212+
213+
#define GMP_Z_PARAM_INTO_MPZ_PTR(destination_mpz_ptr) \
214+
Z_PARAM_PROLOGUE(0, 0); \
215+
if (UNEXPECTED(!gmp_zend_parse_arg_into_mpz(_arg, &destination_mpz_ptr, _i))) { \
216+
_error_code = ZPP_ERROR_FAILURE; \
217+
if (!EG(exception)) { \
218+
zend_argument_type_error(_i, "must be of type GMP|string|int, %s given", zend_zval_value_name(_arg)); \
219+
} \
220+
break; \
221+
}
222+
223+
#define INIT_GMP_RETVAL(gmpnumber) \
224+
gmp_create(return_value, &gmpnumber)
225+
190226
/*
191227
* The gmp_*_op functions provide an implementation for several common types
192228
* of GMP functions. The gmp_zval_(unary|binary)_*_op functions have to be manually
@@ -591,9 +627,19 @@ static ZEND_GINIT_FUNCTION(gmp)
591627
ZEND_TSRMLS_CACHE_UPDATE();
592628
#endif
593629
gmp_globals->rand_initialized = 0;
630+
mpz_init(gmp_globals->zpp_arg[0]);
631+
mpz_init(gmp_globals->zpp_arg[1]);
632+
mpz_init(gmp_globals->zpp_arg[2]);
594633
}
595634
/* }}} */
596635

636+
static ZEND_GSHUTDOWN_FUNCTION(gmp)
637+
{
638+
mpz_clear(gmp_globals->zpp_arg[0]);
639+
mpz_clear(gmp_globals->zpp_arg[1]);
640+
mpz_clear(gmp_globals->zpp_arg[2]);
641+
}
642+
597643
/* {{{ ZEND_MINIT_FUNCTION */
598644
ZEND_MINIT_FUNCTION(gmp)
599645
{

ext/gmp/php_gmp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ ZEND_MODULE_INFO_D(gmp);
3232
ZEND_BEGIN_MODULE_GLOBALS(gmp)
3333
bool rand_initialized;
3434
gmp_randstate_t rand_state;
35+
mpz_t zpp_arg[3];
3536
ZEND_END_MODULE_GLOBALS(gmp)
3637

3738
#define GMPG(v) ZEND_MODULE_GLOBALS_ACCESSOR(gmp, v)

0 commit comments

Comments
 (0)
0