Skip to content

Commit 2646f7b

Browse files
committed
Don't count variadic argument in zend_func.common.num_args. This allows faster CALL/RETURN code.
1 parent 2bc63e7 commit 2646f7b

14 files changed

+87
-46
lines changed

UPGRADING

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ PHP X.Y UPGRADE NOTES
5151
and heredocs means that \u{ followed by an invalid sequence will now error.
5252
However, \u without a following { is unaffected, so "\u202e" won't error and
5353
will work the same as before.
54+
. zend_function.common.num_args don't include the variadic argument anymore.
5455

5556
- DBA
5657
. dba_delete() now returns false if the key was not found for the inifile

Zend/zend_API.c

+2
Original file line numberDiff line numberDiff line change
@@ -2206,6 +2206,8 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
22062206
}
22072207
if (ptr->arg_info[ptr->num_args].is_variadic) {
22082208
internal_function->fn_flags |= ZEND_ACC_VARIADIC;
2209+
/* Don't count the variadic argument */
2210+
internal_function->num_args--;
22092211
}
22102212
} else {
22112213
internal_function->arg_info = NULL;

Zend/zend_builtin_functions.c

-9
Original file line numberDiff line numberDiff line change
@@ -443,9 +443,6 @@ ZEND_FUNCTION(func_get_arg)
443443
}
444444

