mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Use fast method to check if first arguments should be passed by reference (not tested onbig endian).
This commit is contained in:
parent
af33279a6c
commit
15a5f61cf4
11 changed files with 103 additions and 6 deletions
|
@ -2232,6 +2232,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
|
|||
internal_function->num_args = 0;
|
||||
internal_function->required_num_args = 0;
|
||||
}
|
||||
zend_set_function_arg_flags((zend_function*)internal_function);
|
||||
if (ptr->flags & ZEND_ACC_ABSTRACT) {
|
||||
if (scope) {
|
||||
/* This is a class that must be abstract itself. Here we set the check info. */
|
||||
|
|
|
@ -4108,6 +4108,31 @@ void zend_compile_stmt_list(zend_ast *ast) /* {{{ */
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_set_function_arg_flags(zend_function *func) /* {{{ */
|
||||
{
|
||||
uint32_t i, n;
|
||||
|
||||
func->common.arg_flags[0] = 0;
|
||||
func->common.arg_flags[1] = 0;
|
||||
func->common.arg_flags[2] = 0;
|
||||
if (func->common.arg_info) {
|
||||
n = MIN(func->common.num_args, MAX_ARG_FLAG_NUM);
|
||||
i = 0;
|
||||
while (i < n) {
|
||||
ZEND_SET_ARG_FLAG(func, i + 1, func->common.arg_info[i].pass_by_reference);
|
||||
i++;
|
||||
}
|
||||
if (func->common.fn_flags & ZEND_ACC_VARIADIC) {
|
||||
uint32_t pass_by_reference = func->common.arg_info[i].pass_by_reference;
|
||||
while (i < MAX_ARG_FLAG_NUM) {
|
||||
ZEND_SET_ARG_FLAG(func, i + 1, pass_by_reference);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, zend_bool is_method) /* {{{ */
|
||||
{
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
|
@ -4294,6 +4319,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, zend_bool is_
|
|||
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
|
||||
op_array->num_args--;
|
||||
}
|
||||
zend_set_function_arg_flags((zend_function*)op_array);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
|
@ -334,6 +334,7 @@ typedef struct _zend_internal_function_info {
|
|||
struct _zend_op_array {
|
||||
/* Common elements */
|
||||
zend_uchar type;
|
||||
zend_uchar arg_flags[3]; /* bitset of arg_info.pass_by_reference */
|
||||
uint32_t fn_flags;
|
||||
zend_string *function_name;
|
||||
zend_class_entry *scope;
|
||||
|
@ -384,6 +385,7 @@ struct _zend_op_array {
|
|||
typedef struct _zend_internal_function {
|
||||
/* Common elements */
|
||||
zend_uchar type;
|
||||
zend_uchar arg_flags[3]; /* bitset of arg_info.pass_by_reference */
|
||||
uint32_t fn_flags;
|
||||
zend_string* function_name;
|
||||
zend_class_entry *scope;
|
||||
|
@ -404,6 +406,7 @@ union _zend_function {
|
|||
|
||||
struct {
|
||||
zend_uchar type; /* never used */
|
||||
zend_uchar arg_flags[3]; /* bitset of arg_info.pass_by_reference */
|
||||
uint32_t fn_flags;
|
||||
zend_string *function_name;
|
||||
zend_class_entry *scope;
|
||||
|
@ -776,6 +779,7 @@ ZEND_API void zend_activate_auto_globals(void);
|
|||
ZEND_API zend_bool zend_is_auto_global(zend_string *name);
|
||||
ZEND_API zend_bool zend_is_auto_global_str(char *name, size_t len);
|
||||
ZEND_API size_t zend_dirname(char *path, size_t len);
|
||||
ZEND_API int zend_set_function_arg_flags(zend_function *func);
|
||||
|
||||
int zendlex(zend_parser_stack_elem *elem);
|
||||
|
||||
|
@ -910,6 +914,32 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf,
|
|||
#define ARG_MAY_BE_SENT_BY_REF(zf, arg_num) \
|
||||
zend_check_arg_send_type(zf, arg_num, ZEND_SEND_PREFER_REF)
|
||||
|
||||
/* Quick API to check firat 12 arguments */
|
||||
#define MAX_ARG_FLAG_NUM 12
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define ZEND_SET_ARG_FLAG(zf, arg_num, mask) do { \
|
||||
*(uint32_t*)&(zf)->type |= ((mask) << ((arg_num) - 1) * 2); \
|
||||
} while (0)
|
||||
# define ZEND_CHECK_ARG_FLAG(zf, arg_num, mask) \
|
||||
(((*((uint32_t*)&((zf)->type))) >> (((arg_num) - 1) * 2)) & (mask))
|
||||
#else
|
||||
# define ZEND_SET_ARG_FLAG(zf, arg_num, mask) do { \
|
||||
*(uint32_t*)&(zf)->type |= (((mask) << 6) << (arg_num) * 2); \
|
||||
} while (0)
|
||||
# define ZEND_CHECK_ARG_FLAG(zf, arg_num, mask) \
|
||||
(((*(uint32_t*)&(zf)->type) >> (((arg_num) + 3) * 2)) & (mask))
|
||||
#endif
|
||||
|
||||
#define QUICK_ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \
|
||||
ZEND_CHECK_ARG_FLAG(zf, arg_num, ZEND_SEND_BY_REF)
|
||||
|
||||
#define QUICK_ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num) \
|
||||
ZEND_CHECK_ARG_FLAG(zf, arg_num, ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF)
|
||||
|
||||
#define QUICK_ARG_MAY_BE_SENT_BY_REF(zf, arg_num) \
|
||||
ZEND_CHECK_ARG_FLAG(zf, arg_num, ZEND_SEND_PREFER_REF)
|
||||
|
||||
#define ZEND_RETURN_VAL 0
|
||||
#define ZEND_RETURN_REF 1
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ static ZEND_FUNCTION(pass)
|
|||
|
||||
static const zend_internal_function zend_pass_function = {
|
||||
ZEND_INTERNAL_FUNCTION, /* type */
|
||||
{0, 0, 0}, /* arg_flags */
|
||||
0, /* fn_flags */
|
||||
NULL, /* name */
|
||||
NULL, /* scope */
|
||||
|
|
|
@ -1007,6 +1007,9 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend
|
|||
}
|
||||
|
||||
func->type = ZEND_USER_FUNCTION;
|
||||
func->arg_flags[0] = 0;
|
||||
func->arg_flags[1] = 0;
|
||||
func->arg_flags[2] = 0;
|
||||
func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_PUBLIC;
|
||||
if (is_static) {
|
||||
func->fn_flags |= ZEND_ACC_STATIC;
|
||||
|
|
|
@ -51,6 +51,9 @@ static void op_array_alloc_ops(zend_op_array *op_array, uint32_t size)
|
|||
void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size)
|
||||
{
|
||||
op_array->type = type;
|
||||
op_array->arg_flags[0] = 0;
|
||||
op_array->arg_flags[1] = 0;
|
||||
op_array->arg_flags[2] = 0;
|
||||
|
||||
op_array->refcount = (uint32_t *) emalloc(sizeof(uint32_t));
|
||||
*op_array->refcount = 1;
|
||||
|
|
|
@ -4085,7 +4085,12 @@ ZEND_VM_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, ANY)
|
|||
zval *value, *arg;
|
||||
zend_free_op free_op1;
|
||||
|
||||
if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
if (EXPECTED(opline->op2.num <= MAX_ARG_FLAG_NUM)) {
|
||||
if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
ZEND_VM_C_GOTO(send_val_by_ref);
|
||||
}
|
||||
} else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
ZEND_VM_C_LABEL(send_val_by_ref):
|
||||
SAVE_OPLINE();
|
||||
zend_error(E_EXCEPTION | E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
|
||||
FREE_UNFETCHED_OP1();
|
||||
|
@ -4225,7 +4230,12 @@ ZEND_VM_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, ANY)
|
|||
zval *varptr, *arg;
|
||||
zend_free_op free_op1;
|
||||
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
if (EXPECTED(opline->op2.num <= MAX_ARG_FLAG_NUM)) {
|
||||
if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
ZEND_VM_C_GOTO(send_var_by_ref);
|
||||
}
|
||||
} else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
ZEND_VM_C_LABEL(send_var_by_ref):
|
||||
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF);
|
||||
}
|
||||
|
||||
|
|
|
@ -3215,7 +3215,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER
|
|||
zval *value, *arg;
|
||||
|
||||
|
||||
if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
if (EXPECTED(opline->op2.num <= MAX_ARG_FLAG_NUM)) {
|
||||
if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
goto send_val_by_ref;
|
||||
}
|
||||
} else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
send_val_by_ref:
|
||||
SAVE_OPLINE();
|
||||
zend_error(E_EXCEPTION | E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
|
||||
|
||||
|
@ -11466,7 +11471,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(Z
|
|||
zval *value, *arg;
|
||||
zend_free_op free_op1;
|
||||
|
||||
if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
if (EXPECTED(opline->op2.num <= MAX_ARG_FLAG_NUM)) {
|
||||
if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
goto send_val_by_ref;
|
||||
}
|
||||
} else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
send_val_by_ref:
|
||||
SAVE_OPLINE();
|
||||
zend_error(E_EXCEPTION | E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
|
||||
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
|
||||
|
@ -14703,7 +14713,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(Z
|
|||
zval *varptr, *arg;
|
||||
zend_free_op free_op1;
|
||||
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
if (EXPECTED(opline->op2.num <= MAX_ARG_FLAG_NUM)) {
|
||||
if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
goto send_var_by_ref;
|
||||
}
|
||||
} else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
send_var_by_ref:
|
||||
return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
|
||||
|
@ -28441,7 +28456,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_HANDLER(ZE
|
|||
zval *varptr, *arg;
|
||||
|
||||
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
if (EXPECTED(opline->op2.num <= MAX_ARG_FLAG_NUM)) {
|
||||
if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
goto send_var_by_ref;
|
||||
}
|
||||
} else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
||||
send_var_by_ref:
|
||||
return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
|
||||
|
|
|
@ -279,6 +279,7 @@ static union _zend_function *com_method_get(zend_object **object_ptr, zend_strin
|
|||
f.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
|
||||
f.function_name = zend_string_copy(name);
|
||||
f.handler = PHP_FN(com_method_handler);
|
||||
zend_set_function_arg_flags((zend_function*)&f);
|
||||
|
||||
fptr = &f;
|
||||
|
||||
|
|
|
@ -1319,6 +1319,7 @@ int pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind)
|
|||
ifunc->num_args = 0;
|
||||
ifunc->required_num_args = 0;
|
||||
}
|
||||
zend_set_function_arg_flags((zend_function*)ifunc);
|
||||
namelen = strlen(funcs->fname);
|
||||
lc_name = emalloc(namelen+1);
|
||||
zend_str_tolower_copy(lc_name, funcs->fname, namelen);
|
||||
|
|
|
@ -668,6 +668,7 @@ PHP_MINIT_FUNCTION(soap)
|
|||
fe.prototype = NULL;
|
||||
fe.num_args = 2;
|
||||
fe.arg_info = NULL;
|
||||
zend_set_function_arg_flags((zend_function*)&fe);
|
||||
|
||||
INIT_OVERLOADED_CLASS_ENTRY(ce, PHP_SOAP_CLIENT_CLASSNAME, soap_client_functions,
|
||||
(zend_function *)&fe, NULL, NULL);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue