summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2021-01-12 16:33:38 +0300
committerDmitry Stogov <dmitry@zend.com>2021-01-12 16:33:38 +0300
commit1a44599deef8d71e327dd841a06b6546c28b57c2 (patch)
treea18bed66add5a5ceadebe9fbef382c229617dce5
parent1a0fa12753931dba9908161df0f63feb6d0ba025 (diff)
downloadphp-git-1a44599deef8d71e327dd841a06b6546c28b57c2.tar.gz
Always use CG(arena) for unin type lists
-rw-r--r--Zend/zend_compile.c59
-rw-r--r--ext/opcache/zend_persist.c8
-rw-r--r--ext/opcache/zend_persist_calc.c8
3 files changed, 37 insertions, 38 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index b87f79446c..c82a82fc9a 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -6126,7 +6126,7 @@ static zend_bool zend_type_contains_traversable(zend_type type) {
// TODO: Ideally we'd canonicalize "iterable" into "array|Traversable" and essentially
// treat it as a built-in type alias.
static zend_type zend_compile_typename(
- zend_ast *ast, zend_bool force_allow_null, zend_bool use_arena) /* {{{ */
+ zend_ast *ast, zend_bool force_allow_null) /* {{{ */
{
zend_bool allow_null = force_allow_null;
zend_ast_attr orig_ast_attr = ast->attr;
@@ -6138,6 +6138,12 @@ static zend_type zend_compile_typename(
if (ast->kind == ZEND_AST_TYPE_UNION) {
zend_ast_list *list = zend_ast_get_list(ast);
+ zend_type_list *type_list;
+ ALLOCA_FLAG(use_heap)
+
+ type_list = do_alloca(ZEND_TYPE_LIST_SIZE(list->children), use_heap);
+ type_list->num_types = 0;
+
for (uint32_t i = 0; i < list->children; i++) {
zend_ast *type_ast = list->child[i];
zend_type single_type = zend_compile_single_typename(type_ast);
@@ -6163,37 +6169,20 @@ static zend_type zend_compile_typename(
ZEND_TYPE_SET_PTR(type, ZEND_TYPE_NAME(single_type));
ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_NAME_BIT;
} else {
- zend_type_list *list;
- if (ZEND_TYPE_HAS_LIST(type)) {
- /* Add name to existing name list. */
- zend_type_list *old_list = ZEND_TYPE_LIST(type);
- if (use_arena) {
- // TODO: Add a zend_arena_realloc API?
- list = zend_arena_alloc(
- &CG(arena), ZEND_TYPE_LIST_SIZE(old_list->num_types + 1));
- memcpy(list, old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types));
- } else {
- list = erealloc(old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types + 1));
- }
- } else {
+ if (type_list->num_types == 0) {
/* Switch from single name to name list. */
- size_t size = ZEND_TYPE_LIST_SIZE(2);
- list = use_arena ? zend_arena_alloc(&CG(arena), size) : emalloc(size);
- list->num_types = 1;
- list->types[0] = type;
- ZEND_TYPE_FULL_MASK(list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
+ type_list->num_types = 1;
+ type_list->types[0] = type;
+ ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
+ ZEND_TYPE_SET_LIST(type, type_list);
}
- list->types[list->num_types++] = single_type;
- ZEND_TYPE_SET_LIST(type, list);
- if (use_arena) {
- ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
- }
+ type_list->types[type_list->num_types++] = single_type;
/* Check for trivially redundant class types */
- for (size_t i = 0; i < list->num_types - 1; i++) {
+ for (size_t i = 0; i < type_list->num_types - 1; i++) {
if (zend_string_equals_ci(
- ZEND_TYPE_NAME(list->types[i]), ZEND_TYPE_NAME(single_type))) {
+ ZEND_TYPE_NAME(type_list->types[i]), ZEND_TYPE_NAME(single_type))) {
zend_string *single_type_str = zend_type_to_string(single_type);
zend_error_noreturn(E_COMPILE_ERROR,
"Duplicate type %s is redundant", ZSTR_VAL(single_type_str));
@@ -6202,6 +6191,16 @@ static zend_type zend_compile_typename(
}
}
}
+
+ if (type_list->num_types) {
+ zend_type_list *list = zend_arena_alloc(
+ &CG(arena), ZEND_TYPE_LIST_SIZE(type_list->num_types));
+ memcpy(list, type_list, ZEND_TYPE_LIST_SIZE(type_list->num_types));
+ ZEND_TYPE_SET_LIST(type, list);
+ ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
+ }
+
+ free_alloca(type_list, use_heap);
} else {
type = zend_compile_single_typename(ast);
}
@@ -6378,7 +6377,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
arg_infos->name = NULL;
if (return_type_ast) {
arg_infos->type = zend_compile_typename(
- return_type_ast, /* force_allow_null */ 0, /* use_arena */ 0);
+ return_type_ast, /* force_allow_null */ 0);
ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS(
(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0);
} else {
@@ -6480,7 +6479,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
zend_bool force_nullable = default_type == IS_NULL && !visibility;
op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
- arg_info->type = zend_compile_typename(type_ast, force_nullable, /* use_arena */ 0);
+ arg_info->type = zend_compile_typename(type_ast, force_nullable);
if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_VOID) {
zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
@@ -6546,7 +6545,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
/* Recompile the type, as it has different memory management requirements. */
zend_type type = ZEND_TYPE_INIT_NONE(0);
if (type_ast) {
- type = zend_compile_typename(type_ast, /* force_allow_null */ 0, /* use_arena */ 1);
+ type = zend_compile_typename(type_ast, /* force_allow_null */ 0);
}
/* Don't give the property an explicit default value. For typed properties this means
@@ -7076,7 +7075,7 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags, z
zend_type type = ZEND_TYPE_INIT_NONE(0);
if (type_ast) {
- type = zend_compile_typename(type_ast, /* force_allow_null */ 0, /* use_arena */ 1);
+ type = zend_compile_typename(type_ast, /* force_allow_null */ 0);
if (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE)) {
zend_string *str = zend_type_to_string(type);
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c
index efadcb91fb..c37bb2ec45 100644
--- a/ext/opcache/zend_persist.c
+++ b/ext/opcache/zend_persist.c
@@ -285,11 +285,11 @@ static HashTable *zend_persist_attributes(HashTable *attributes)
return ptr;
}
-static void zend_persist_type(zend_type *type) {
+static void zend_persist_type(zend_type *type, zend_bool use_arena) {
if (ZEND_TYPE_HAS_LIST(*type)) {
zend_type_list *list = ZEND_TYPE_LIST(*type);
if (ZEND_TYPE_USES_ARENA(*type)) {
- if (!ZCG(is_immutable_class)) {
+ if (!ZCG(is_immutable_class) && use_arena) {
list = zend_shared_memdup_arena_put(list, ZEND_TYPE_LIST_SIZE(list->num_types));
} else {
/* Moved from arena to SHM because type list was fully resolved. */
@@ -575,7 +575,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
if (arg_info[i].name) {
zend_accel_store_interned_string(arg_info[i].name);
}
- zend_persist_type(&arg_info[i].type);
+ zend_persist_type(&arg_info[i].type, 0);
}
if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
arg_info++;
@@ -738,7 +738,7 @@ static zend_property_info *zend_persist_property_info(zend_property_info *prop)
if (prop->attributes) {
prop->attributes = zend_persist_attributes(prop->attributes);
}
- zend_persist_type(&prop->type);
+ zend_persist_type(&prop->type, 1);
return prop;
}
diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c
index 9de02e91e2..191674b641 100644
--- a/ext/opcache/zend_persist_calc.c
+++ b/ext/opcache/zend_persist_calc.c
@@ -166,10 +166,10 @@ static void zend_persist_attributes_calc(HashTable *attributes)
}
}
-static void zend_persist_type_calc(zend_type *type)
+static void zend_persist_type_calc(zend_type *type, zend_bool use_arena)
{
if (ZEND_TYPE_HAS_LIST(*type)) {
- if (ZEND_TYPE_USES_ARENA(*type) && !ZCG(is_immutable_class)) {
+ if (ZEND_TYPE_USES_ARENA(*type) && !ZCG(is_immutable_class) && use_arena) {
ADD_ARENA_SIZE(ZEND_TYPE_LIST_SIZE(ZEND_TYPE_LIST(*type)->num_types));
} else {
ADD_SIZE(ZEND_TYPE_LIST_SIZE(ZEND_TYPE_LIST(*type)->num_types));
@@ -254,7 +254,7 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
if (arg_info[i].name) {
ADD_INTERNED_STRING(arg_info[i].name);
}
- zend_persist_type_calc(&arg_info[i].type);
+ zend_persist_type_calc(&arg_info[i].type, 0);
}
}
@@ -338,7 +338,7 @@ static void zend_persist_property_info_calc(zend_property_info *prop)
{
ADD_SIZE_EX(sizeof(zend_property_info));
ADD_INTERNED_STRING(prop->name);
- zend_persist_type_calc(&prop->type);
+ zend_persist_type_calc(&prop->type, 1);
if (ZCG(accel_directives).save_comments && prop->doc_comment) {
ADD_STRING(prop->doc_comment);
}