445445
first_extra_arg = ex->func->op_array.num_args;
446-
if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
447-
first_extra_arg--;
448-
}
449446
if (requested_offset >= first_extra_arg && (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg)) {
450447
arg = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
451448
} else {
@@ -476,9 +473,6 @@ ZEND_FUNCTION(func_get_args)
476473
Bucket *q;
477474

478475
first_extra_arg = ex->func->op_array.num_args;
479-
if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
480-
first_extra_arg--;
481-
}
482476
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
483477
i = 0;
484478
q = Z_ARRVAL_P(return_value)->arData;
@@ -2136,9 +2130,6 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /
21362130
if (call->func->type == ZEND_USER_FUNCTION) {
21372131
uint32_t first_extra_arg = call->func->op_array.num_args;
21382132

2139-
if (call->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
2140-
first_extra_arg--;
2141-
}
21422133
if (ZEND_CALL_NUM_ARGS(call) > first_extra_arg) {
21432134
while (i < first_extra_arg) {
21442135
if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);

Zend/zend_closures.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,15 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{
361361
}
362362

363363
if (arg_info) {
364-
uint32_t i, required = closure->func.common.required_num_args;
364+
uint32_t i, num_args, required = closure->func.common.required_num_args;
365365

366366
array_init(&val);
367367

368-
for (i = 0; i < closure->func.common.num_args; i++) {
368+
num_args = closure->func.common.num_args;
369+
if (closure->func.common.fn_flags & ZEND_ACC_VARIADIC) {
370+
num_args++;
371+
}
372+
for (i = 0; i < num_args; i++) {
369373
zend_string *name;
370374
zval info;
371375
if (arg_info->name) {

Zend/zend_compile.c

+5
Original file line numberDiff line numberDiff line change
@@ -3884,6 +3884,11 @@ void zend_compile_params(zend_ast *ast) /* {{{ */
38843884
/* These are assigned at the end to avoid unitialized memory in case of an error */
38853885
op_array->num_args = list->children;
38863886
op_array->arg_info = arg_infos;
3887+
3888+
/* Don't count the variadic argument */
3889+
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
3890+
op_array->num_args--;
3891+
}
38873892
}
38883893
/* }}} */
38893894

Zend/zend_compile.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -835,13 +835,14 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf,
835835
if (UNEXPECTED(zf->common.arg_info == NULL)) {
836836
return 0;
837837
}
838-
if (UNEXPECTED(arg_num > zf->common.num_args)) {
838+
arg_num--;
839+
if (UNEXPECTED(arg_num >= zf->common.num_args)) {
839840
if (EXPECTED((zf->common.fn_flags & ZEND_ACC_VARIADIC) == 0)) {
840841
return 0;
841842
}
842843
arg_num = zf->common.num_args;
843844
}
844-
return UNEXPECTED((zf->common.arg_info[arg_num-1].pass_by_reference & mask) != 0);
845+
return UNEXPECTED((zf->common.arg_info[arg_num].pass_by_reference & mask) != 0);
845846
}
846847

847848
#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \

Zend/zend_execute.c

+3-9
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, z
622622
if (EXPECTED(arg_num <= zf->internal_function.num_args)) {
623623
cur_arg_info = &zf->internal_function.arg_info[arg_num-1];
624624
} else if (zf->internal_function.fn_flags & ZEND_ACC_VARIADIC) {
625-
cur_arg_info = &zf->internal_function.arg_info[zf->internal_function.num_args-1];
625+
cur_arg_info = &zf->internal_function.arg_info[zf->internal_function.num_args];
626626
} else {
627627
return;
628628
}
@@ -671,7 +671,7 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg,
671671
if (EXPECTED(arg_num <= zf->common.num_args)) {
672672
cur_arg_info = &zf->common.arg_info[arg_num-1];
673673
} else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
674-
cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
674+
cur_arg_info = &zf->common.arg_info[zf->common.num_args];
675675
} else {
676676
return;
677677
}
@@ -720,7 +720,7 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n
720720
if (EXPECTED(arg_num <= zf->common.num_args)) {
721721
cur_arg_info = &zf->common.arg_info[arg_num-1];
722722
} else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
723-
cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
723+
cur_arg_info = &zf->common.arg_info[zf->common.num_args];
724724
} else {
725725
return 1;
726726
}
@@ -1626,9 +1626,6 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
16261626

16271627
/* Handle arguments */
16281628
first_extra_arg = op_array->num_args;
1629-
if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
1630-
first_extra_arg--;
1631-
}
16321629
num_args = EX_NUM_ARGS();
16331630
if (UNEXPECTED(num_args > first_extra_arg)) {
16341631
zval *end, *src, *dst;
@@ -1721,9 +1718,6 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
17211718

17221719
/* Handle arguments */
17231720
first_extra_arg = op_array->num_args;
1724-
if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
1725-
first_extra_arg--;
1726-
}
17271721
num_args = EX_NUM_ARGS();
17281722
if (UNEXPECTED(num_args > first_extra_arg)) {
17291723
zval *end, *src, *dst;

Zend/zend_execute.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint3
176176

177177
static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call)
178178
{
179-
uint32_t first_extra_arg = call->func->op_array.num_args - ((call->func->common.fn_flags & ZEND_ACC_VARIADIC) != 0);
179+
uint32_t first_extra_arg = call->func->op_array.num_args;
180180

181181
if (UNEXPECTED(ZEND_CALL_NUM_ARGS(call) > first_extra_arg)) {
182182
zval *end = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);

Zend/zend_inheritance.c

+16-7
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,14 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
261261
* go through all the parameters of the function and not just those present in the
262262
* prototype. */
263263
num_args = proto->common.num_args;
264-
if ((proto->common.fn_flags & ZEND_ACC_VARIADIC)
265-
&& fe->common.num_args > proto->common.num_args) {
266-
num_args = fe->common.num_args;
264+
if (proto->common.fn_flags & ZEND_ACC_VARIADIC) {
265+
num_args++;
266+
if (fe->common.num_args >= proto->common.num_args) {
267+
num_args = fe->common.num_args;
268+
if (fe->common.fn_flags & ZEND_ACC_VARIADIC) {
269+
num_args++;
270+
}
271+
}
267272
}
268273

269274
for (i = 0; i < num_args; i++) {
@@ -273,7 +278,7 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
273278
if (i < proto->common.num_args) {
274279
proto_arg_info = &proto->common.arg_info[i];
275280
} else {
276-
proto_arg_info = &proto->common.arg_info[proto->common.num_args-1];
281+
proto_arg_info = &proto->common.arg_info[proto->common.num_args];
277282
}
278283

279284
if (ZEND_LOG_XOR(fe_arg_info->class_name, proto_arg_info->class_name)) {
@@ -380,11 +385,15 @@ static zend_string *zend_get_function_declaration(zend_function *fptr) /* {{{ */
380385
smart_str_appendc(&str, '(');
381386

382387
if (fptr->common.arg_info) {
383-
uint32_t i, required;
388+
uint32_t i, num_args, required;
384389
zend_arg_info *arg_info = fptr->common.arg_info;
385390

386391
required = fptr->common.required_num_args;
387-
for (i = 0; i < fptr->common.num_args;) {
392+
num_args = fptr->common.num_args;
393+
if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
394+
num_args++;
395+
}
396+
for (i = 0; i < num_args;) {
388397
if (arg_info->class_name) {
389398
const char *class_name;
390399
size_t class_name_len;
@@ -486,7 +495,7 @@ static zend_string *zend_get_function_declaration(zend_function *fptr) /* {{{ */
486495
}
487496
}
488497

489-
if (++i < fptr->common.num_args) {
498+
if (++i < num_args) {
490499
smart_str_appends(&str, ", ");
491500
}
492501
arg_info++;

Zend/zend_opcode.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,12 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
368368
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array);
369369
}
370370
if (op_array->arg_info) {
371-
for (i=0; i<op_array->num_args; i++) {
371+
uint32_t num_args = op_array->num_args;
372+
373+
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
374+
num_args++;
375+
}
376+
for (i = 0; i < num_args; i++) {
372377
zend_string_release(op_array->arg_info[i].name);
373378
if (op_array->arg_info[i].class_name) {
374379
zend_string_release(op_array->arg_info[i].class_name);

ext/opcache/zend_persist.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -419,10 +419,14 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
419419
ZEND_ASSERT(new_ptr != NULL);
420420
op_array->arg_info = new_ptr;
421421
} else {
422-
uint32_t i;
422+
uint32_t i, num_args;
423423

424-
zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
425-
for (i = 0; i < op_array->num_args; i++) {
424+
num_args = op_array->num_args;
425+
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
426+
num_args++;
427+
}
428+
zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * num_args);
429+
for (i = 0; i < num_args; i++) {
426430
if (op_array->arg_info[i].name) {
427431
zend_accel_store_interned_string(op_array->arg_info[i].name);
428432
}

ext/opcache/zend_persist_calc.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,14 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
194194
}
195195

196196
if (op_array->arg_info) {
197-
uint32_t i;
197+
uint32_t i, num_args;
198198

199-
ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
200-
for (i = 0; i < op_array->num_args; i++) {
199+
num_args = op_array->num_args;
200+
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
201+
num_args++;
202+
}
203+
ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * num_args);
204+
for (i = 0; i < num_args; i++) {
201205
if (op_array->arg_info[i].name) {
202206
ADD_INTERNED_STRING(op_array->arg_info[i].name, 1);
203207
}

ext/pdo/pdo_dbh.c

+2
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,8 @@ int pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind)
13121312
}
13131313
if (funcs->arg_info[funcs->num_args].is_variadic) {
13141314
ifunc->fn_flags |= ZEND_ACC_VARIADIC;
1315+
/* Don't count the variadic argument */
1316+
ifunc->num_args--;
13151317
}
13161318
} else {
13171319
ifunc->arg_info = NULL;

ext/reflection/php_reflection.c

+28-9
Original file line numberDiff line numberDiff line change
@@ -758,15 +758,19 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
758758
static void _function_parameter_string(string *str, zend_function *fptr, char* indent)
759759
{
760760
struct _zend_arg_info *arg_info = fptr->common.arg_info;
761-
uint32_t i, required = fptr->common.required_num_args;
761+
uint32_t i, num_args, required = fptr->common.required_num_args;
762762

763763
if (!arg_info) {
764764
return;
765765
}
766766

767+
num_args = fptr->common.num_args;
768+
if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
769+
num_args++;
770+
}
767771
string_printf(str, "\n");
768-
string_printf(str, "%s- Parameters [%d] {\n", indent, fptr->common.num_args);
769-
for (i = 0; i < fptr->common.num_args; i++) {
772+
string_printf(str, "%s- Parameters [%d] {\n", indent, num_args);
773+
for (i = 0; i < num_args; i++) {
770774
string_printf(str, "%s ", indent);
771775
_parameter_string(str, fptr, arg_info, i, required, indent);
772776
string_write(str, "\n", sizeof("\n")-1);
@@ -2019,11 +2023,17 @@ ZEND_METHOD(reflection_function, getNumberOfParameters)
20192023
{
20202024
reflection_object *intern;
20212025
zend_function *fptr;
2026+
uint32_t num_args;
20222027

20232028
METHOD_NOTSTATIC(reflection_function_abstract_ptr);
20242029
GET_REFLECTION_OBJECT_PTR(fptr);
20252030

2026-
RETURN_LONG(fptr->common.num_args);
2031+
num_args = fptr->common.num_args;
2032+
if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2033+
num_args++;
2034+
}
2035+
2036+
RETURN_LONG(num_args);
20272037
}
20282038
/* }}} */
20292039

@@ -2047,16 +2057,20 @@ ZEND_METHOD(reflection_function, getParameters)
20472057
{
20482058
reflection_object *intern;
20492059
zend_function *fptr;
2050-
uint32_t i;
2060+
uint32_t i, num_args;
20512061
struct _zend_arg_info *arg_info;
20522062

20532063
METHOD_NOTSTATIC(reflection_function_abstract_ptr);
20542064
GET_REFLECTION_OBJECT_PTR(fptr);
20552065

20562066
arg_info= fptr->common.arg_info;
2067+
num_args = fptr->common.num_args;
2068+
if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2069+
num_args++;
2070+
}
20572071

20582072
array_init(return_value);
2059-
for (i = 0; i < fptr->common.num_args; i++) {
2073+
for (i = 0; i < num_args; i++) {
20602074
zval parameter;
20612075

20622076
reflection_parameter_factory(_copy_function(fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, arg_info, i, fptr->common.required_num_args, &parameter);
@@ -2135,6 +2149,7 @@ ZEND_METHOD(reflection_parameter, __construct)
21352149
zend_function *fptr;
21362150
struct _zend_arg_info *arg_info;
21372151
int position;
2152+
uint32_t num_args;
21382153
zend_class_entry *ce = NULL;
21392154
zend_bool is_closure = 0;
21402155
zend_bool is_invoke = 0;
@@ -2235,9 +2250,13 @@ ZEND_METHOD(reflection_parameter, __construct)
22352250

22362251
/* Now, search for the parameter */
22372252
arg_info = fptr->common.arg_info;
2253+
num_args = fptr->common.num_args;
2254+
if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2255+
num_args++;
2256+
}
22382257
if (Z_TYPE_P(parameter) == IS_LONG) {
22392258
position= (int)Z_LVAL_P(parameter);
2240-
if (position < 0 || (uint32_t)position >= fptr->common.num_args) {
2259+
if (position < 0 || (uint32_t)position >= num_args) {
22412260
if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
22422261
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
22432262
zend_string_release(fptr->common.function_name);
@@ -2256,7 +2275,7 @@ ZEND_METHOD(reflection_parameter, __construct)
22562275
position= -1;
22572276
convert_to_string_ex(parameter);
22582277
if (!is_invoke && fptr->type == ZEND_INTERNAL_FUNCTION) {
2259-
for (i = 0; i < fptr->common.num_args; i++) {
2278+
for (i = 0; i < num_args; i++) {
22602279
if (arg_info[i].name) {
22612280
if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, Z_STRVAL_P(parameter)) == 0) {
22622281
position= i;
@@ -2266,7 +2285,7 @@ ZEND_METHOD(reflection_parameter, __construct)
22662285
}
22672286
}
22682287
} else {
2269-
for (i = 0; i < fptr->common.num_args; i++) {
2288+
for (i = 0; i < num_args; i++) {
22702289
if (arg_info[i].name) {
22712290
if (strcmp(arg_info[i].name->val, Z_STRVAL_P(parameter)) == 0) {
22722291
position= i;

0 commit comments

Comments
 (0)