/* Final class or method | | | */
#define ZEND_ACC_FINAL (1 << 5) /* X | X | | */
/* | | | */
-/* Abstarct method | | | */
+/* Abstract method | | | */
#define ZEND_ACC_ABSTRACT (1 << 6) /* X | X | | */
#define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS (1 << 6) /* X | | | */
/* | | | */
/* User class has methods with static variables | | | */
#define ZEND_HAS_STATIC_IN_METHODS (1 << 15) /* X | | | */
/* | | | */
+/* Whether all property types are resolved to CEs | | | */
+#define ZEND_ACC_PROPERTY_TYPES_RESOLVED (1 << 16) /* X | | | */
+/* | | | */
/* Function Flags (unused: 28...30) | | | */
/* ============== | | | */
/* | | | */
} while (changed);
EG(exception) = NULL;
+ /* Resolve property types */
+ ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) {
+ ce = Z_PTR_P(zv);
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ break;
+ }
+ if ((ce->ce_flags & ZEND_ACC_LINKED)
+ && !(ce->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED)) {
+ zend_bool ok = 1;
+ zend_property_info *prop;
+ if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) {
+ ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
+ zend_string *name, *lcname;
+ if (!ZEND_TYPE_IS_NAME(prop->type)) {
+ continue;
+ }
+
+ name = ZEND_TYPE_NAME(prop->type);
+ lcname = zend_string_tolower(name);
+ p = zend_hash_find_ptr(EG(class_table), lcname);
+ zend_string_release(lcname);
+ if (!p) {
+ ok = 0;
+ continue;
+ }
+
+ zend_string_release(name);
+ prop->type = ZEND_TYPE_ENCODE_CE(p, ZEND_TYPE_ALLOW_NULL(prop->type));
+ } ZEND_HASH_FOREACH_END();
+ }
+ if (ok) {
+ ce->ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED;
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+
/* Move unlinked clases (and with unresilved constants) back to scripts */
orig_dtor = EG(class_table)->pDestructor;
EG(class_table)->pDestructor = NULL;
zend_error(E_WARNING, "Can't preload unlinked class %s at %s:%d\n", ZSTR_VAL(ce->name), ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start);
} else if (!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
zend_error(E_WARNING, "Can't preload class %s with unresolved constants at %s:%d\n", ZSTR_VAL(ce->name), ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start);
+ } else if (!(ce->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED)) {
+ zend_error(E_WARNING, "Can't preload class %s with unresolved property types at %s:%d\n", ZSTR_VAL(ce->name), ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start);
} else {
continue;
}
class Z {
public $foo;
+ public a $bar;
}
zend_string *class_name = ZEND_TYPE_NAME(prop->type);
zend_accel_store_interned_string(class_name);
prop->type = ZEND_TYPE_ENCODE_CLASS(class_name, ZEND_TYPE_ALLOW_NULL(prop->type));
- } else if (ZEND_TYPE_IS_CE(prop->type)) {
- zend_class_entry *ce = ZEND_TYPE_CE(prop->type);
- ce = zend_shared_alloc_get_xlat_entry(ce);
- prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type));
}
}
}
}
-static zend_bool has_unresolved_property_types(zend_class_entry *ce) {
- zend_property_info *prop;
- ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
- if (ZEND_TYPE_IS_NAME(prop->type)) {
- return 1;
- }
- } ZEND_HASH_FOREACH_END();
- return 0;
-}
-
static void zend_persist_class_entry(zval *zv)
{
zend_class_entry *ce = Z_PTR_P(zv);
if (ce->type == ZEND_USER_CLASS) {
if ((ce->ce_flags & ZEND_ACC_LINKED)
&& (ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)
- && !has_unresolved_property_types(ce)
+ && (ce->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED)
&& !ZCG(current_persistent_script)->corrupted) {
ZCG(is_immutable_class) = 1;
ce = Z_PTR_P(zv) = zend_shared_memdup_put(ce, sizeof(zend_class_entry));
}
}
-//static int zend_update_property_info_ce(zval *zv)
-//{
-// zend_property_info *prop = Z_PTR_P(zv);
-//
-// prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
-// return 0;
-//}
-
static void zend_update_parent_ce(zend_class_entry *ce)
{
if (ce->ce_flags & ZEND_ACC_LINKED) {
}
}
+ if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) {
+ zend_property_info *prop;
+ ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
+ if (ZEND_TYPE_IS_CE(prop->type)) {
+ zend_class_entry *ce = ZEND_TYPE_CE(prop->type);
+ if (ce->type == ZEND_USER_CLASS) {
+ ce = zend_shared_alloc_get_xlat_entry(ce);
+ ZEND_ASSERT(ce);
+ prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type));
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+
/* update methods */
if (ce->constructor) {
zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->constructor);
}
}
-static zend_bool has_unresolved_property_types(zend_class_entry *ce) {
+static void check_property_type_resolution(zend_class_entry *ce) {
zend_property_info *prop;
- ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
- if (ZEND_TYPE_IS_NAME(prop->type)) {
- return 1;
- }
- } ZEND_HASH_FOREACH_END();
- return 0;
+ if (ce->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED) {
+ /* Preloading might have computed this already. */
+ return;
+ }
+
+ if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) {
+ ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
+ if (ZEND_TYPE_IS_NAME(prop->type)) {
+ return;
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+ ce->ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED;
}
static void zend_persist_class_entry_calc(zval *zv)
zend_class_entry *ce = Z_PTR_P(zv);
if (ce->type == ZEND_USER_CLASS) {
+ check_property_type_resolution(ce);
+
ZCG(is_immutable_class) =
(ce->ce_flags & ZEND_ACC_LINKED) &&
(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) &&
- !has_unresolved_property_types(ce) &&
+ (ce->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED) &&
!ZCG(current_persistent_script)->corrupted;
ADD_SIZE_EX(sizeof(zend_class_entry));