diff options
Diffstat (limited to 'Zend/zend_execute.c')
| -rw-r--r-- | Zend/zend_execute.c | 182 |
1 files changed, 99 insertions, 83 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index bc964c1ad1..753eef4267 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -716,12 +716,12 @@ ZEND_API ZEND_COLD void zend_verify_arg_error( zend_string_release(need_msg); } -static zend_bool zend_verify_weak_scalar_type_hint(uint32_t type_mask, zval *arg) +static bool zend_verify_weak_scalar_type_hint(uint32_t type_mask, zval *arg) { zend_long lval; double dval; zend_string *str; - zend_bool bval; + bool bval; /* Type preference order: int -> float -> string -> bool */ if (type_mask & MAY_BE_LONG) { @@ -775,11 +775,11 @@ static bool can_convert_to_string(zval *zv) { } /* Used to sanity-check internal arginfo types without performing any actual type conversions. */ -static zend_bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_mask, zval *arg) +static bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_mask, zval *arg) { zend_long lval; double dval; - zend_bool bval; + bool bval; if ((type_mask & MAY_BE_LONG) && zend_parse_arg_long_weak(arg, &lval)) { return 1; @@ -797,7 +797,7 @@ static zend_bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_m } #endif -ZEND_API zend_bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, zend_bool strict, zend_bool is_internal_arg) +ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg) { if (UNEXPECTED(strict)) { /* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */ @@ -851,20 +851,32 @@ static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class } } -static zend_bool zend_check_and_resolve_property_class_type( +static bool zend_check_and_resolve_property_class_type( zend_property_info *info, zend_class_entry *object_ce) { zend_class_entry *ce; if (ZEND_TYPE_HAS_LIST(info->type)) { zend_type *list_type; ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) { if (ZEND_TYPE_HAS_NAME(*list_type)) { - zend_string *name = ZEND_TYPE_NAME(*list_type); - ce = resolve_single_class_type(name, info->ce); - if (!ce) { - continue; + if (ZEND_TYPE_HAS_CE_CACHE(*list_type)) { + ce = ZEND_TYPE_CE_CACHE(*list_type); + if (!ce) { + zend_string *name = ZEND_TYPE_NAME(*list_type); + ce = resolve_single_class_type(name, info->ce); + if (UNEXPECTED(!ce)) { + continue; + } + ZEND_TYPE_SET_CE_CACHE(*list_type, ce); + } + } else { + zend_string *name = ZEND_TYPE_NAME(*list_type); + ce = resolve_single_class_type(name, info->ce); + if (!ce) { + continue; + } + zend_string_release(name); + ZEND_TYPE_SET_CE(*list_type, ce); } - zend_string_release(name); - ZEND_TYPE_SET_CE(*list_type, ce); } else { ce = ZEND_TYPE_CE(*list_type); } @@ -875,14 +887,26 @@ static zend_bool zend_check_and_resolve_property_class_type( return 0; } else { if (UNEXPECTED(ZEND_TYPE_HAS_NAME(info->type))) { - zend_string *name = ZEND_TYPE_NAME(info->type); - ce = resolve_single_class_type(name, info->ce); - if (UNEXPECTED(!ce)) { - return 0; - } + if (ZEND_TYPE_HAS_CE_CACHE(info->type)) { + ce = ZEND_TYPE_CE_CACHE(info->type); + if (!ce) { + zend_string *name = ZEND_TYPE_NAME(info->type); + ce = resolve_single_class_type(name, info->ce); + if (UNEXPECTED(!ce)) { + return 0; + } + ZEND_TYPE_SET_CE_CACHE(info->type, ce); + } + } else { + zend_string *name = ZEND_TYPE_NAME(info->type); + ce = resolve_single_class_type(name, info->ce); + if (UNEXPECTED(!ce)) { + return 0; + } - zend_string_release(name); - ZEND_TYPE_SET_CE(info->type, ce); + zend_string_release(name); + ZEND_TYPE_SET_CE(info->type, ce); + } } else { ce = ZEND_TYPE_CE(info->type); } @@ -890,7 +914,7 @@ static zend_bool zend_check_and_resolve_property_class_type( } } -static zend_always_inline zend_bool i_zend_check_property_type(zend_property_info *info, zval *property, zend_bool strict) +static zend_always_inline bool i_zend_check_property_type(zend_property_info *info, zval *property, bool strict) { ZEND_ASSERT(!Z_ISREF_P(property)); if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(info->type, Z_TYPE_P(property)))) { @@ -910,7 +934,7 @@ static zend_always_inline zend_bool i_zend_check_property_type(zend_property_inf return zend_verify_scalar_type_hint(type_mask, property, strict, 0); } -static zend_always_inline zend_bool i_zend_verify_property_type(zend_property_info *info, zval *property, zend_bool strict) +static zend_always_inline bool i_zend_verify_property_type(zend_property_info *info, zval *property, bool strict) { if (i_zend_check_property_type(info, property, strict)) { return 1; @@ -920,7 +944,7 @@ static zend_always_inline zend_bool i_zend_verify_property_type(zend_property_in return 0; } -ZEND_API zend_bool zend_never_inline zend_verify_property_type(zend_property_info *info, zval *property, zend_bool strict) { +ZEND_API bool zend_never_inline zend_verify_property_type(zend_property_info *info, zval *property, bool strict) { return i_zend_verify_property_type(info, property, strict); } @@ -939,7 +963,7 @@ static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *inf return zend_assign_to_variable(property_val, &tmp, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } -ZEND_API zend_bool zend_value_instanceof_static(zval *zv) { +ZEND_API bool zend_value_instanceof_static(zval *zv) { if (Z_TYPE_P(zv) != IS_OBJECT) { return 0; } @@ -959,18 +983,23 @@ ZEND_API zend_bool zend_value_instanceof_static(zval *zv) { # define HAVE_CACHE_SLOT 1 #endif -static zend_always_inline zend_bool zend_check_type_slow( - zend_type type, zval *arg, zend_reference *ref, void **cache_slot, zend_class_entry *scope, - zend_bool is_return_type, zend_bool is_internal) +static zend_always_inline bool zend_check_type_slow( + zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, zend_class_entry *scope, + bool is_return_type, bool is_internal) { uint32_t type_mask; - if (ZEND_TYPE_HAS_CLASS(type) && Z_TYPE_P(arg) == IS_OBJECT) { + if (ZEND_TYPE_HAS_CLASS(*type) && Z_TYPE_P(arg) == IS_OBJECT) { zend_class_entry *ce; - if (ZEND_TYPE_HAS_LIST(type)) { + if (ZEND_TYPE_HAS_LIST(*type)) { zend_type *list_type; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) { if (HAVE_CACHE_SLOT && *cache_slot) { ce = *cache_slot; + } else if (ZEND_TYPE_HAS_CE_CACHE(*list_type) && ZEND_TYPE_CE_CACHE(*list_type)) { + ce = ZEND_TYPE_CE_CACHE(*list_type); + if (HAVE_CACHE_SLOT) { + *cache_slot = ce; + } } else { ce = zend_fetch_class(ZEND_TYPE_NAME(*list_type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); @@ -983,6 +1012,9 @@ static zend_always_inline zend_bool zend_check_type_slow( if (HAVE_CACHE_SLOT) { *cache_slot = ce; } + if (ZEND_TYPE_HAS_CE_CACHE(*list_type)) { + ZEND_TYPE_SET_CE_CACHE(*list_type, ce); + } } if (instanceof_function(Z_OBJCE_P(arg), ce)) { return 1; @@ -994,14 +1026,22 @@ static zend_always_inline zend_bool zend_check_type_slow( } else { if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) { ce = (zend_class_entry *) *cache_slot; + } else if (ZEND_TYPE_HAS_CE_CACHE(*type) && ZEND_TYPE_CE_CACHE(*type)) { + ce = ZEND_TYPE_CE_CACHE(*type); + if (HAVE_CACHE_SLOT) { + *cache_slot = ce; + } } else { - ce = zend_fetch_class(ZEND_TYPE_NAME(type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); + ce = zend_fetch_class(ZEND_TYPE_NAME(*type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); if (UNEXPECTED(!ce)) { goto builtin_types; } if (HAVE_CACHE_SLOT) { *cache_slot = (void *) ce; } + if (ZEND_TYPE_HAS_CE_CACHE(*type)) { + ZEND_TYPE_SET_CE_CACHE(*type, ce); + } } if (instanceof_function(Z_OBJCE_P(arg), ce)) { return 1; @@ -1010,7 +1050,7 @@ static zend_always_inline zend_bool zend_check_type_slow( } builtin_types: - type_mask = ZEND_TYPE_FULL_MASK(type); + type_mask = ZEND_TYPE_FULL_MASK(*type); if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, 0, NULL)) { return 1; } @@ -1039,19 +1079,19 @@ builtin_types: * because this case is already checked at compile-time. */ } -static zend_always_inline zend_bool zend_check_type( - zend_type type, zval *arg, void **cache_slot, zend_class_entry *scope, - zend_bool is_return_type, zend_bool is_internal) +static zend_always_inline bool zend_check_type( + zend_type *type, zval *arg, void **cache_slot, zend_class_entry *scope, + bool is_return_type, bool is_internal) { zend_reference *ref = NULL; - ZEND_ASSERT(ZEND_TYPE_IS_SET(type)); + ZEND_ASSERT(ZEND_TYPE_IS_SET(*type)); if (UNEXPECTED(Z_ISREF_P(arg))) { ref = Z_REF_P(arg); arg = Z_REFVAL_P(arg); } - if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(arg)))) { + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(*type, Z_TYPE_P(arg)))) { return 1; } @@ -1066,7 +1106,7 @@ static zend_always_inline bool zend_verify_recv_arg_type(zend_function *zf, uint cur_arg_info = &zf->common.arg_info[arg_num-1]; if (ZEND_TYPE_IS_SET(cur_arg_info->type) - && UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { + && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { zend_verify_arg_error(zf, cur_arg_info, arg_num, arg); return 0; } @@ -1078,7 +1118,7 @@ static zend_always_inline bool zend_verify_variadic_arg_type( zend_function *zf, zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void **cache_slot) { ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type)); - if (UNEXPECTED(!zend_check_type(arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { + if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { zend_verify_arg_error(zf, arg_info, arg_num, arg); return 0; } @@ -1103,7 +1143,7 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ } if (ZEND_TYPE_IS_SET(cur_arg_info->type) - && UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, /* cache_slot */ NULL, fbc->common.scope, 0, /* is_internal */ 1))) { + && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, /* cache_slot */ NULL, fbc->common.scope, 0, /* is_internal */ 1))) { return 0; } arg++; @@ -1115,7 +1155,7 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ /* Determine whether an internal call should throw, because the passed arguments violate * an arginfo constraint. This is only checked in debug builds. In release builds, we * trust that arginfo matches what is enforced by zend_parse_parameters. */ -static zend_always_inline zend_bool zend_internal_call_should_throw(zend_function *fbc, zend_execute_data *call) +static zend_always_inline bool zend_internal_call_should_throw(zend_function *fbc, zend_execute_data *call) { if (fbc->internal_function.handler == ZEND_FN(pass)) { /* Be lenient about the special pass function. */ @@ -1236,7 +1276,7 @@ static bool zend_verify_internal_return_type(zend_function *zf, zval *ret) return 1; } - if (UNEXPECTED(!zend_check_type(ret_info->type, ret, /* cache_slot */ NULL, NULL, 1, /* is_internal */ 1))) { + if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, /* cache_slot */ NULL, NULL, 1, /* is_internal */ 1))) { zend_verify_internal_return_error(zf, ret); return 0; } @@ -2100,31 +2140,7 @@ num_undef: } str_index: retval = zend_hash_find_ex(ht, offset_key, ZEND_CONST_COND(dim_type == IS_CONST, 0)); - if (retval) { - /* support for $GLOBALS[...] */ - if (UNEXPECTED(Z_TYPE_P(retval) == IS_INDIRECT)) { - retval = Z_INDIRECT_P(retval); - if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) { - switch (type) { - case BP_VAR_R: - zend_undefined_index(offset_key); - /* break missing intentionally */ - case BP_VAR_UNSET: - case BP_VAR_IS: - retval = &EG(uninitialized_zval); - break; - case BP_VAR_RW: - if (UNEXPECTED(zend_undefined_index_write(ht, offset_key))) { - return NULL; - } - /* break missing intentionally */ - case BP_VAR_W: - ZVAL_NULL(retval); - break; - } - } - } - } else { + if (!retval) { switch (type) { case BP_VAR_R: zend_undefined_index(offset_key); @@ -2478,7 +2494,7 @@ num_idx: return zend_hash_index_find(ht, hval); } else if (Z_TYPE_P(offset) == IS_NULL) { str_idx: - return zend_hash_find_ex_ind(ht, ZSTR_EMPTY_ALLOC(), 1); + return zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; goto num_idx; @@ -2576,7 +2592,7 @@ str_offset: } } -static zend_never_inline zend_bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable *ht, zval *key OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable *ht, zval *key OPLINE_DC EXECUTE_DATA_DC) { zend_string *str; zend_ulong hval; @@ -2588,11 +2604,11 @@ try_again: goto num_key; } str_key: - return zend_hash_find_ind(ht, str) != NULL; + return zend_hash_exists(ht, str); } else if (EXPECTED(Z_TYPE_P(key) == IS_LONG)) { hval = Z_LVAL_P(key); num_key: - return zend_hash_index_find(ht, hval) != NULL; + return zend_hash_index_exists(ht, hval); } else if (EXPECTED(Z_ISREF_P(key))) { key = Z_REFVAL_P(key); goto try_again; @@ -2636,12 +2652,12 @@ static ZEND_COLD void ZEND_FASTCALL zend_array_key_exists_error( } } -static zend_always_inline zend_bool promotes_to_array(zval *val) { +static zend_always_inline bool promotes_to_array(zval *val) { return Z_TYPE_P(val) <= IS_FALSE || (Z_ISREF_P(val) && Z_TYPE_P(Z_REFVAL_P(val)) <= IS_FALSE); } -static zend_always_inline zend_bool check_type_array_assignable(zend_type type) { +static zend_always_inline bool check_type_array_assignable(zend_type type) { if (!ZEND_TYPE_IS_SET(type)) { return 1; } @@ -2649,7 +2665,7 @@ static zend_always_inline zend_bool check_type_array_assignable(zend_type type) } /* Checks whether an array can be assigned to the reference. Throws error if not assignable. */ -ZEND_API zend_bool zend_verify_ref_array_assignable(zend_reference *ref) { +ZEND_API bool zend_verify_ref_array_assignable(zend_reference *ref) { zend_property_info *prop; ZEND_ASSERT(ZEND_REF_HAS_TYPE_SOURCES(ref)); ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) { @@ -2677,7 +2693,7 @@ static zend_property_info *zend_object_fetch_property_type_info( return zend_get_typed_property_info_for_slot(obj, slot); } -static zend_never_inline zend_bool zend_handle_fetch_obj_flags( +static zend_never_inline bool zend_handle_fetch_obj_flags( zval *result, zval *ptr, zend_object *obj, zend_property_info *prop_info, uint32_t flags) { switch (flags) { @@ -2722,7 +2738,7 @@ static zend_never_inline zend_bool zend_handle_fetch_obj_flags( return 1; } -static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type, uint32_t flags, zend_bool init_undef OPLINE_DC EXECUTE_DATA_DC) +static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type, uint32_t flags, bool init_undef OPLINE_DC EXECUTE_DATA_DC) { zval *ptr; zend_object *zobj; @@ -3063,7 +3079,7 @@ ZEND_API ZEND_COLD void zend_throw_conflicting_coercion_error(zend_property_info /* 1: valid, 0: invalid, -1: may be valid after type coercion */ static zend_always_inline int i_zend_verify_type_assignable_zval( - zend_property_info *info, zval *zv, zend_bool strict) { + zend_property_info *info, zval *zv, bool strict) { zend_type type = info->type; uint32_t type_mask; zend_uchar zv_type = Z_TYPE_P(zv); @@ -3106,7 +3122,7 @@ static zend_always_inline int i_zend_verify_type_assignable_zval( return -1; } -ZEND_API zend_bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference *ref, zval *zv, zend_bool strict) +ZEND_API bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference *ref, zval *zv, bool strict) { zend_property_info *prop; @@ -3185,9 +3201,9 @@ static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) { } } -ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, zend_bool strict) +ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict) { - zend_bool ret; + bool ret; zval value; zend_refcounted *ref = NULL; @@ -3218,7 +3234,7 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ze return variable_ptr; } -ZEND_API zend_bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, zend_bool strict) { +ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict) { zval *val = orig_val; if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) { int result; @@ -3525,7 +3541,7 @@ static zend_always_inline void zend_init_cvs(uint32_t first, uint32_t last EXECU } } -static zend_always_inline void i_init_func_execute_data(zend_op_array *op_array, zval *return_value, zend_bool may_be_trampoline EXECUTE_DATA_DC) /* {{{ */ +static zend_always_inline void i_init_func_execute_data(zend_op_array *op_array, zval *return_value, bool may_be_trampoline EXECUTE_DATA_DC) /* {{{ */ { uint32_t first_extra_arg, num_args; ZEND_ASSERT(EX(func) == (zend_function*)op_array); @@ -4262,11 +4278,11 @@ already_compiled: } /* }}} */ -static zend_never_inline zend_bool ZEND_FASTCALL zend_fe_reset_iterator(zval *array_ptr, int by_ref OPLINE_DC EXECUTE_DATA_DC) /* {{{ */ +static zend_never_inline bool ZEND_FASTCALL zend_fe_reset_iterator(zval *array_ptr, int by_ref OPLINE_DC EXECUTE_DATA_DC) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(array_ptr); zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, by_ref); - zend_bool is_empty; + bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { if (iter) { |
