mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Don't reverse class order during preloading
We don't guarantee any particular order, but this reduces test failures under --preload that are sensitive to class order. Add some ZEND_HASH_FOREACH_*_FROM macros to allow skipping the persistent classes while iterating in forward direction.
This commit is contained in:
@@ -958,10 +958,10 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht,
|
||||
#define zend_hash_get_current_data_ptr(ht) \
|
||||
zend_hash_get_current_data_ptr_ex(ht, &(ht)->nInternalPointer)
|
||||
|
||||
#define ZEND_HASH_FOREACH(_ht, indirect) do { \
|
||||
#define ZEND_HASH_FOREACH_FROM(_ht, indirect, _from) do { \
|
||||
HashTable *__ht = (_ht); \
|
||||
Bucket *_p = __ht->arData; \
|
||||
Bucket *_end = _p + __ht->nNumUsed; \
|
||||
Bucket *_p = __ht->arData + (_from); \
|
||||
Bucket *_end = __ht->arData + __ht->nNumUsed; \
|
||||
for (; _p != _end; _p++) { \
|
||||
zval *_z = &_p->val; \
|
||||
if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \
|
||||
@@ -969,6 +969,8 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht,
|
||||
} \
|
||||
if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue;
|
||||
|
||||
#define ZEND_HASH_FOREACH(_ht, indirect) ZEND_HASH_FOREACH_FROM(_ht, indirect, 0)
|
||||
|
||||
#define ZEND_HASH_REVERSE_FOREACH(_ht, indirect) do { \
|
||||
HashTable *__ht = (_ht); \
|
||||
uint32_t _idx = __ht->nNumUsed; \
|
||||
@@ -1011,6 +1013,10 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht,
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_bucket = _p;
|
||||
|
||||
#define ZEND_HASH_FOREACH_BUCKET_FROM(ht, _bucket, _from) \
|
||||
ZEND_HASH_FOREACH_FROM(ht, 0, _from); \
|
||||
_bucket = _p;
|
||||
|
||||
#define ZEND_HASH_REVERSE_FOREACH_BUCKET(ht, _bucket) \
|
||||
ZEND_HASH_REVERSE_FOREACH(ht, 0); \
|
||||
_bucket = _p;
|
||||
@@ -1080,6 +1086,11 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht,
|
||||
_key = _p->key; \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_FOREACH_STR_KEY_VAL_FROM(ht, _key, _val, _from) \
|
||||
ZEND_HASH_FOREACH_FROM(ht, 0, _from); \
|
||||
_key = _p->key; \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(ht, _key, _val) \
|
||||
ZEND_HASH_REVERSE_FOREACH(ht, 0); \
|
||||
_key = _p->key; \
|
||||
|
||||
@@ -3564,32 +3564,28 @@ static void preload_move_user_classes(HashTable *src, HashTable *dst)
|
||||
|
||||
src->pDestructor = NULL;
|
||||
zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0);
|
||||
ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) {
|
||||
ZEND_HASH_FOREACH_BUCKET_FROM(src, p, EG(persistent_classes_count)) {
|
||||
zend_class_entry *ce = Z_PTR(p->val);
|
||||
|
||||
if (EXPECTED(ce->type == ZEND_USER_CLASS)) {
|
||||
if (ce->info.user.filename != filename) {
|
||||
filename = ce->info.user.filename;
|
||||
if (filename) {
|
||||
if (!(copy = zend_hash_exists(preload_scripts, filename))) {
|
||||
size_t eval_len = preload_try_strip_filename(filename);
|
||||
if (eval_len) {
|
||||
copy = zend_hash_str_exists(preload_scripts, ZSTR_VAL(filename), eval_len);
|
||||
}
|
||||
ZEND_ASSERT(ce->type == ZEND_USER_CLASS);
|
||||
if (ce->info.user.filename != filename) {
|
||||
filename = ce->info.user.filename;
|
||||
if (filename) {
|
||||
if (!(copy = zend_hash_exists(preload_scripts, filename))) {
|
||||
size_t eval_len = preload_try_strip_filename(filename);
|
||||
if (eval_len) {
|
||||
copy = zend_hash_str_exists(preload_scripts, ZSTR_VAL(filename), eval_len);
|
||||
}
|
||||
} else {
|
||||
copy = 0;
|
||||
}
|
||||
}
|
||||
if (copy) {
|
||||
_zend_hash_append(dst, p->key, &p->val);
|
||||
} else {
|
||||
orig_dtor(&p->val);
|
||||
copy = 0;
|
||||
}
|
||||
zend_hash_del_bucket(src, p);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (copy) {
|
||||
_zend_hash_append(dst, p->key, &p->val);
|
||||
} else {
|
||||
orig_dtor(&p->val);
|
||||
}
|
||||
zend_hash_del_bucket(src, p);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
src->pDestructor = orig_dtor;
|
||||
}
|
||||
@@ -3844,11 +3840,10 @@ static void preload_link(void)
|
||||
do {
|
||||
changed = 0;
|
||||
|
||||
ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL_FROM(EG(class_table), key, zv, EG(persistent_classes_count)) {
|
||||
ce = Z_PTR_P(zv);
|
||||
if (ce->type == ZEND_INTERNAL_CLASS) {
|
||||
break;
|
||||
}
|
||||
ZEND_ASSERT(ce->type != ZEND_INTERNAL_CLASS);
|
||||
|
||||
if ((ce->ce_flags & (ZEND_ACC_TOP_LEVEL|ZEND_ACC_ANON_CLASS))
|
||||
&& !(ce->ce_flags & ZEND_ACC_LINKED)) {
|
||||
zend_string *lcname = zend_string_tolower(ce->name);
|
||||
@@ -3967,7 +3962,8 @@ static void preload_link(void)
|
||||
} while (changed);
|
||||
|
||||
/* Warn for classes that could not be linked. */
|
||||
ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL_FROM(
|
||||
EG(class_table), key, zv, EG(persistent_classes_count)) {
|
||||
ce = Z_PTR_P(zv);
|
||||
if (ce->type == ZEND_INTERNAL_CLASS) {
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user