}
/* }}} */
-
static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) /* {{{ */
{
if (return_info->type_hint != IS_UNDEF) {
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;
}
/* }}} */
-
static void zend_compile_typename(zend_ast *ast, zend_arg_info *arg_info) /* {{{ */
{
if (ast->kind == ZEND_AST_TYPE) {
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;
}
/* }}} */
-
void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
{
zend_ast_list *list = zend_ast_get_list(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;
+ }
+ }
}
}
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 */
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,
}
}
-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)
}
}
-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;
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)) {
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;
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;
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 {
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";
}
#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), "");
}
}
-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;
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", "");
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);
}
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);
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)
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();
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();
}
}
}
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();
}
}
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++;
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();
}
}
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++;
}
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();
}
}
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)
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)) {
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)
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);
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)
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);
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)
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)) {
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)
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)) {
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 */
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);
#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));
}
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) {
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++;
}
}
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++;
}
}
}
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);
- }
}
}
}
}
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);
- }
}
}
}