summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-09-19 12:11:29 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-09-23 15:31:35 +0200
commit9e8ba7891e74a80265e09ff5b810ec947680c1ce (patch)
tree6550898580da2445d9d54370d2adef6e68a881b3 /ext
parent9ec2480bd6d8cadd8ca2ecac07f00fd3d411bc7a (diff)
downloadphp-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.c2
-rw-r--r--ext/opcache/Optimizer/dfa_pass.c5
-rw-r--r--ext/opcache/Optimizer/zend_inference.c65
-rw-r--r--ext/opcache/Optimizer/zend_inference.h6
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c4
-rw-r--r--ext/opcache/jit/zend_jit_helpers.c190
-rw-r--r--ext/opcache/jit/zend_jit_x86.dasc62
-rw-r--r--ext/reflection/php_reflection.c54
-rw-r--r--ext/standard/var.c21
-rw-r--r--ext/zend_test/test.c4
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(&param_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);
}