diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-09-20 17:01:19 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-11-08 15:15:48 +0100 |
commit | ac4e0f0852ce780e143013ceff45067a172e8a83 (patch) | |
tree | f39eebeb379b6f75e95a333ccec37c4af264d8ee /Zend/zend_execute.c | |
parent | a555cc0b3d4f745e6d0bb8c595de400a0c728827 (diff) | |
download | php-git-ac4e0f0852ce780e143013ceff45067a172e8a83.tar.gz |
Make zend_type a 2-field struct
We now store the pointer payload and the type mask separately. This
is in preparation for union types, where we will be using both at
the same time.
To avoid increasing the size of arginfo structures, the
pass_by_reference and is_variadic fields are now stored as part of
the type_mask (8-bit are reserved for custom use).
Different types of pointer payloads are distinguished based on bits
in the type_mask.
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r-- | Zend/zend_execute.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 8278f698cd..097137aa5c 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -676,8 +676,8 @@ static ZEND_COLD void zend_verify_type_error_common( *need_kind = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type)); } } else { - zend_type type = ZEND_TYPE_WITHOUT_NULL(arg_info->type); - switch (ZEND_TYPE_MASK(type)) { + uint32_t type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(arg_info->type); + switch (type_mask) { case MAY_BE_OBJECT: *need_msg = "be an "; *need_kind = "object"; @@ -691,11 +691,15 @@ static ZEND_COLD void zend_verify_type_error_common( *need_kind = ""; break; default: + { /* TODO: The zend_type_to_string() result is guaranteed interned here. * It would be beter to switch all this code to use zend_string though. */ + zend_type type = arg_info->type; + ZEND_TYPE_FULL_MASK(type) &= ~MAY_BE_NULL; *need_msg = "be of the type "; *need_kind = ZSTR_VAL(zend_type_to_string(type)); break; + } } } @@ -904,7 +908,7 @@ static zend_bool zend_resolve_class_type(zend_type *type, zend_class_entry *self } zend_string_release(name); - *type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(*type)); + *type = (zend_type) ZEND_TYPE_INIT_CE(ce, ZEND_TYPE_ALLOW_NULL(*type), 0); return 1; } @@ -924,13 +928,13 @@ static zend_always_inline zend_bool i_zend_check_property_type(zend_property_inf return instanceof_function(Z_OBJCE_P(property), ZEND_TYPE_CE(info->type)); } - ZEND_ASSERT(!(ZEND_TYPE_MASK(info->type) & MAY_BE_CALLABLE)); + ZEND_ASSERT(!(ZEND_TYPE_FULL_MASK(info->type) & MAY_BE_CALLABLE)); if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(info->type, Z_TYPE_P(property)))) { return 1; - } else if (ZEND_TYPE_MASK(info->type) & MAY_BE_ITERABLE) { + } else if (ZEND_TYPE_FULL_MASK(info->type) & MAY_BE_ITERABLE) { return zend_is_iterable(property); } else { - return zend_verify_scalar_type_hint(ZEND_TYPE_MASK(info->type), property, strict, 0); + return zend_verify_scalar_type_hint(ZEND_TYPE_FULL_MASK(info->type), property, strict, 0); } } @@ -996,7 +1000,7 @@ static zend_always_inline zend_bool zend_check_type( return 1; } - type_mask = ZEND_TYPE_MASK(type); + type_mask = ZEND_TYPE_FULL_MASK(type); if (type_mask & MAY_BE_CALLABLE) { return zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL); } else if (type_mask & MAY_BE_ITERABLE) { @@ -1184,7 +1188,7 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret) zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1; void *dummy_cache_slot = NULL; - if (ZEND_TYPE_IS_MASK(ret_info->type) && (ZEND_TYPE_MASK(ret_info->type) & MAY_BE_VOID)) { + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_VOID) { if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) { zend_verify_void_return_error(zf, zend_zval_type_name(ret), ""); return 0; @@ -1216,6 +1220,7 @@ static ZEND_COLD int zend_verify_missing_return_type(const zend_function *zf, vo zend_arg_info *ret_info = zf->common.arg_info - 1; // TODO: Eliminate this! + zend_class_entry *ce = NULL; if (ZEND_TYPE_IS_CLASS(ret_info->type)) { if (UNEXPECTED(!*cache_slot)) { zend_class_entry *ce = zend_fetch_class(ZEND_TYPE_NAME(ret_info->type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); @@ -1560,7 +1565,7 @@ static zend_property_info *zend_get_prop_not_accepting_double(zend_reference *re { zend_property_info *prop; ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) { - if (!ZEND_TYPE_IS_MASK(prop->type) || !(ZEND_TYPE_MASK(prop->type) & MAY_BE_DOUBLE)) { + if (!(ZEND_TYPE_FULL_MASK(prop->type) & MAY_BE_DOUBLE)) { return prop; } } ZEND_REF_FOREACH_TYPE_SOURCES_END(); @@ -2528,7 +2533,7 @@ static zend_always_inline zend_bool check_type_array_assignable(zend_type type) if (!ZEND_TYPE_IS_SET(type)) { return 1; } - return ZEND_TYPE_IS_MASK(type) && (ZEND_TYPE_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)); + return (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0; } /* Checks whether an array can be assigned to the reference. Throws error if not assignable. */ @@ -2959,7 +2964,7 @@ static zend_always_inline int i_zend_verify_type_assignable_zval( return 1; } - type_mask = ZEND_TYPE_MASK(type); + type_mask = ZEND_TYPE_FULL_MASK(type); if (type_mask & MAY_BE_ITERABLE) { return zend_is_iterable(zv); } @@ -3013,9 +3018,9 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference if (!seen_prop) { seen_prop = prop; seen_type_mask = ZEND_TYPE_IS_CLASS(prop->type) - ? MAY_BE_OBJECT : ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop->type)); + ? MAY_BE_OBJECT : ZEND_TYPE_PURE_MASK_WITHOUT_NULL(prop->type); } else if (needs_coercion - && seen_type_mask != ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop->type))) { + && seen_type_mask != ZEND_TYPE_PURE_MASK_WITHOUT_NULL(prop->type)) { zend_throw_conflicting_coercion_error(seen_prop, prop, zv); return 0; } @@ -3082,13 +3087,13 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_propert if (result < 0) { zend_property_info *ref_prop = ZEND_REF_FIRST_SOURCE(Z_REF_P(orig_val)); - if (ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop_info->type)) - != ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(ref_prop->type))) { + if (ZEND_TYPE_PURE_MASK_WITHOUT_NULL(prop_info->type) + != ZEND_TYPE_PURE_MASK_WITHOUT_NULL(ref_prop->type)) { /* Invalid due to conflicting coercion */ zend_throw_ref_type_error_type(ref_prop, prop_info, val); return 0; } - if (zend_verify_weak_scalar_type_hint(ZEND_TYPE_MASK(prop_info->type), val)) { + if (zend_verify_weak_scalar_type_hint(ZEND_TYPE_FULL_MASK(prop_info->type), val)) { return 1; } } |