Skip to content

Commit

Permalink
Don't count variadic argument in zend_func.common.num_args. This allo…
Browse files Browse the repository at this point in the history
…ws faster CALL/RETURN code.
  • Loading branch information
dstogov committed Dec 22, 2014
1 parent 2bc63e7 commit 2646f7b
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 46 deletions.
1 change: 1 addition & 0 deletions UPGRADING
Expand Up @@ -51,6 +51,7 @@ PHP X.Y UPGRADE NOTES
and heredocs means that \u{ followed by an invalid sequence will now error.
However, \u without a following { is unaffected, so "\u202e" won't error and
will work the same as before.
. zend_function.common.num_args don't include the variadic argument anymore.

- DBA
. dba_delete() now returns false if the key was not found for the inifile
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_API.c
Expand Up @@ -2206,6 +2206,8 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
if (ptr->arg_info[ptr->num_args].is_variadic) {
internal_function->fn_flags |= ZEND_ACC_VARIADIC;
/* Don't count the variadic argument */
internal_function->num_args--;
}
} else {
internal_function->arg_info = NULL;
Expand Down
9 changes: 0 additions & 9 deletions Zend/zend_builtin_functions.c
Expand Up @@ -443,9 +443,6 @@ ZEND_FUNCTION(func_get_arg)
}

first_extra_arg = ex->func->op_array.num_args;
if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
first_extra_arg--;
}
if (requested_offset >= first_extra_arg && (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg)) {
arg = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
} else {
Expand Down Expand Up @@ -476,9 +473,6 @@ ZEND_FUNCTION(func_get_args)
Bucket *q;

first_extra_arg = ex->func->op_array.num_args;
if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
first_extra_arg--;
}
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
i = 0;
q = Z_ARRVAL_P(return_value)->arData;
Expand Down Expand Up @@ -2136,9 +2130,6 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /
if (call->func->type == ZEND_USER_FUNCTION) {
uint32_t first_extra_arg = call->func->op_array.num_args;

if (call->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
first_extra_arg--;
}
if (ZEND_CALL_NUM_ARGS(call) > first_extra_arg) {
while (i < first_extra_arg) {
if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);
Expand Down
8 changes: 6 additions & 2 deletions Zend/zend_closures.c
Expand Up @@ -361,11 +361,15 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{
}

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

array_init(&val);

for (i = 0; i < closure->func.common.num_args; i++) {
num_args = closure->func.common.num_args;
if (closure->func.common.fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
}
for (i = 0; i < num_args; i++) {
zend_string *name;
zval info;
if (arg_info->name) {
Expand Down
5 changes: 5 additions & 0 deletions Zend/zend_compile.c
Expand Up @@ -3884,6 +3884,11 @@ void zend_compile_params(zend_ast *ast) /* {{{ */
/* These are assigned at the end to avoid unitialized memory in case of an error */
op_array->num_args = list->children;
op_array->arg_info = arg_infos;

/* Don't count the variadic argument */
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
op_array->num_args--;
}
}
/* }}} */

Expand Down
5 changes: 3 additions & 2 deletions Zend/zend_compile.h
Expand Up @@ -835,13 +835,14 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf,
if (UNEXPECTED(zf->common.arg_info == NULL)) {
return 0;
}
if (UNEXPECTED(arg_num > zf->common.num_args)) {
arg_num--;
if (UNEXPECTED(arg_num >= zf->common.num_args)) {
if (EXPECTED((zf->common.fn_flags & ZEND_ACC_VARIADIC) == 0)) {
return 0;
}
arg_num = zf->common.num_args;
}
return UNEXPECTED((zf->common.arg_info[arg_num-1].pass_by_reference & mask) != 0);
return UNEXPECTED((zf->common.arg_info[arg_num].pass_by_reference & mask) != 0);
}

#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \
Expand Down
12 changes: 3 additions & 9 deletions Zend/zend_execute.c
Expand Up @@ -622,7 +622,7 @@ static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, z
if (EXPECTED(arg_num <= zf->internal_function.num_args)) {
cur_arg_info = &zf->internal_function.arg_info[arg_num-1];
} else if (zf->internal_function.fn_flags & ZEND_ACC_VARIADIC) {
cur_arg_info = &zf->internal_function.arg_info[zf->internal_function.num_args-1];
cur_arg_info = &zf->internal_function.arg_info[zf->internal_function.num_args];
} else {
return;
}
Expand Down Expand Up @@ -671,7 +671,7 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg,
if (EXPECTED(arg_num <= zf->common.num_args)) {
cur_arg_info = &zf->common.arg_info[arg_num-1];
} else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
cur_arg_info = &zf->common.arg_info[zf->common.num_args];
} else {
return;
}
Expand Down Expand Up @@ -720,7 +720,7 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n
if (EXPECTED(arg_num <= zf->common.num_args)) {
cur_arg_info = &zf->common.arg_info[arg_num-1];
} else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
cur_arg_info = &zf->common.arg_info[zf->common.num_args];
} else {
return 1;
}
Expand Down Expand Up @@ -1626,9 +1626,6 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu

/* Handle arguments */
first_extra_arg = op_array->num_args;
if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
first_extra_arg--;
}
num_args = EX_NUM_ARGS();
if (UNEXPECTED(num_args > first_extra_arg)) {
zval *end, *src, *dst;
Expand Down Expand Up @@ -1721,9 +1718,6 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da

/* Handle arguments */
first_extra_arg = op_array->num_args;
if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
first_extra_arg--;
}
num_args = EX_NUM_ARGS();
if (UNEXPECTED(num_args > first_extra_arg)) {
zval *end, *src, *dst;
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_execute.h
Expand Up @@ -176,7 +176,7 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint3

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

if (UNEXPECTED(ZEND_CALL_NUM_ARGS(call) > first_extra_arg)) {
zval *end = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
Expand Down
23 changes: 16 additions & 7 deletions Zend/zend_inheritance.c
Expand Up @@ -261,9 +261,14 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
* go through all the parameters of the function and not just those present in the
* prototype. */
num_args = proto->common.num_args;
if ((proto->common.fn_flags & ZEND_ACC_VARIADIC)
&& fe->common.num_args > proto->common.num_args) {
num_args = fe->common.num_args;
if (proto->common.fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
if (fe->common.num_args >= proto->common.num_args) {
num_args = fe->common.num_args;
if (fe->common.fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
}
}
}

for (i = 0; i < num_args; i++) {
Expand All @@ -273,7 +278,7 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
if (i < proto->common.num_args) {
proto_arg_info = &proto->common.arg_info[i];
} else {
proto_arg_info = &proto->common.arg_info[proto->common.num_args-1];
proto_arg_info = &proto->common.arg_info[proto->common.num_args];
}

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

if (fptr->common.arg_info) {
uint32_t i, required;
uint32_t i, num_args, required;
zend_arg_info *arg_info = fptr->common.arg_info;

required = fptr->common.required_num_args;
for (i = 0; i < fptr->common.num_args;) {
num_args = fptr->common.num_args;
if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
}
for (i = 0; i < num_args;) {
if (arg_info->class_name) {
const char *class_name;
size_t class_name_len;
Expand Down Expand Up @@ -486,7 +495,7 @@ static zend_string *zend_get_function_declaration(zend_function *fptr) /* {{{ */
}
}

if (++i < fptr->common.num_args) {
if (++i < num_args) {
smart_str_appends(&str, ", ");
}
arg_info++;
Expand Down
7 changes: 6 additions & 1 deletion Zend/zend_opcode.c
Expand Up @@ -368,7 +368,12 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array);
}
if (op_array->arg_info) {
for (i=0; i<op_array->num_args; i++) {
uint32_t num_args = op_array->num_args;

if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
}
for (i = 0; i < num_args; i++) {
zend_string_release(op_array->arg_info[i].name);
if (op_array->arg_info[i].class_name) {
zend_string_release(op_array->arg_info[i].class_name);
Expand Down
10 changes: 7 additions & 3 deletions ext/opcache/zend_persist.c
Expand Up @@ -419,10 +419,14 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
ZEND_ASSERT(new_ptr != NULL);
op_array->arg_info = new_ptr;
} else {
uint32_t i;
uint32_t i, num_args;

zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
for (i = 0; i < op_array->num_args; i++) {
num_args = op_array->num_args;
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
}
zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * num_args);
for (i = 0; i < num_args; i++) {
if (op_array->arg_info[i].name) {
zend_accel_store_interned_string(op_array->arg_info[i].name);
}
Expand Down
10 changes: 7 additions & 3 deletions ext/opcache/zend_persist_calc.c
Expand Up @@ -194,10 +194,14 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
}

if (op_array->arg_info) {
uint32_t i;
uint32_t i, num_args;

ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
for (i = 0; i < op_array->num_args; i++) {
num_args = op_array->num_args;
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
}
ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * num_args);
for (i = 0; i < num_args; i++) {
if (op_array->arg_info[i].name) {
ADD_INTERNED_STRING(op_array->arg_info[i].name, 1);
}
Expand Down
2 changes: 2 additions & 0 deletions ext/pdo/pdo_dbh.c
Expand Up @@ -1312,6 +1312,8 @@ int pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind)
}
if (funcs->arg_info[funcs->num_args].is_variadic) {
ifunc->fn_flags |= ZEND_ACC_VARIADIC;
/* Don't count the variadic argument */
ifunc->num_args--;
}
} else {
ifunc->arg_info = NULL;
Expand Down
37 changes: 28 additions & 9 deletions ext/reflection/php_reflection.c
Expand Up @@ -758,15 +758,19 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
static void _function_parameter_string(string *str, zend_function *fptr, char* indent)
{
struct _zend_arg_info *arg_info = fptr->common.arg_info;
uint32_t i, required = fptr->common.required_num_args;
uint32_t i, num_args, required = fptr->common.required_num_args;

if (!arg_info) {
return;
}

num_args = fptr->common.num_args;
if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
}
string_printf(str, "\n");
string_printf(str, "%s- Parameters [%d] {\n", indent, fptr->common.num_args);
for (i = 0; i < fptr->common.num_args; i++) {
string_printf(str, "%s- Parameters [%d] {\n", indent, num_args);
for (i = 0; i < num_args; i++) {
string_printf(str, "%s ", indent);
_parameter_string(str, fptr, arg_info, i, required, indent);
string_write(str, "\n", sizeof("\n")-1);
Expand Down Expand Up @@ -2019,11 +2023,17 @@ ZEND_METHOD(reflection_function, getNumberOfParameters)
{
reflection_object *intern;
zend_function *fptr;
uint32_t num_args;

METHOD_NOTSTATIC(reflection_function_abstract_ptr);
GET_REFLECTION_OBJECT_PTR(fptr);

RETURN_LONG(fptr->common.num_args);
num_args = fptr->common.num_args;
if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
}

RETURN_LONG(num_args);
}
/* }}} */

Expand All @@ -2047,16 +2057,20 @@ ZEND_METHOD(reflection_function, getParameters)
{
reflection_object *intern;
zend_function *fptr;
uint32_t i;
uint32_t i, num_args;
struct _zend_arg_info *arg_info;

METHOD_NOTSTATIC(reflection_function_abstract_ptr);
GET_REFLECTION_OBJECT_PTR(fptr);

arg_info= fptr->common.arg_info;
num_args = fptr->common.num_args;
if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
}

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

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

/* Now, search for the parameter */
arg_info = fptr->common.arg_info;
num_args = fptr->common.num_args;
if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
num_args++;
}
if (Z_TYPE_P(parameter) == IS_LONG) {
position= (int)Z_LVAL_P(parameter);
if (position < 0 || (uint32_t)position >= fptr->common.num_args) {
if (position < 0 || (uint32_t)position >= num_args) {
if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
zend_string_release(fptr->common.function_name);
Expand All @@ -2256,7 +2275,7 @@ ZEND_METHOD(reflection_parameter, __construct)
position= -1;
convert_to_string_ex(parameter);
if (!is_invoke && fptr->type == ZEND_INTERNAL_FUNCTION) {
for (i = 0; i < fptr->common.num_args; i++) {
for (i = 0; i < num_args; i++) {
if (arg_info[i].name) {
if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, Z_STRVAL_P(parameter)) == 0) {
position= i;
Expand All @@ -2266,7 +2285,7 @@ ZEND_METHOD(reflection_parameter, __construct)
}
}
} else {
for (i = 0; i < fptr->common.num_args; i++) {
for (i = 0; i < num_args; i++) {
if (arg_info[i].name) {
if (strcmp(arg_info[i].name->val, Z_STRVAL_P(parameter)) == 0) {
position= i;
Expand Down

0 comments on commit 2646f7b

Please sign in to comment.