diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-09-19 12:11:29 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-09-23 15:31:35 +0200 |
commit | 9e8ba7891e74a80265e09ff5b810ec947680c1ce (patch) | |
tree | 6550898580da2445d9d54370d2adef6e68a881b3 /ext | |
parent | 9ec2480bd6d8cadd8ca2ecac07f00fd3d411bc7a (diff) | |
download | php-git-9e8ba7891e74a80265e09ff5b810ec947680c1ce.tar.gz |
Change representation of zend_type from type code to MAY_BE_* mask
This switches zend_type from storing a single IS_* type code to
storing a MAY_BE_* type mask. Right now most code still assumes
that there is only a single type in the mask (or two together
with MAY_BE_NULL). But this will make it a lot simpler to introduce
union types.
An additional advantage (and why I'm doing this separately), is
that a number of special cases no longer need to be handled
separately: We can do a single mask & (1 << type) check to handle
all simple types, booleans (true|false) and null.
Diffstat (limited to 'ext')
-rw-r--r-- | ext/com_dotnet/com_handlers.c | 2 | ||||
-rw-r--r-- | ext/opcache/Optimizer/dfa_pass.c | 5 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_inference.c | 65 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_inference.h | 6 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 4 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_helpers.c | 190 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_x86.dasc | 62 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 54 | ||||
-rw-r--r-- | ext/standard/var.c | 21 | ||||
-rw-r--r-- | ext/zend_test/test.c | 4 |
10 files changed, 115 insertions, 298 deletions
diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index 3893017553..fd4cb4ab3b 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -319,7 +319,7 @@ static zend_function *com_method_get(zend_object **object_ptr, zend_string *name f.arg_info = ecalloc(bindptr.lpfuncdesc->cParams, sizeof(zend_arg_info)); for (i = 0; i < bindptr.lpfuncdesc->cParams; i++) { - f.arg_info[i].type = ZEND_TYPE_ENCODE(0,1); + f.arg_info[i].type = ZEND_TYPE_ENCODE_CODE(0,1); if (bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) { f.arg_info[i].pass_by_reference = ZEND_SEND_BY_REF; } diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index 5401c9df6a..5ea7775921 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -312,6 +312,8 @@ static inline zend_bool can_elide_return_type_check( zend_ssa_var_info *use_info = &ssa->var_info[ssa_op->op1_use]; zend_ssa_var_info *def_info = &ssa->var_info[ssa_op->op1_def]; + /* TODO: It would be better to rewrite this without using def_info, + * which may not be an exact representation of the type. */ if (use_info->type & MAY_BE_REF) { return 0; } @@ -322,7 +324,8 @@ static inline zend_bool can_elide_return_type_check( } /* These types are not represented exactly */ - if (ZEND_TYPE_CODE(info->type) == IS_CALLABLE || ZEND_TYPE_CODE(info->type) == IS_ITERABLE) { + if (ZEND_TYPE_IS_MASK(info->type) + && (ZEND_TYPE_MASK(info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE))) { return 0; } diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index e8a9918b39..2e30857013 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -1419,18 +1419,22 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int return 1; } else if (op_array->arg_info && opline->op1.num <= op_array->num_args) { - if (ZEND_TYPE_CODE(op_array->arg_info[opline->op1.num-1].type) == IS_LONG) { - tmp->underflow = 0; - tmp->min = ZEND_LONG_MIN; - tmp->max = ZEND_LONG_MAX; - tmp->overflow = 0; - return 1; - } else if (ZEND_TYPE_CODE(op_array->arg_info[opline->op1.num-1].type) == _IS_BOOL) { - tmp->underflow = 0; - tmp->min = 0; - tmp->max = 1; - tmp->overflow = 0; - return 1; + zend_type type = op_array->arg_info[opline->op1.num-1].type; + if (ZEND_TYPE_IS_MASK(type)) { + uint32_t mask = ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(type)); + if (mask == MAY_BE_LONG) { + tmp->underflow = 0; + tmp->min = ZEND_LONG_MIN; + tmp->max = ZEND_LONG_MAX; + tmp->overflow = 0; + return 1; + } else if (mask == (MAY_BE_FALSE|MAY_BE_TRUE)) { + tmp->underflow = 0; + tmp->min = 0; + tmp->max = 1; + tmp->overflow = 0; + return 1; + } } } } @@ -2232,22 +2236,23 @@ static inline zend_class_entry *get_class_entry(const zend_script *script, zend_ return NULL; } -static uint32_t zend_convert_type_code_to_may_be(zend_uchar type_code) { - switch (type_code) { - case IS_VOID: - return MAY_BE_NULL; - case IS_CALLABLE: - return MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; - case IS_ITERABLE: - return MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; - case IS_ARRAY: - return MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; - case _IS_BOOL: - return MAY_BE_TRUE|MAY_BE_FALSE; - default: - ZEND_ASSERT(type_code < IS_REFERENCE); - return 1 << type_code; +static uint32_t zend_convert_type_declaration_mask(uint32_t type_mask) { + if (type_mask & MAY_BE_VOID) { + type_mask &= ~MAY_BE_VOID; + type_mask |= MAY_BE_NULL; + } + if (type_mask & MAY_BE_CALLABLE) { + type_mask &= ~MAY_BE_CALLABLE; + type_mask |= MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; + } + if (type_mask & MAY_BE_ITERABLE) { + type_mask &= ~MAY_BE_ITERABLE; + type_mask |= MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; + } + if (type_mask & MAY_BE_ARRAY) { + type_mask |= MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; } + return type_mask; } uint32_t zend_fetch_arg_info_type(const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce) @@ -2261,8 +2266,8 @@ uint32_t zend_fetch_arg_info_type(const zend_script *script, zend_arg_info *arg_ tmp |= MAY_BE_OBJECT; *pce = get_class_entry(script, lcname); zend_string_release_ex(lcname, 0); - } else if (ZEND_TYPE_IS_CODE(arg_info->type)) { - tmp |= zend_convert_type_code_to_may_be(ZEND_TYPE_CODE(arg_info->type)); + } else if (ZEND_TYPE_IS_MASK(arg_info->type)) { + tmp |= zend_convert_type_declaration_mask(ZEND_TYPE_MASK(arg_info->type)); } else { tmp |= MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; } @@ -2366,7 +2371,7 @@ static uint32_t zend_fetch_prop_type(const zend_script *script, zend_property_in if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) { uint32_t type = ZEND_TYPE_IS_CLASS(prop_info->type) ? MAY_BE_OBJECT - : zend_convert_type_code_to_may_be(ZEND_TYPE_CODE(prop_info->type)); + : zend_convert_type_declaration_mask(ZEND_TYPE_MASK(prop_info->type)); if (ZEND_TYPE_ALLOW_NULL(prop_info->type)) { type |= MAY_BE_NULL; diff --git a/ext/opcache/Optimizer/zend_inference.h b/ext/opcache/Optimizer/zend_inference.h index 03cbb5e82b..80a58405e7 100644 --- a/ext/opcache/Optimizer/zend_inference.h +++ b/ext/opcache/Optimizer/zend_inference.h @@ -26,11 +26,11 @@ /* Bitmask for type inference (zend_ssa_var_info.type) */ #include "zend_type_info.h" -#define MAY_BE_IN_REG (1<<25) /* value allocated in CPU register */ +#define MAY_BE_IN_REG (1<<29) /* value allocated in CPU register */ //TODO: remome MAY_BE_RC1, MAY_BE_RCN??? -#define MAY_BE_RC1 (1<<27) /* may be non-reference with refcount == 1 */ -#define MAY_BE_RCN (1<<28) /* may be non-reference with refcount > 1 */ +#define MAY_BE_RC1 (1<<30) /* may be non-reference with refcount == 1 */ +#define MAY_BE_RCN (1<<31) /* may be non-reference with refcount > 1 */ #define MAY_HAVE_DTOR \ (MAY_BE_OBJECT|MAY_BE_RESOURCE \ diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 952ea95ab2..7bac2d7538 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -657,8 +657,8 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array, case ZEND_VERIFY_RETURN_TYPE: { zend_arg_info *ret_info = op_array->arg_info - 1; if (ZEND_TYPE_IS_CLASS(ret_info->type) - || ZEND_TYPE_CODE(ret_info->type) == IS_CALLABLE - || !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(val)) + || (ZEND_TYPE_IS_MASK(ret_info->type) + && !ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(val))) || (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) { return 0; } diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 18af7234a7..54b888a132 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1115,169 +1115,6 @@ static zval* ZEND_FASTCALL zend_jit_fetch_global_helper(zend_execute_data *execu return value; } -static zend_bool zend_verify_weak_scalar_type_hint(zend_uchar type_hint, zval *arg) -{ - switch (type_hint) { - case _IS_BOOL: { - zend_bool dest; - - if (!zend_parse_arg_bool_weak(arg, &dest)) { - return 0; - } - zval_ptr_dtor(arg); - ZVAL_BOOL(arg, dest); - return 1; - } - case IS_LONG: { - zend_long dest; - - if (!zend_parse_arg_long_weak(arg, &dest)) { - return 0; - } - zval_ptr_dtor(arg); - ZVAL_LONG(arg, dest); - return 1; - } - case IS_DOUBLE: { - double dest; - - if (!zend_parse_arg_double_weak(arg, &dest)) { - return 0; - } - zval_ptr_dtor(arg); - ZVAL_DOUBLE(arg, dest); - return 1; - } - case IS_STRING: { - zend_string *dest; - - /* on success "arg" is converted to IS_STRING */ - if (!zend_parse_arg_str_weak(arg, &dest)) { - return 0; - } - return 1; - } - default: - return 0; - } -} - -static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict) -{ - if (UNEXPECTED(strict)) { - /* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */ - if (type_hint != IS_DOUBLE || Z_TYPE_P(arg) != IS_LONG) { - return 0; - } - } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) { - /* NULL may be accepted only by nullable hints (this is already checked) */ - return 0; - } - return zend_verify_weak_scalar_type_hint(type_hint, arg); -} - -static ZEND_COLD void zend_verify_type_error_common( - const zend_function *zf, const zend_arg_info *arg_info, - const zend_class_entry *ce, zval *value, - const char **fname, const char **fsep, const char **fclass, - const char **need_msg, const char **need_kind, const char **need_or_null, - const char **given_msg, const char **given_kind) -{ - zend_bool is_interface = 0; - *fname = ZSTR_VAL(zf->common.function_name); - - if (zf->common.scope) { - *fsep = "::"; - *fclass = ZSTR_VAL(zf->common.scope->name); - } else { - *fsep = ""; - *fclass = ""; - } - - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - if (ce) { - if (ce->ce_flags & ZEND_ACC_INTERFACE) { - *need_msg = "implement interface "; - is_interface = 1; - } else { - *need_msg = "be an instance of "; - } - *need_kind = ZSTR_VAL(ce->name); - } else { - /* We don't know whether it's a class or interface, assume it's a class */ - *need_msg = "be an instance of "; - *need_kind = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type)); - } - } else { - switch (ZEND_TYPE_CODE(arg_info->type)) { - case IS_CALLABLE: - *need_msg = "be callable"; - *need_kind = ""; - break; - case IS_ITERABLE: - *need_msg = "be iterable"; - *need_kind = ""; - break; - case IS_OBJECT: - *need_msg = "be an object"; - *need_kind = ""; - break; - default: - *need_msg = "be of the type "; - *need_kind = zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)); - break; - } - } - - if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) { - *need_or_null = is_interface ? " or be null" : " or null"; - } else { - *need_or_null = ""; - } - - if (value) { - if (ZEND_TYPE_IS_CLASS(arg_info->type) && Z_TYPE_P(value) == IS_OBJECT) { - *given_msg = "instance of "; - *given_kind = ZSTR_VAL(Z_OBJCE_P(value)->name); - } else { - *given_msg = zend_zval_type_name(value); - *given_kind = ""; - } - } else { - *given_msg = "none"; - *given_kind = ""; - } -} - -static ZEND_COLD void zend_verify_arg_error( - const zend_function *zf, const zend_arg_info *arg_info, - int arg_num, const zend_class_entry *ce, zval *value) -{ - zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data; - const char *fname, *fsep, *fclass; - const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind; - - if (value && !Z_ISUNDEF_P(value)) { - zend_verify_type_error_common( - zf, arg_info, ce, value, - &fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind); - - if (zf->common.type == ZEND_USER_FUNCTION) { - if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) { - zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given, called in %s on line %d", - arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind, - ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno); - } else { - zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind); - } - } else { - zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind); - } - } else { - zend_missing_arg_error(EG(current_execute_data)); - } -} - static void ZEND_FASTCALL zend_jit_verify_arg_object(zval *arg, zend_op_array *op_array, uint32_t arg_num, zend_arg_info *arg_info, void **cache_slot) { zend_class_entry *ce; @@ -1299,13 +1136,14 @@ static void ZEND_FASTCALL zend_jit_verify_arg_object(zval *arg, zend_op_array *o static void ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, zend_op_array *op_array, uint32_t arg_num, zend_arg_info *arg_info, void **cache_slot) { zend_class_entry *ce = NULL; - - if (Z_TYPE_P(arg) == IS_NULL && ZEND_TYPE_ALLOW_NULL(arg_info->type)) { - /* Null passed to nullable type */ - return; - } + uint32_t type_mask; if (UNEXPECTED(ZEND_TYPE_IS_CLASS(arg_info->type))) { + if (Z_TYPE_P(arg) == IS_NULL && ZEND_TYPE_ALLOW_NULL(arg_info->type)) { + /* Null passed to nullable type */ + return; + } + /* This is always an error - we fetch the class name for the error message here */ if (EXPECTED(*cache_slot)) { ce = (zend_class_entry *) *cache_slot; @@ -1316,20 +1154,20 @@ static void ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, zend_op_array *op_ } } goto err; - } else if (ZEND_TYPE_CODE(arg_info->type) == IS_CALLABLE) { + } + + type_mask = ZEND_TYPE_MASK(arg_info->type); + if (type_mask & MAY_BE_CALLABLE) { if (zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) == 0) { goto err; } - } else if (ZEND_TYPE_CODE(arg_info->type) == IS_ITERABLE) { + } else if (type_mask & MAY_BE_ITERABLE) { if (zend_is_iterable(arg) == 0) { goto err; } - } else if (ZEND_TYPE_CODE(arg_info->type) == _IS_BOOL && - EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) { - return; - } else if (ZEND_TYPE_CODE(arg_info->type) != Z_TYPE_P(arg)) { + } else { if (Z_ISUNDEF_P(arg) || - zend_verify_scalar_type_hint(ZEND_TYPE_CODE(arg_info->type), arg, ZEND_ARG_USES_STRICT_TYPES()) == 0) { + zend_verify_scalar_type_hint(ZEND_TYPE_MASK(arg_info->type), arg, ZEND_ARG_USES_STRICT_TYPES(), /* is_internal */ 0) == 0) { goto err; } } @@ -1485,7 +1323,7 @@ static zend_property_info *zend_jit_get_prop_not_accepting_double(zend_reference { zend_property_info *prop; ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) { - if (ZEND_TYPE_CODE(prop->type) != IS_DOUBLE) { + if (!ZEND_TYPE_IS_MASK(prop->type) || !(ZEND_TYPE_MASK(prop->type) & MAY_BE_DOUBLE)) { return prop; } } ZEND_REF_FOREACH_TYPE_SOURCES_END(); diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 90f674a939..c716068923 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -7019,19 +7019,10 @@ static uint32_t skip_valid_arguments(zend_op_array *op_array, zend_ssa *ssa, zen zend_arg_info *arg_info = func->op_array.arg_info + num_args; if (ZEND_TYPE_IS_SET(arg_info->type)) { - if (!ZEND_TYPE_IS_CLASS(arg_info->type)) { - unsigned char code = ZEND_TYPE_CODE(arg_info->type); + if (ZEND_TYPE_IS_MASK(arg_info->type)) { + uint32_t type_mask = ZEND_TYPE_MASK(arg_info->type); uint32_t info = _ssa_op1_info(op_array, ssa, call_info->arg_info[num_args].opline); - - if (code == _IS_BOOL) { - if (info & ((MAY_BE_ANY|MAY_BE_UNDEF) - (MAY_BE_FALSE|MAY_BE_TRUE))) { - break; - } - } else if (code <= IS_RESOURCE) { - if (info & ((MAY_BE_ANY|MAY_BE_UNDEF) - (1 << code))) { - break; - } - } else { + if ((info & (MAY_BE_ANY|MAY_BE_UNDEF)) & ~type_mask) { break; } } else { @@ -8945,6 +8936,16 @@ static int zend_jit_recv(dasm_State **Dst, const zend_op *opline, zend_op_array { uint32_t arg_num = opline->op1.num; + | cmp dword EX->This.u2.num_args, arg_num + | jb >1 + |.cold_code + |1: + | SAVE_VALID_OPLINE opline + | mov FCARG1a, FP + | EXT_CALL zend_missing_arg_error, r0 + | jmp ->exception_handler + |.code + if (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { zend_arg_info *arg_info = NULL; @@ -8966,18 +8967,13 @@ static int zend_jit_recv(dasm_State **Dst, const zend_op *opline, zend_op_array | add r0, offsetof(zend_reference, val) } if (!ZEND_TYPE_IS_CLASS(type)) { - unsigned char code = ZEND_TYPE_CODE(type); - - if (code == _IS_BOOL) { - | cmp byte [r0 + 8], IS_FALSE - | je >1 - | cmp byte [r0 + 8], IS_TRUE - | jne >8 - |1: - } else { - | cmp byte [r0 + 8], code - | jne >8 - } + // TODO: Use bt? + uint32_t type_mask = ZEND_TYPE_MASK(type); + | mov edx, 1 + | mov cl, byte [r0 + 8] + | shl edx, cl + | test edx, type_mask + | je >8 } else { | SAVE_VALID_OPLINE opline | cmp byte [r0 + 8], IS_OBJECT @@ -9054,16 +9050,6 @@ static int zend_jit_recv(dasm_State **Dst, const zend_op *opline, zend_op_array } } - | cmp dword EX->This.u2.num_args, arg_num - | jb >1 - |.cold_code - |1: - | SAVE_VALID_OPLINE opline - | mov FCARG1a, FP - | EXT_CALL zend_missing_arg_error, r0 - | jmp ->exception_handler - |.code - if ((opline+1)->opcode != ZEND_RECV && (opline+1)->opcode != ZEND_RECV_INIT) { last_valid_opline = NULL; if (!zend_jit_set_valid_ip(Dst, opline + 1)) { @@ -9125,8 +9111,12 @@ static int zend_jit_recv_init(dasm_State **Dst, const zend_op *opline, zend_op_a | LOAD_ZVAL_ADDR r0, res_addr | ZVAL_DEREF r0, MAY_BE_REF if (!ZEND_TYPE_IS_CLASS(arg_info->type)) { - | cmp byte [r0 + 8], ZEND_TYPE_CODE(arg_info->type) - | jne >8 + // TODO: Use bt? + | mov edx, 1 + | mov cl, byte [r0 + 8] + | shl edx, cl + | test edx, ZEND_TYPE_MASK(arg_info->type) + | je >8 } else { | cmp byte [r0 + 8], IS_OBJECT | jne >8 diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 5cc023831e..18e3a0cecc 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -582,17 +582,14 @@ static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_ } else { smart_str_append_printf(str, "<required> "); } - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - smart_str_append_printf(str, "%s ", - ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type))); - if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) { - smart_str_append_printf(str, "or NULL "); - } - } else if (ZEND_TYPE_IS_CODE(arg_info->type)) { - smart_str_append_printf(str, "%s ", zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type))); + if (ZEND_TYPE_IS_SET(arg_info->type)) { + /* TODO: We should be using ?Type instead of "or NULL" here. */ + zend_string *type_str = zend_type_to_string(ZEND_TYPE_WITHOUT_NULL(arg_info->type)); + smart_str_append_printf(str, "%s ", ZSTR_VAL(type_str)); if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) { smart_str_append_printf(str, "or NULL "); } + zend_string_release(type_str); } if (arg_info->pass_by_reference) { smart_str_appendc(str, '&'); @@ -802,17 +799,15 @@ static void _function_string(smart_str *str, zend_function *fptr, zend_class_ent smart_str_free(¶m_indent); if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { smart_str_append_printf(str, " %s- Return [ ", indent); - if (ZEND_TYPE_IS_CLASS(fptr->common.arg_info[-1].type)) { - smart_str_append_printf(str, "%s ", - ZSTR_VAL(ZEND_TYPE_NAME(fptr->common.arg_info[-1].type))); - if (ZEND_TYPE_ALLOW_NULL(fptr->common.arg_info[-1].type)) { - smart_str_appends(str, "or NULL "); - } - } else if (ZEND_TYPE_IS_CODE(fptr->common.arg_info[-1].type)) { - smart_str_append_printf(str, "%s ", zend_get_type_by_const(ZEND_TYPE_CODE(fptr->common.arg_info[-1].type))); + if (ZEND_TYPE_IS_SET(fptr->common.arg_info[-1].type)) { + /* TODO: We should use ?Type instead of "or NULL" here */ + zend_string *type_str = + zend_type_to_string(ZEND_TYPE_WITHOUT_NULL(fptr->common.arg_info[-1].type)); + smart_str_append_printf(str, "%s ", ZSTR_VAL(type_str)); if (ZEND_TYPE_ALLOW_NULL(fptr->common.arg_info[-1].type)) { smart_str_appends(str, "or NULL "); } + zend_string_release(type_str); } smart_str_appends(str, "]\n"); } @@ -2565,13 +2560,15 @@ ZEND_METHOD(reflection_parameter, isArray) { reflection_object *intern; parameter_reference *param; + zend_type type; if (zend_parse_parameters_none() == FAILURE) { return; } GET_REFLECTION_OBJECT_PTR(param); - RETVAL_BOOL(ZEND_TYPE_CODE(param->arg_info->type) == IS_ARRAY); + type = ZEND_TYPE_WITHOUT_NULL(param->arg_info->type); + RETVAL_BOOL(ZEND_TYPE_MASK(type) == MAY_BE_ARRAY); } /* }}} */ @@ -2581,13 +2578,15 @@ ZEND_METHOD(reflection_parameter, isCallable) { reflection_object *intern; parameter_reference *param; + zend_type type; if (zend_parse_parameters_none() == FAILURE) { return; } GET_REFLECTION_OBJECT_PTR(param); - RETVAL_BOOL(ZEND_TYPE_CODE(param->arg_info->type) == IS_CALLABLE); + type = ZEND_TYPE_WITHOUT_NULL(param->arg_info->type); + RETVAL_BOOL(ZEND_TYPE_MASK(type) == MAY_BE_CALLABLE); } /* }}} */ @@ -2817,19 +2816,6 @@ ZEND_METHOD(reflection_type, allowsNull) } /* }}} */ -/* {{{ reflection_type_name */ -static zend_string *reflection_type_name(type_reference *param) { - if (ZEND_TYPE_IS_NAME(param->type)) { - return zend_string_copy(ZEND_TYPE_NAME(param->type)); - } else if (ZEND_TYPE_IS_CE(param->type)) { - return zend_string_copy(ZEND_TYPE_CE(param->type)->name); - } else { - const char *name = zend_get_type_by_const(ZEND_TYPE_CODE(param->type)); - return zend_string_init(name, strlen(name), 0); - } -} -/* }}} */ - /* {{{ proto public string ReflectionType::__toString() Return the text of the type hint */ ZEND_METHOD(reflection_type, __toString) @@ -2842,7 +2828,7 @@ ZEND_METHOD(reflection_type, __toString) } GET_REFLECTION_OBJECT_PTR(param); - RETURN_STR(reflection_type_name(param)); + RETURN_STR(zend_type_to_string(ZEND_TYPE_WITHOUT_NULL(param->type))); } /* }}} */ @@ -2858,7 +2844,7 @@ ZEND_METHOD(reflection_named_type, getName) } GET_REFLECTION_OBJECT_PTR(param); - RETURN_STR(reflection_type_name(param)); + RETURN_STR(zend_type_to_string(ZEND_TYPE_WITHOUT_NULL(param->type))); } /* }}} */ @@ -2874,7 +2860,7 @@ ZEND_METHOD(reflection_named_type, isBuiltin) } GET_REFLECTION_OBJECT_PTR(param); - RETVAL_BOOL(ZEND_TYPE_IS_CODE(param->type)); + RETVAL_BOOL(ZEND_TYPE_IS_MASK(param->type)); } /* }}} */ diff --git a/ext/standard/var.c b/ext/standard/var.c index 410c0fdeb9..7b75bffe85 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -77,12 +77,10 @@ static void php_object_property_dump(zend_property_info *prop_info, zval *zv, ze if (Z_TYPE_P(zv) == IS_UNDEF) { ZEND_ASSERT(prop_info->type); - php_printf("%*cuninitialized(%s%s)\n", - level + 1, ' ', - ZEND_TYPE_ALLOW_NULL(prop_info->type) ? "?" : "", - ZEND_TYPE_IS_CLASS(prop_info->type) ? - ZSTR_VAL(ZEND_TYPE_IS_CE(prop_info->type) ? ZEND_TYPE_CE(prop_info->type)->name : ZEND_TYPE_NAME(prop_info->type)) : - zend_get_type_by_const(ZEND_TYPE_CODE(prop_info->type))); + zend_string *type_str = zend_type_to_string(prop_info->type); + php_printf("%*cuninitialized(%s)\n", + level + 1, ' ', ZSTR_VAL(type_str)); + zend_string_release(type_str); } else { php_var_dump(zv, level + 2); } @@ -260,13 +258,10 @@ static void zval_object_property_dump(zend_property_info *prop_info, zval *zv, z ZEND_PUTS("]=>\n"); } if (prop_info && Z_TYPE_P(zv) == IS_UNDEF) { - ZEND_ASSERT(prop_info->type); - php_printf("%*cuninitialized(%s%s)\n", - level + 1, ' ', - ZEND_TYPE_ALLOW_NULL(prop_info->type) ? "?" : "", - ZEND_TYPE_IS_CLASS(prop_info->type) ? - ZSTR_VAL(ZEND_TYPE_IS_CE(prop_info->type) ? ZEND_TYPE_CE(prop_info->type)->name : ZEND_TYPE_NAME(prop_info->type)) : - zend_get_type_by_const(ZEND_TYPE_CODE(prop_info->type))); + zend_string *type_str = zend_type_to_string(prop_info->type); + php_printf("%*cuninitialized(%s)\n", + level + 1, ' ', ZSTR_VAL(type_str)); + zend_string_release(type_str); } else { php_debug_zval_dump(zv, level + 2); } diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 63608124eb..2b1813ee47 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -219,7 +219,7 @@ PHP_MINIT_FUNCTION(zend_test) zval val; ZVAL_LONG(&val, 123); zend_declare_typed_property( - zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL, ZEND_TYPE_ENCODE(IS_LONG, 0)); + zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL, ZEND_TYPE_ENCODE_CODE(IS_LONG, 0)); zend_string_release(name); } @@ -240,7 +240,7 @@ PHP_MINIT_FUNCTION(zend_test) ZVAL_LONG(&val, 123); zend_declare_typed_property( zend_test_class, name, &val, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC, NULL, - ZEND_TYPE_ENCODE(IS_LONG, 0)); + ZEND_TYPE_ENCODE_CODE(IS_LONG, 0)); zend_string_release(name); } |