diff options
Diffstat (limited to 'ext/opcache/zend_persist.c')
-rw-r--r-- | ext/opcache/zend_persist.c | 393 |
1 files changed, 246 insertions, 147 deletions
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index efadcb91fb..52d961c428 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -36,6 +36,7 @@ #endif #define zend_set_str_gc_flags(str) do { \ + GC_SET_REFCOUNT(str, 2); \ if (file_cache_only) { \ GC_TYPE_INFO(str) = GC_STRING | (IS_STR_INTERNED << GC_FLAGS_SHIFT); \ } else { \ @@ -81,6 +82,7 @@ typedef void (*zend_persist_func_t)(zval*); static void zend_persist_zval(zval *z); +static void zend_persist_op_array(zval *zv); static const uint32_t uninitialized_bucket[-HT_MIN_MASK] = {HT_INVALID_IDX, HT_INVALID_IDX}; @@ -115,7 +117,11 @@ static void zend_hash_persist(HashTable *ht) } if (HT_FLAGS(ht) & HASH_FLAG_PACKED) { void *data = HT_GET_DATA_ADDR(ht); - data = zend_shared_memdup_free(data, HT_USED_SIZE(ht)); + if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { + data = zend_shared_memdup(data, HT_USED_SIZE(ht)); + } else { + data = zend_shared_memdup_free(data, HT_USED_SIZE(ht)); + } HT_SET_DATA_ADDR(ht, data); } else if (ht->nNumUsed > HT_MIN_SIZE && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) { /* compact table */ @@ -133,7 +139,9 @@ static void zend_hash_persist(HashTable *ht) ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE((hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket)))); HT_HASH_RESET(ht); memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket)); - efree(old_data); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + efree(old_data); + } /* rehash */ for (idx = 0; idx < ht->nNumUsed; idx++) { @@ -150,7 +158,9 @@ static void zend_hash_persist(HashTable *ht) ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ ZCG(mem) = (void*)((char*)data + ZEND_ALIGNED_SIZE(HT_USED_SIZE(ht))); memcpy(data, old_data, HT_USED_SIZE(ht)); - efree(old_data); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + efree(old_data); + } HT_SET_DATA_ADDR(ht, data); } } @@ -201,33 +211,29 @@ static void zend_persist_zval(zval *z) if (new_ptr) { Z_ARR_P(z) = new_ptr; Z_TYPE_FLAGS_P(z) = 0; + } else if (!ZCG(current_persistent_script)->corrupted + && zend_accel_in_shm(Z_ARR_P(z))) { + /* pass */ } else { Bucket *p; if (!Z_REFCOUNTED_P(z)) { Z_ARR_P(z) = zend_shared_memdup_put(Z_ARR_P(z), sizeof(zend_array)); - zend_hash_persist(Z_ARRVAL_P(z)); - ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(z), p) { - if (p->key) { - zend_accel_memdup_interned_string(p->key); - } - zend_persist_zval(&p->val); - } ZEND_HASH_FOREACH_END(); } else { GC_REMOVE_FROM_BUFFER(Z_ARR_P(z)); Z_ARR_P(z) = zend_shared_memdup_put_free(Z_ARR_P(z), sizeof(zend_array)); - zend_hash_persist(Z_ARRVAL_P(z)); - ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(z), p) { - if (p->key) { - zend_accel_store_interned_string(p->key); - } - zend_persist_zval(&p->val); - } ZEND_HASH_FOREACH_END(); - /* make immutable array */ - Z_TYPE_FLAGS_P(z) = 0; - GC_SET_REFCOUNT(Z_COUNTED_P(z), 2); - GC_ADD_FLAGS(Z_COUNTED_P(z), IS_ARRAY_IMMUTABLE); } + zend_hash_persist(Z_ARRVAL_P(z)); + ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(z), p) { + if (p->key) { + zend_accel_store_interned_string(p->key); + } + zend_persist_zval(&p->val); + } ZEND_HASH_FOREACH_END(); + /* make immutable array */ + Z_TYPE_FLAGS_P(z) = 0; + GC_SET_REFCOUNT(Z_COUNTED_P(z), 2); + GC_ADD_FLAGS(Z_COUNTED_P(z), IS_ARRAY_IMMUTABLE); } break; case IS_CONSTANT_AST: @@ -235,7 +241,8 @@ static void zend_persist_zval(zval *z) if (new_ptr) { Z_AST_P(z) = new_ptr; Z_TYPE_FLAGS_P(z) = 0; - } else { + } else if (ZCG(current_persistent_script)->corrupted + || !zend_accel_in_shm(Z_AST_P(z))) { zend_ast_ref *old_ref = Z_AST_P(z); Z_AST_P(z) = zend_shared_memdup_put(Z_AST_P(z), sizeof(zend_ast_ref)); zend_persist_ast(GC_AST(old_ref)); @@ -252,50 +259,99 @@ static void zend_persist_zval(zval *z) static HashTable *zend_persist_attributes(HashTable *attributes) { - HashTable *ptr = zend_shared_alloc_get_xlat_entry(attributes); + uint32_t i; + zval *v; - if (!ptr) { - uint32_t i; - zval *v; + if (!ZCG(current_persistent_script)->corrupted && zend_accel_in_shm(attributes)) { + return attributes; + } - zend_hash_persist(attributes); + zend_hash_persist(attributes); - ZEND_HASH_FOREACH_VAL(attributes, v) { - zend_attribute *attr = Z_PTR_P(v); - zend_attribute *copy = zend_shared_memdup_put_free(attr, ZEND_ATTRIBUTE_SIZE(attr->argc)); + ZEND_HASH_FOREACH_VAL(attributes, v) { + zend_attribute *attr = Z_PTR_P(v); + zend_attribute *copy = zend_shared_memdup_put_free(attr, ZEND_ATTRIBUTE_SIZE(attr->argc)); - zend_accel_store_interned_string(copy->name); - zend_accel_store_interned_string(copy->lcname); + zend_accel_store_interned_string(copy->name); + zend_accel_store_interned_string(copy->lcname); - for (i = 0; i < copy->argc; i++) { - if (copy->args[i].name) { - zend_accel_store_interned_string(copy->args[i].name); - } - zend_persist_zval(©->args[i].value); + for (i = 0; i < copy->argc; i++) { + if (copy->args[i].name) { + zend_accel_store_interned_string(copy->args[i].name); } + zend_persist_zval(©->args[i].value); + } - ZVAL_PTR(v, copy); - } ZEND_HASH_FOREACH_END(); + ZVAL_PTR(v, copy); + } ZEND_HASH_FOREACH_END(); - ptr = zend_shared_memdup_put_free(attributes, sizeof(HashTable)); - GC_SET_REFCOUNT(ptr, 2); - GC_TYPE_INFO(ptr) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT); + HashTable *ptr = zend_shared_memdup_put_free(attributes, sizeof(HashTable)); + GC_SET_REFCOUNT(ptr, 2); + GC_TYPE_INFO(ptr) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT); + + return ptr; +} + +uint32_t zend_accel_get_type_map_ptr(zend_string *type_name, zend_class_entry *scope) +{ + uint32_t ret; + + if (zend_string_equals_literal_ci(type_name, "self")) { + if (!scope || (scope->ce_flags & ZEND_ACC_TRAIT)) { + return 0; + } + type_name = scope->name; + } else if (zend_string_equals_literal_ci(type_name, "parent")) { + if (!scope || !scope->parent) { + return 0; + } + if (scope->ce_flags & ZEND_ACC_RESOLVED_PARENT) { + type_name = scope->parent->name; + } else { + type_name = scope->parent_name; + } } + ZEND_ASSERT(GC_FLAGS(type_name) & GC_IMMUTABLE); + ZEND_ASSERT(GC_FLAGS(type_name) & IS_STR_PERMANENT); + ret = GC_REFCOUNT(type_name); + + /* We use type.name.gc.refcount to keep map_ptr of corresponding type */ + if (ret <= 2) { + do { + ret = (uint32_t)(uintptr_t)zend_map_ptr_new(); + } while (ret <= 2); + GC_SET_REFCOUNT(type_name, ret); + } + return ret; +} + +static HashTable *zend_persist_backed_enum_table(HashTable *backed_enum_table) +{ + HashTable *ptr; + Bucket *p; + zend_hash_persist(backed_enum_table); + + ZEND_HASH_FOREACH_BUCKET(backed_enum_table, p) { + if (p->key != NULL) { + zend_accel_store_interned_string(p->key); + } + zend_persist_zval(&p->val); + } ZEND_HASH_FOREACH_END(); + + ptr = zend_shared_memdup_free(backed_enum_table, sizeof(HashTable)); + GC_SET_REFCOUNT(ptr, 2); + GC_TYPE_INFO(ptr) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT); + return ptr; } -static void zend_persist_type(zend_type *type) { +static void zend_persist_type(zend_type *type, zend_class_entry *scope) { 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)) { - 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. */ - list = zend_shared_memdup_put(list, ZEND_TYPE_LIST_SIZE(list->num_types)); - ZEND_TYPE_FULL_MASK(*type) &= ~_ZEND_TYPE_ARENA_BIT; - } + list = zend_shared_memdup_put(list, ZEND_TYPE_LIST_SIZE(list->num_types)); + ZEND_TYPE_FULL_MASK(*type) &= ~_ZEND_TYPE_ARENA_BIT; } else { list = zend_shared_memdup_put_free(list, ZEND_TYPE_LIST_SIZE(list->num_types)); } @@ -308,6 +364,14 @@ static void zend_persist_type(zend_type *type) { zend_string *type_name = ZEND_TYPE_NAME(*single_type); zend_accel_store_interned_string(type_name); ZEND_TYPE_SET_PTR(*single_type, type_name); + if (!ZCG(current_persistent_script)->corrupted) { + uint32_t ptr = zend_accel_get_type_map_ptr(type_name, scope); + + if (ptr) { + single_type->type_mask |= _ZEND_TYPE_CACHE_BIT; + single_type->ce_cache__ptr = ptr; + } + } } } ZEND_TYPE_FOREACH_END(); } @@ -352,6 +416,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc if (scope) { op_array->scope = scope; } + if (op_array->prototype) { zend_function *ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype); @@ -367,7 +432,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc op_array->static_variables = zend_shared_alloc_get_xlat_entry(op_array->static_variables); ZEND_ASSERT(op_array->static_variables != NULL); } - ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); if (op_array->literals) { op_array->literals = zend_shared_alloc_get_xlat_entry(op_array->literals); ZEND_ASSERT(op_array->literals != NULL); @@ -401,7 +465,8 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc } } if (op_array->attributes) { - op_array->attributes = zend_persist_attributes(op_array->attributes); + op_array->attributes = zend_shared_alloc_get_xlat_entry(op_array->attributes); + ZEND_ASSERT(op_array->attributes != NULL); } if (op_array->try_catch_array) { @@ -435,7 +500,13 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc op_array->prototype = NULL; } - if (op_array->static_variables) { + if (op_array->scope + && !(op_array->fn_flags & ZEND_ACC_CLOSURE) + && (op_array->scope->ce_flags & ZEND_ACC_CACHED)) { + return; + } + + if (op_array->static_variables && !zend_accel_in_shm(op_array->static_variables)) { Bucket *p; zend_hash_persist(op_array->static_variables); @@ -449,7 +520,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc GC_SET_REFCOUNT(op_array->static_variables, 2); GC_TYPE_INFO(op_array->static_variables) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT); } - ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); if (op_array->literals) { zval *p, *end; @@ -551,7 +621,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc efree(op_array->opcodes); op_array->opcodes = new_opcodes; - ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL); } if (op_array->filename) { @@ -575,7 +644,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, op_array->scope); } if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { arg_info++; @@ -612,6 +681,17 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc } } + if (op_array->num_dynamic_func_defs) { + op_array->dynamic_func_defs = zend_shared_memdup_put_free( + op_array->dynamic_func_defs, sizeof(zend_function *) * op_array->num_dynamic_func_defs); + for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) { + zval tmp; + ZVAL_PTR(&tmp, op_array->dynamic_func_defs[i]); + zend_persist_op_array(&tmp); + op_array->dynamic_func_defs[i] = Z_PTR(tmp); + } + } + ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem)))); #ifdef HAVE_JIT @@ -625,24 +705,27 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc static void zend_persist_op_array(zval *zv) { zend_op_array *op_array = Z_PTR_P(zv); - + zend_op_array *old_op_array; ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION); - op_array = Z_PTR_P(zv) = zend_shared_memdup(Z_PTR_P(zv), sizeof(zend_op_array)); - zend_persist_op_array_ex(op_array, NULL); - if (!ZCG(current_persistent_script)->corrupted) { - op_array->fn_flags |= ZEND_ACC_IMMUTABLE; - ZEND_MAP_PTR_NEW(op_array->run_time_cache); - if (op_array->static_variables) { - ZEND_MAP_PTR_NEW(op_array->static_variables_ptr); + + old_op_array = zend_shared_alloc_get_xlat_entry(op_array); + if (!old_op_array) { + op_array = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_op_array)); + zend_persist_op_array_ex(op_array, NULL); + if (!ZCG(current_persistent_script)->corrupted) { + op_array->fn_flags |= ZEND_ACC_IMMUTABLE; + ZEND_MAP_PTR_NEW(op_array->run_time_cache); + if (op_array->static_variables) { + ZEND_MAP_PTR_NEW(op_array->static_variables_ptr); + } } } else { - ZEND_MAP_PTR_INIT(op_array->run_time_cache, ZCG(arena_mem)); - ZCG(arena_mem) = (void*)(((char*)ZCG(arena_mem)) + ZEND_ALIGNED_SIZE(sizeof(void*))); - ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL); + /* This can happen during preloading, if a dynamic function definition is declared. */ + Z_PTR_P(zv) = old_op_array; } } -static void zend_persist_class_method(zval *zv) +static void zend_persist_class_method(zval *zv, zend_class_entry *ce) { zend_op_array *op_array = Z_PTR_P(zv); zend_op_array *old_op_array; @@ -654,11 +737,7 @@ static void zend_persist_class_method(zval *zv) if (old_op_array) { Z_PTR_P(zv) = old_op_array; } else { - if (ZCG(is_immutable_class)) { - op_array = Z_PTR_P(zv) = zend_shared_memdup_put(op_array, sizeof(zend_internal_function)); - } else { - op_array = Z_PTR_P(zv) = zend_shared_memdup_arena_put(op_array, sizeof(zend_internal_function)); - } + op_array = Z_PTR_P(zv) = zend_shared_memdup_put(op_array, sizeof(zend_internal_function)); if (op_array->scope) { void *persist_ptr; @@ -676,6 +755,14 @@ static void zend_persist_class_method(zval *zv) return; } + if ((op_array->fn_flags & ZEND_ACC_IMMUTABLE) + && !op_array->static_variables + && !ZCG(current_persistent_script)->corrupted + && zend_accel_in_shm(op_array)) { + zend_shared_alloc_register_xlat_entry(op_array, op_array); + return; + } + old_op_array = zend_shared_alloc_get_xlat_entry(op_array); if (old_op_array) { Z_PTR_P(zv) = old_op_array; @@ -692,33 +779,27 @@ static void zend_persist_class_method(zval *zv) } return; } - if (ZCG(is_immutable_class)) { - op_array = Z_PTR_P(zv) = zend_shared_memdup_put(op_array, sizeof(zend_op_array)); - } else { - op_array = Z_PTR_P(zv) = zend_shared_memdup_arena_put(op_array, sizeof(zend_op_array)); - } + op_array = Z_PTR_P(zv) = zend_shared_memdup_put(op_array, sizeof(zend_op_array)); zend_persist_op_array_ex(op_array, NULL); - if (ZCG(is_immutable_class)) { + if ((ce->ce_flags & ZEND_ACC_LINKED) + && (ce->ce_flags & ZEND_ACC_IMMUTABLE)) { op_array->fn_flags |= ZEND_ACC_IMMUTABLE; ZEND_MAP_PTR_NEW(op_array->run_time_cache); if (op_array->static_variables) { ZEND_MAP_PTR_NEW(op_array->static_variables_ptr); } } else { - ZEND_MAP_PTR_INIT(op_array->run_time_cache, ZCG(arena_mem)); - ZCG(arena_mem) = (void*)(((char*)ZCG(arena_mem)) + ZEND_ALIGNED_SIZE(sizeof(void*))); - ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL); + if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { + ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL); + ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL); + } } } static zend_property_info *zend_persist_property_info(zend_property_info *prop) { zend_class_entry *ce; - if (ZCG(is_immutable_class)) { - prop = zend_shared_memdup_put(prop, sizeof(zend_property_info)); - } else { - prop = zend_shared_memdup_arena_put(prop, sizeof(zend_property_info)); - } + prop = zend_shared_memdup_put(prop, sizeof(zend_property_info)); ce = zend_shared_alloc_get_xlat_entry(prop->ce); if (ce) { prop->ce = ce; @@ -738,7 +819,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, ce); return prop; } @@ -750,12 +831,11 @@ static void zend_persist_class_constant(zval *zv) if (c) { Z_PTR_P(zv) = c; return; + } else if (!ZCG(current_persistent_script)->corrupted + && zend_accel_in_shm(Z_PTR_P(zv))) { + return; } - if (ZCG(is_immutable_class)) { - c = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_class_constant)); - } else { - c = Z_PTR_P(zv) = zend_shared_memdup_arena_put(Z_PTR_P(zv), sizeof(zend_class_constant)); - } + c = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_class_constant)); zend_persist_zval(&c->value); ce = zend_shared_alloc_get_xlat_entry(c->ce); if (ce) { @@ -783,38 +863,35 @@ static void zend_persist_class_constant(zval *zv) } } -static void zend_persist_class_entry(zval *zv) +zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce) { Bucket *p; - zend_class_entry *orig_ce = Z_PTR_P(zv), *ce = orig_ce; + zend_class_entry *ce = orig_ce; if (ce->type == ZEND_USER_CLASS) { /* The same zend_class_entry may be reused by class_alias */ zend_class_entry *new_ce = zend_shared_alloc_get_xlat_entry(ce); if (new_ce) { - Z_PTR_P(zv) = new_ce; - return; + return new_ce; } - if ((ce->ce_flags & ZEND_ACC_LINKED) - && (ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) - && (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)); + ce = zend_shared_memdup_put(ce, sizeof(zend_class_entry)); + if (EXPECTED(!ZCG(current_persistent_script)->corrupted)) { ce->ce_flags |= ZEND_ACC_IMMUTABLE; - } else { - ZCG(is_immutable_class) = 0; - ce = Z_PTR_P(zv) = zend_shared_memdup_arena_put(ce, sizeof(zend_class_entry)); } - zend_accel_store_interned_string(ce->name); - if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_LINKED)) { - zend_accel_store_interned_string(ce->parent_name); + ce->inheritance_cache = NULL; + + if (!(ce->ce_flags & ZEND_ACC_CACHED)) { + zend_accel_store_interned_string(ce->name); + if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_LINKED)) { + zend_accel_store_interned_string(ce->parent_name); + } } + zend_hash_persist(&ce->function_table); ZEND_HASH_FOREACH_BUCKET(&ce->function_table, p) { ZEND_ASSERT(p->key != NULL); zend_accel_store_interned_string(p->key); - zend_persist_class_method(&p->val); + zend_persist_class_method(&p->val, ce); } ZEND_HASH_FOREACH_END(); HT_FLAGS(&ce->function_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS); if (ce->default_properties_table) { @@ -825,6 +902,15 @@ static void zend_persist_class_entry(zval *zv) zend_persist_zval(&ce->default_properties_table[i]); } } + if ((ce->ce_flags & ZEND_ACC_IMMUTABLE) + && (ce->ce_flags & ZEND_ACC_LINKED) + && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + ZEND_MAP_PTR_NEW(ce->mutable_data); + } else if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { + ZEND_MAP_PTR_INIT(ce->mutable_data, NULL); + } else { + ce->ce_flags |= ZEND_ACC_FILE_CACHED; + } if (ce->default_static_members_table) { int i; ce->default_static_members_table = zend_shared_memdup_free(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count); @@ -836,7 +922,11 @@ static void zend_persist_class_entry(zval *zv) zend_persist_zval(&ce->default_static_members_table[i]); } if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { - ZEND_MAP_PTR_NEW(ce->static_members_table); + if (ce->ce_flags & ZEND_ACC_LINKED) { + ZEND_MAP_PTR_NEW(ce->static_members_table); + } else { + ZEND_MAP_PTR_INIT(ce->static_members_table, NULL); + } } else { ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table); } @@ -852,23 +942,6 @@ static void zend_persist_class_entry(zval *zv) } ZEND_HASH_FOREACH_END(); HT_FLAGS(&ce->constants_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS); - if (ce->info.user.filename) { - zend_accel_store_string(ce->info.user.filename); - } - if (ce->info.user.doc_comment) { - if (ZCG(accel_directives).save_comments) { - zend_accel_store_interned_string(ce->info.user.doc_comment); - } else { - if (!zend_shared_alloc_get_xlat_entry(ce->info.user.doc_comment)) { - zend_shared_alloc_register_xlat_entry(ce->info.user.doc_comment, ce->info.user.doc_comment); - zend_string_release_ex(ce->info.user.doc_comment, 0); - } - ce->info.user.doc_comment = NULL; - } - } - if (ce->attributes) { - ce->attributes = zend_persist_attributes(ce->attributes); - } zend_hash_persist(&ce->properties_info); ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) { zend_property_info *prop = Z_PTR(p->val); @@ -894,13 +967,8 @@ static void zend_persist_class_entry(zval *zv) size_t size = sizeof(zend_property_info *) * ce->default_properties_count; ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED); - if (ZCG(is_immutable_class)) { - ce->properties_info_table = zend_shared_memdup( - ce->properties_info_table, size); - } else { - ce->properties_info_table = zend_shared_memdup_arena( - ce->properties_info_table, size); - } + ce->properties_info_table = zend_shared_memdup( + ce->properties_info_table, size); for (i = 0; i < ce->default_properties_count; i++) { if (ce->properties_info_table[i]) { @@ -913,6 +981,36 @@ static void zend_persist_class_entry(zval *zv) } } + if (ce->iterator_funcs_ptr) { + ce->iterator_funcs_ptr = zend_shared_memdup(ce->iterator_funcs_ptr, sizeof(zend_class_iterator_funcs)); + } + + if (ce->ce_flags & ZEND_ACC_CACHED) { + return ce; + } + + ce->ce_flags |= ZEND_ACC_CACHED; + + if (ce->info.user.filename) { + zend_accel_store_string(ce->info.user.filename); + } + + if (ce->info.user.doc_comment) { + if (ZCG(accel_directives).save_comments) { + zend_accel_store_interned_string(ce->info.user.doc_comment); + } else { + if (!zend_shared_alloc_get_xlat_entry(ce->info.user.doc_comment)) { + zend_shared_alloc_register_xlat_entry(ce->info.user.doc_comment, ce->info.user.doc_comment); + zend_string_release_ex(ce->info.user.doc_comment, 0); + } + ce->info.user.doc_comment = NULL; + } + } + + if (ce->attributes) { + ce->attributes = zend_persist_attributes(ce->attributes); + } + if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_LINKED)) { uint32_t i = 0; @@ -973,13 +1071,15 @@ static void zend_persist_class_entry(zval *zv) } } - if (ce->iterator_funcs_ptr) { - ce->iterator_funcs_ptr = zend_shared_memdup(ce->iterator_funcs_ptr, sizeof(zend_class_iterator_funcs)); + if (ce->backed_enum_table) { + ce->backed_enum_table = zend_persist_backed_enum_table(ce->backed_enum_table); } } + + return ce; } -static void zend_update_parent_ce(zend_class_entry *ce) +void zend_update_parent_ce(zend_class_entry *ce) { if (ce->ce_flags & ZEND_ACC_LINKED) { if (ce->parent) { @@ -1144,7 +1244,7 @@ static void zend_accel_persist_class_table(HashTable *class_table) ZEND_HASH_FOREACH_BUCKET(class_table, p) { ZEND_ASSERT(p->key != NULL); zend_accel_store_interned_string(p->key); - zend_persist_class_entry(&p->val); + Z_CE(p->val) = zend_persist_class_entry(Z_CE(p->val)); } ZEND_HASH_FOREACH_END(); ZEND_HASH_FOREACH_BUCKET(class_table, p) { if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) { @@ -1167,7 +1267,7 @@ static void zend_persist_warnings(zend_persistent_script *script) { } } -zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, const char **key, unsigned int key_length, int for_shm) +zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, int for_shm) { Bucket *p; @@ -1176,10 +1276,6 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ script = zend_shared_memdup_free(script, sizeof(zend_persistent_script)); - if (key && *key) { - *key = zend_shared_memdup_put((void*)*key, key_length + 1); - } - script->corrupted = 0; ZCG(current_persistent_script) = script; @@ -1197,9 +1293,6 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ #endif - script->arena_mem = ZCG(arena_mem) = ZCG(mem); - ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size); - #ifdef HAVE_JIT if (JIT_G(on) && for_shm) { zend_jit_unprotect(); @@ -1216,6 +1309,12 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script zend_persist_op_array(&p->val); } ZEND_HASH_FOREACH_END(); zend_persist_op_array_ex(&script->script.main_op_array, script); + if (!script->corrupted) { + ZEND_MAP_PTR_INIT(script->script.main_op_array.run_time_cache, NULL); + if (script->script.main_op_array.static_variables) { + ZEND_MAP_PTR_NEW(script->script.main_op_array.static_variables_ptr); + } + } zend_persist_warnings(script); if (for_shm) { |