diff options
-rw-r--r-- | Zend/zend_compile.c | 28 | ||||
-rw-r--r-- | Zend/zend_compile.h | 2 | ||||
-rw-r--r-- | Zend/zend_execute.c | 140 | ||||
-rw-r--r-- | Zend/zend_execute.h | 1 | ||||
-rw-r--r-- | Zend/zend_opcode.c | 4 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 16 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 40 | ||||
-rw-r--r-- | ext/opcache/Optimizer/compact_literals.c | 31 | ||||
-rw-r--r-- | ext/opcache/zend_file_cache.c | 6 | ||||
-rw-r--r-- | ext/opcache/zend_persist.c | 3 | ||||
-rw-r--r-- | ext/opcache/zend_persist_calc.c | 3 |
11 files changed, 171 insertions, 103 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0eecbf6810..5045d4c85d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2032,7 +2032,6 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */ } /* }}} */ - static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) /* {{{ */ { if (return_info->type_hint != IS_UNDEF) { @@ -2041,11 +2040,16 @@ static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) opline->result_type = expr->op_type = IS_TMP_VAR; opline->result.var = expr->u.op.var = get_temporary_variable(CG(active_op_array)); } + if (return_info->class_name) { + opline->op2.num = CG(active_op_array)->cache_size; + CG(active_op_array)->cache_size += sizeof(void*); + } else { + opline->op2.num = -1; + } } } /* }}} */ - void zend_emit_final_return(zval *zv) /* {{{ */ { znode zn; @@ -4222,7 +4226,6 @@ ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */ } /* }}} */ - static void zend_compile_typename(zend_ast *ast, zend_arg_info *arg_info) /* {{{ */ { if (ast->kind == ZEND_AST_TYPE) { @@ -4238,11 +4241,9 @@ static void zend_compile_typename(zend_ast *ast, zend_arg_info *arg_info) /* {{{ if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) { class_name = zend_resolve_class_name_ast(ast); zend_assert_valid_class_name(class_name); - arg_info->lower_class_name = zend_string_tolower(class_name); } else { zend_ensure_valid_class_fetch_type(fetch_type); zend_string_addref(class_name); - arg_info->lower_class_name = NULL; } arg_info->type_hint = IS_OBJECT; @@ -4252,7 +4253,6 @@ static void zend_compile_typename(zend_ast *ast, zend_arg_info *arg_info) /* {{{ } /* }}} */ - void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); @@ -4390,6 +4390,22 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ } } } + + /* Allocate cache slot to speed-up run-time class resolution */ + if (opline->opcode == ZEND_RECV_INIT) { + if (arg_info->class_name) { + zend_alloc_cache_slot(opline->op2.constant); + } else { + Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = -1; + } + } else { + if (arg_info->class_name) { + opline->op2.num = op_array->cache_size; + op_array->cache_size += sizeof(void*); + } else { + opline->op2.num = -1; + } + } } } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 1ed6e236b0..106d0fc475 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -300,7 +300,6 @@ typedef struct _zend_internal_arg_info { zend_uchar pass_by_reference; zend_bool allow_null; zend_bool is_variadic; - void *reserved; /* to align with zend_arg_info */ } zend_internal_arg_info; /* arg_info for user functions */ @@ -311,7 +310,6 @@ typedef struct _zend_arg_info { zend_uchar pass_by_reference; zend_bool allow_null; zend_bool is_variadic; - zend_string *lower_class_name; } zend_arg_info; /* the following structure repeats the layout of zend_internal_arg_info, diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index e63fc2dd32..9190eff2c3 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -585,21 +585,9 @@ ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info } } -ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce) +static zend_always_inline zend_class_entry* zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info) { - /* optimization to not always recalculate the lowercase name and hash */ - if (cur_arg_info->lower_class_name) { - *pce = zend_hash_find_ptr(EG(class_table), cur_arg_info->lower_class_name); - } else { /* "extra" fetch type */ - *pce = zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); - } - - *class_name = (*pce) ? (*pce)->name->val : cur_arg_info->class_name->val; - if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) { - return "implement interface "; - } else { - return "be an instance of "; - } + return zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); } ZEND_API void zend_verify_arg_error(const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg) @@ -749,15 +737,15 @@ static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, z } } -static int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value) +static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot) { zend_arg_info *cur_arg_info; - char *need_msg, *class_name; + char *need_msg; zend_class_entry *ce; 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) { + } else if (UNEXPECTED(zf->common.fn_flags & ZEND_ACC_VARIADIC)) { cur_arg_info = &zf->common.arg_info[zf->common.num_args]; } else { return 1; @@ -767,16 +755,40 @@ static int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, ZVAL_DEREF(arg); if (EXPECTED(cur_arg_info->type_hint == Z_TYPE_P(arg))) { if (cur_arg_info->class_name) { - need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); - if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) { - zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + if (EXPECTED(*cache_slot)) { + ce = (zend_class_entry*)*cache_slot; + } else { + ce = zend_verify_arg_class_kind(cur_arg_info); + if (UNEXPECTED(!ce)) { + zend_verify_arg_error(zf, arg_num, "be an instance of ", cur_arg_info->class_name->val, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + return 0; + } + *cache_slot = (void*)ce; + } + if (UNEXPECTED(!instanceof_function(Z_OBJCE_P(arg), ce))) { + need_msg = + (ce->ce_flags & ZEND_ACC_INTERFACE) ? + "implement interface " : "be an instance of "; + zend_verify_arg_error(zf, arg_num, need_msg, ce->name->val, "instance of ", Z_OBJCE_P(arg)->name->val, arg); return 0; } } } else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value)))) { if (cur_arg_info->class_name) { - need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); - zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); + if (EXPECTED(*cache_slot)) { + ce = (zend_class_entry*)*cache_slot; + } else { + ce = zend_verify_arg_class_kind(cur_arg_info); + if (UNEXPECTED(!ce)) { + zend_verify_arg_error(zf, arg_num, "be an instance of ", cur_arg_info->class_name->val, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + return 0; + } + *cache_slot = (void*)ce; + } + need_msg = + (ce->ce_flags & ZEND_ACC_INTERFACE) ? + "implement interface " : "be an instance of "; + zend_verify_arg_error(zf, arg_num, need_msg, ce->name->val, zend_zval_type_name(arg), "", arg); return 0; } else if (cur_arg_info->type_hint == IS_CALLABLE) { if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL)) { @@ -795,7 +807,7 @@ static int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, return 1; } -static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num) +static zend_always_inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num, void **cache_slot) { zend_arg_info *cur_arg_info; char *need_msg; @@ -803,7 +815,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) { + } else if (UNEXPECTED(zf->common.fn_flags & ZEND_ACC_VARIADIC)) { cur_arg_info = &zf->common.arg_info[zf->common.num_args]; } else { return 1; @@ -811,10 +823,20 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n if (cur_arg_info->type_hint) { if (cur_arg_info->class_name) { - char *class_name; - - need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); - zend_verify_arg_error(zf, arg_num, need_msg, class_name, "none", "", NULL); + if (EXPECTED(*cache_slot)) { + ce = (zend_class_entry*)*cache_slot; + } else { + ce = zend_verify_arg_class_kind(cur_arg_info); + if (UNEXPECTED(!ce)) { + zend_verify_arg_error(zf, arg_num, "be an instance of ", cur_arg_info->class_name->val, "none", "", NULL); + return 0; + } + *cache_slot = (void*)ce; + } + need_msg = + (ce->ce_flags & ZEND_ACC_INTERFACE) ? + "implement interface " : "be an instance of "; + zend_verify_arg_error(zf, arg_num, need_msg, ce->name->val, "none", "", NULL); } else if (cur_arg_info->type_hint == IS_CALLABLE) { zend_verify_arg_error(zf, arg_num, "be callable", "", "none", "", NULL); } else { @@ -825,10 +847,10 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n return 1; } -static int zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num) +static zend_always_inline int zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num, void **cache_slot) { if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) || - zend_verify_missing_arg_type(EX(func), arg_num)) { + zend_verify_missing_arg_type(EX(func), arg_num, cache_slot)) { const char *class_name = EX(func)->common.scope ? EX(func)->common.scope->name->val : ""; const char *space = EX(func)->common.scope ? "::" : ""; const char *func_name = EX(func)->common.function_name ? EX(func)->common.function_name->val : "main"; @@ -926,24 +948,48 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret) } #endif -static void zend_verify_return_type(zend_function *zf, zval *ret) +static zend_always_inline void zend_verify_return_type(zend_function *zf, zval *ret, void **cache_slot) { zend_arg_info *ret_info = zf->common.arg_info - 1; - char *need_msg, *class_name; + char *need_msg; zend_class_entry *ce; if (ret_info->type_hint) { if (EXPECTED(ret_info->type_hint == Z_TYPE_P(ret))) { if (ret_info->class_name) { - need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); - if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) { - zend_verify_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); + if (EXPECTED(*cache_slot)) { + ce = (zend_class_entry*)*cache_slot; + } else { + ce = zend_verify_arg_class_kind(ret_info); + if (UNEXPECTED(!ce)) { + zend_verify_return_error(zf, "be an instance of ", ret_info->class_name->val, "instance of ", Z_OBJCE_P(ret)->name->val); + return; + } + *cache_slot = (void*)ce; + } + if (UNEXPECTED(!instanceof_function(Z_OBJCE_P(ret), ce))) { + need_msg = + (ce->ce_flags & ZEND_ACC_INTERFACE) ? + "implement interface " : "be an instance of "; + zend_verify_return_error(zf, need_msg, ce->name->val, "instance of ", Z_OBJCE_P(ret)->name->val); } } } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) { if (ret_info->class_name) { - need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); - zend_verify_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), ""); + if (EXPECTED(*cache_slot)) { + ce = (zend_class_entry*)*cache_slot; + } else { + ce = zend_verify_arg_class_kind(ret_info); + if (UNEXPECTED(!ce)) { + zend_verify_return_error(zf, "be an instance of ", ret_info->class_name->val, zend_zval_type_name(ret), ""); + return; + } + *cache_slot = (void*)ce; + } + need_msg = + (ce->ce_flags & ZEND_ACC_INTERFACE) ? + "implement interface " : "be an instance of "; + zend_verify_return_error(zf, need_msg, ce->name->val, zend_zval_type_name(ret), ""); } else if (ret_info->type_hint == IS_CALLABLE) { if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL)) { zend_verify_return_error(zf, "be callable", "", zend_zval_type_name(ret), ""); @@ -958,7 +1004,7 @@ static void zend_verify_return_type(zend_function *zf, zval *ret) } } -static inline int zend_verify_missing_return_type(zend_function *zf) +static zend_always_inline int zend_verify_missing_return_type(zend_function *zf, void **cache_slot) { zend_arg_info *ret_info = zf->common.arg_info - 1; char *need_msg; @@ -966,10 +1012,20 @@ static inline int zend_verify_missing_return_type(zend_function *zf) if (ret_info->type_hint) { if (ret_info->class_name) { - char *class_name; - - need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); - zend_verify_return_error(zf, need_msg, class_name, "none", ""); + if (EXPECTED(*cache_slot)) { + ce = (zend_class_entry*)*cache_slot; + } else { + ce = zend_verify_arg_class_kind(ret_info); + if (UNEXPECTED(!ce)) { + zend_verify_return_error(zf, "be an instance of ", ret_info->class_name->val, "none", ""); + return 0; + } + *cache_slot = (void*)ce; + } + need_msg = + (ce->ce_flags & ZEND_ACC_INTERFACE) ? + "implement interface " : "be an instance of "; + zend_verify_return_error(zf, need_msg, ce->name->val, "none", ""); return 0; } else if (ret_info->type_hint == IS_CALLABLE) { zend_verify_return_error(zf, "be callable", "", "none", ""); diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 75d61ded53..8430fc8499 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -50,7 +50,6 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, char *string_name, int handle_exceptions); ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce); -ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce); ZEND_API void zend_verify_arg_error(const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg); ZEND_API void zend_verify_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind); ZEND_API void zend_verify_internal_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index abb91b1ee3..1c760c5902 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -410,10 +410,6 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) } if (arg_info[i].class_name) { zend_string_release(arg_info[i].class_name); - - if (arg_info[i].lower_class_name) { - zend_string_release(arg_info[i].lower_class_name); - } } } efree(arg_info); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 0fe820a20f..686eb2a293 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3919,13 +3919,11 @@ ZEND_VM_C_LABEL(fcall_end): ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED) { -#if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED) USE_OPLINE -#endif SAVE_OPLINE(); if (OP1_TYPE == IS_UNUSED) { - zend_verify_missing_return_type(EX(func)); + zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); } else { /* prevents "undefined variable opline" errors */ #if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED) @@ -3959,7 +3957,7 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED) SEPARATE_ZVAL_NOREF(retval_ptr); } } - zend_verify_return_type(EX(func), retval_ptr); + zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); if (UNEXPECTED(EG(exception) != NULL)) { FREE_OP1(); @@ -4752,14 +4750,14 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY) if (UNEXPECTED(arg_num > EX_NUM_ARGS())) { SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_missing_arg(execute_data, arg_num))) { + if (UNEXPECTED(!zend_verify_missing_arg(execute_data, arg_num, CACHE_ADDR(opline->op2.num)))) { HANDLE_EXCEPTION(); } } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var); SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, NULL))) { + if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) { HANDLE_EXCEPTION(); } } @@ -4794,8 +4792,10 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST) } if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { + zval *default_value = EX_CONSTANT(opline->op2); + SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2)))) { + if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(Z_CACHE_SLOT_P(default_value))))) { HANDLE_EXCEPTION(); } } @@ -4824,7 +4824,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY) param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { do { - zend_verify_arg_type(EX(func), arg_num, param, NULL); + zend_verify_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)); if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); ZEND_HASH_FILL_ADD(param); param++; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c7fef27bd4..9d7fac449b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1202,14 +1202,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_ if (UNEXPECTED(arg_num > EX_NUM_ARGS())) { SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_missing_arg(execute_data, arg_num))) { + if (UNEXPECTED(!zend_verify_missing_arg(execute_data, arg_num, CACHE_ADDR(opline->op2.num)))) { HANDLE_EXCEPTION(); } } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var); SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, NULL))) { + if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) { HANDLE_EXCEPTION(); } } @@ -1237,7 +1237,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEN param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { do { - zend_verify_arg_type(EX(func), arg_num, param, NULL); + zend_verify_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)); if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); ZEND_HASH_FILL_ADD(param); param++; @@ -2354,8 +2354,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(Z } if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { + zval *default_value = EX_CONSTANT(opline->op2); + SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2)))) { + if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(Z_CACHE_SLOT_P(default_value))))) { HANDLE_EXCEPTION(); } } @@ -7973,13 +7975,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 || (IS_CONST != IS_UNUSED) USE_OPLINE -#endif SAVE_OPLINE(); if (IS_CONST == IS_UNUSED) { - zend_verify_missing_return_type(EX(func)); + zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_CONST != IS_UNUSED) @@ -8013,7 +8013,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_ SEPARATE_ZVAL_NOREF(retval_ptr); } } - zend_verify_return_type(EX(func), retval_ptr); + zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); if (UNEXPECTED(EG(exception) != NULL)) { @@ -13854,13 +13854,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 || (IS_TMP_VAR != IS_UNUSED) USE_OPLINE -#endif SAVE_OPLINE(); if (IS_TMP_VAR == IS_UNUSED) { - zend_verify_missing_return_type(EX(func)); + zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_TMP_VAR != IS_UNUSED) @@ -13894,7 +13892,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN SEPARATE_ZVAL_NOREF(retval_ptr); } } - zend_verify_return_type(EX(func), retval_ptr); + zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op1); @@ -19605,13 +19603,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 || (IS_VAR != IS_UNUSED) USE_OPLINE -#endif SAVE_OPLINE(); if (IS_VAR == IS_UNUSED) { - zend_verify_missing_return_type(EX(func)); + zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_VAR != IS_UNUSED) @@ -19645,7 +19641,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN SEPARATE_ZVAL_NOREF(retval_ptr); } } - zend_verify_return_type(EX(func), retval_ptr); + zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op1); @@ -25379,13 +25375,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_UNUS static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 || (IS_UNUSED != IS_UNUSED) USE_OPLINE -#endif SAVE_OPLINE(); if (IS_UNUSED == IS_UNUSED) { - zend_verify_missing_return_type(EX(func)); + zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_UNUSED != IS_UNUSED) @@ -25419,7 +25413,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED SEPARATE_ZVAL_NOREF(retval_ptr); } } - zend_verify_return_type(EX(func), retval_ptr); + zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); if (UNEXPECTED(EG(exception) != NULL)) { @@ -35013,13 +35007,11 @@ assign_dim_clean: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 || (IS_CV != IS_UNUSED) USE_OPLINE -#endif SAVE_OPLINE(); if (IS_CV == IS_UNUSED) { - zend_verify_missing_return_type(EX(func)); + zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_CV != IS_UNUSED) @@ -35053,7 +35045,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU SEPARATE_ZVAL_NOREF(retval_ptr); } } - zend_verify_return_type(EX(func), retval_ptr); + zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); if (UNEXPECTED(EG(exception) != NULL)) { diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c index c72e8f6772..c20ddbd183 100644 --- a/ext/opcache/Optimizer/compact_literals.c +++ b/ext/opcache/Optimizer/compact_literals.c @@ -128,6 +128,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx void *checkpoint = zend_arena_checkpoint(ctx->arena); if (op_array->last_literal) { + cache_size = 0; info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info)); /* Mark literals of specific types */ @@ -286,6 +287,19 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx case ZEND_BIND_GLOBAL: LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 0, 1, 1); break; + case ZEND_RECV_INIT: + LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 0, 0, 1); + if (Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) != -1) { + Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = cache_size; + cache_size += sizeof(void *); + } + break; + case ZEND_RECV: + case ZEND_VERIFY_RETURN_TYPE: + if (opline->op2.num != -1) { + opline->op2.num = cache_size; + cache_size += sizeof(void *); + } default: if (ZEND_OP1_TYPE(opline) == IS_CONST) { LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1); @@ -319,7 +333,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx #endif /* Merge equal constants */ - j = 0; cache_size = 0; + j = 0; zend_hash_init(&hash, op_array->last_literal, NULL, NULL, 0); map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int)); memset(map, 0, op_array->last_literal * sizeof(int)); @@ -331,15 +345,24 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx } switch (Z_TYPE(op_array->literals[i])) { case IS_NULL: - if (l_null < 0) { - l_null = j; + if ((info[i].flags & LITERAL_MAY_MERGE)) { + if (l_null < 0) { + l_null = j; + if (i != j) { + op_array->literals[j] = op_array->literals[i]; + info[j] = info[i]; + } + j++; + } + map[i] = l_null; + } else { + map[i] = j; if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } j++; } - map[i] = l_null; break; case IS_FALSE: if (l_false < 0) { diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 10a149c9f6..219bb50820 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -438,9 +438,6 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra if (!IS_SERIALIZED(p->class_name)) { SERIALIZE_STR(p->class_name); } - if (p->class_name && !IS_SERIALIZED(p->lower_class_name)) { - SERIALIZE_STR(p->lower_class_name); - } p++; } } @@ -965,9 +962,6 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr if (!IS_UNSERIALIZED(p->class_name)) { UNSERIALIZE_STR(p->class_name); } - if (p->class_name && !IS_UNSERIALIZED(p->lower_class_name)) { - UNSERIALIZE_STR(p->lower_class_name); - } p++; } } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 585c34f46e..09eebe0d02 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -581,9 +581,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc } if (arg_info[i].class_name) { zend_accel_store_interned_string(arg_info[i].class_name); - if (arg_info[i].lower_class_name) { - zend_accel_store_interned_string(arg_info[i].lower_class_name); - } } } } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index d721db2feb..98412109a5 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -225,9 +225,6 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array) } if (arg_info[i].class_name) { ADD_INTERNED_STRING(arg_info[i].class_name, 1); - if (arg_info[i].lower_class_name) { - ADD_INTERNED_STRING(arg_info[i].lower_class_name, 1); - } } } } |