1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

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.
This commit is contained in:
Gina Peter Banyard
2024-11-03 13:10:24 +00:00
parent 2313a465b6
commit 290f69662a
2 changed files with 51 additions and 4 deletions

View File

@@ -55,6 +55,7 @@
ZEND_DECLARE_MODULE_GLOBALS(gmp)
static ZEND_GINIT_FUNCTION(gmp);
static ZEND_GSHUTDOWN_FUNCTION(gmp);
/* {{{ gmp_module_entry */
zend_module_entry gmp_module_entry = {
@@ -69,7 +70,7 @@ zend_module_entry gmp_module_entry = {
PHP_GMP_VERSION,
ZEND_MODULE_GLOBALS(gmp),
ZEND_GINIT(gmp),
NULL,
ZEND_GSHUTDOWN(gmp),
NULL,
STANDARD_MODULE_PROPERTIES_EX
};
@@ -179,14 +180,49 @@ if (IS_GMP(zval)) { \
gmpnumber = temp.num; \
}
#define INIT_GMP_RETVAL(gmpnumber) \
gmp_create(return_value, &gmpnumber)
static void gmp_strval(zval *result, mpz_t gmpnum, int base);
static zend_result convert_zstr_to_gmp(mpz_t gmp_number, const zend_string *val, zend_long base, uint32_t arg_pos);
static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos);
static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg, bool is_operator);
static bool gmp_zend_parse_arg_into_mpz(
zval *arg,
mpz_ptr *destination_mpz_ptr,
uint32_t arg_num
) {
if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
if (EXPECTED(instanceof_function(Z_OBJCE_P(arg), gmp_ce))) {
*destination_mpz_ptr = GET_GMP_FROM_ZVAL(arg);
return true;
}
return false;
}
*destination_mpz_ptr = GMPG(zpp_arg[arg_num-1]);
if (Z_TYPE_P(arg) == IS_STRING) {
return convert_zstr_to_gmp(*destination_mpz_ptr, Z_STR_P(arg), /* base */ 0, arg_num) != FAILURE;
}
if (Z_TYPE_P(arg) == IS_LONG) {
mpz_set_si(*destination_mpz_ptr, Z_LVAL_P(arg));
return true;
}
return false;
}
#define GMP_Z_PARAM_INTO_MPZ_PTR(destination_mpz_ptr) \
Z_PARAM_PROLOGUE(0, 0); \
if (UNEXPECTED(!gmp_zend_parse_arg_into_mpz(_arg, &destination_mpz_ptr, _i))) { \
_error_code = ZPP_ERROR_FAILURE; \
if (!EG(exception)) { \
zend_argument_type_error(_i, "must be of type GMP|string|int, %s given", zend_zval_value_name(_arg)); \
} \
break; \
}
#define INIT_GMP_RETVAL(gmpnumber) \
gmp_create(return_value, &gmpnumber)
/*
* The gmp_*_op functions provide an implementation for several common types
* of GMP functions. The gmp_zval_(unary|binary)_*_op functions have to be manually
@@ -591,9 +627,19 @@ static ZEND_GINIT_FUNCTION(gmp)
ZEND_TSRMLS_CACHE_UPDATE();
#endif
gmp_globals->rand_initialized = 0;
mpz_init(gmp_globals->zpp_arg[0]);
mpz_init(gmp_globals->zpp_arg[1]);
mpz_init(gmp_globals->zpp_arg[2]);
}
/* }}} */
static ZEND_GSHUTDOWN_FUNCTION(gmp)
{
mpz_clear(gmp_globals->zpp_arg[0]);
mpz_clear(gmp_globals->zpp_arg[1]);
mpz_clear(gmp_globals->zpp_arg[2]);
}
/* {{{ ZEND_MINIT_FUNCTION */
ZEND_MINIT_FUNCTION(gmp)
{

View File

@@ -32,6 +32,7 @@ ZEND_MODULE_INFO_D(gmp);
ZEND_BEGIN_MODULE_GLOBALS(gmp)
bool rand_initialized;
gmp_randstate_t rand_state;
mpz_t zpp_arg[3];
ZEND_END_MODULE_GLOBALS(gmp)
#define GMPG(v) ZEND_MODULE_GLOBALS_ACCESSOR(gmp, v)