diff options
Diffstat (limited to 'ext/opcache/zend_persist.c')
-rw-r--r-- | ext/opcache/zend_persist.c | 317 |
1 files changed, 126 insertions, 191 deletions
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 83171e2d75..16d07e689f 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -83,7 +83,7 @@ static void zend_persist_zval(zval *z); static const uint32_t uninitialized_bucket[-HT_MIN_MASK] = {HT_INVALID_IDX, HT_INVALID_IDX}; -static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement) +static void zend_hash_persist(HashTable *ht) { uint32_t idx, nIndex; Bucket *p; @@ -115,19 +115,15 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement void *data = HT_GET_DATA_ADDR(ht); data = zend_shared_memdup_free(data, HT_USED_SIZE(ht)); HT_SET_DATA_ADDR(ht, data); - } else if (ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) { + } else if (ht->nNumUsed > HT_MIN_SIZE && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) { /* compact table */ void *old_data = HT_GET_DATA_ADDR(ht); Bucket *old_buckets = ht->arData; uint32_t hash_size; - if (ht->nNumUsed <= HT_MIN_SIZE) { - hash_size = HT_MIN_SIZE * 2; - } else { - hash_size = (uint32_t)(-(int32_t)ht->nTableMask); - while (hash_size >> 2 > ht->nNumUsed) { - hash_size >>= 1; - } + hash_size = (uint32_t)(-(int32_t)ht->nTableMask); + while (hash_size >> 2 > ht->nNumUsed) { + hash_size >>= 1; } ht->nTableMask = (uint32_t)(-(int32_t)hash_size); ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ @@ -137,23 +133,14 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket)); efree(old_data); + /* rehash */ for (idx = 0; idx < ht->nNumUsed; idx++) { p = ht->arData + idx; if (Z_TYPE(p->val) == IS_UNDEF) continue; - - /* persist bucket and key */ - if (p->key) { - zend_accel_store_interned_string(p->key); - } - - /* persist the data itself */ - pPersistElement(&p->val); - nIndex = p->h | ht->nTableMask; Z_NEXT(p->val) = HT_HASH(ht, nIndex); HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx); } - return; } else { void *data = ZCG(mem); void *old_data = HT_GET_DATA_ADDR(ht); @@ -164,107 +151,6 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement efree(old_data); HT_SET_DATA_ADDR(ht, data); } - - for (idx = 0; idx < ht->nNumUsed; idx++) { - p = ht->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - - /* persist bucket and key */ - if (p->key) { - zend_accel_store_interned_string(p->key); - } - - /* persist the data itself */ - pPersistElement(&p->val); - } -} - -static void zend_hash_persist_immutable(HashTable *ht) -{ - uint32_t idx, nIndex; - Bucket *p; - - HT_FLAGS(ht) |= HASH_FLAG_STATIC_KEYS; - ht->pDestructor = NULL; - - if (HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) { - if (EXPECTED(!ZCG(current_persistent_script)->corrupted)) { - HT_SET_DATA_ADDR(ht, &ZCSG(uninitialized_bucket)); - } else { - HT_SET_DATA_ADDR(ht, &uninitialized_bucket); - } - return; - } - if (ht->nNumUsed == 0) { - efree(HT_GET_DATA_ADDR(ht)); - ht->nTableMask = HT_MIN_MASK; - if (EXPECTED(!ZCG(current_persistent_script)->corrupted)) { - HT_SET_DATA_ADDR(ht, &ZCSG(uninitialized_bucket)); - } else { - HT_SET_DATA_ADDR(ht, &uninitialized_bucket); - } - HT_FLAGS(ht) |= HASH_FLAG_UNINITIALIZED; - return; - } - if (HT_FLAGS(ht) & HASH_FLAG_PACKED) { - HT_SET_DATA_ADDR(ht, zend_shared_memdup(HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht))); - } else if (ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) { - /* compact table */ - Bucket *old_buckets = ht->arData; - uint32_t hash_size; - - if (ht->nNumUsed <= HT_MIN_SIZE) { - hash_size = HT_MIN_SIZE * 2; - } else { - hash_size = (uint32_t)(-(int32_t)ht->nTableMask); - while (hash_size >> 2 > ht->nNumUsed) { - hash_size >>= 1; - } - } - ht->nTableMask = (uint32_t)(-(int32_t)hash_size); - ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ - HT_SET_DATA_ADDR(ht, ZCG(mem)); - ZCG(mem) = (void*)((char*)ZCG(mem) + (hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket))); - HT_HASH_RESET(ht); - memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket)); - - for (idx = 0; idx < ht->nNumUsed; idx++) { - p = ht->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - - /* persist bucket and key */ - if (p->key) { - zend_accel_memdup_interned_string(p->key); - } - - /* persist the data itself */ - zend_persist_zval(&p->val); - - nIndex = p->h | ht->nTableMask; - Z_NEXT(p->val) = HT_HASH(ht, nIndex); - HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx); - } - return; - } else { - void *data = ZCG(mem); - - 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, HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht)); - HT_SET_DATA_ADDR(ht, data); - } - for (idx = 0; idx < ht->nNumUsed; idx++) { - p = ht->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - - /* persist bucket and key */ - if (p->key) { - zend_accel_memdup_interned_string(p->key); - } - - /* persist the data itself */ - zend_persist_zval(&p->val); - } } static zend_ast *zend_persist_ast(zend_ast *ast) @@ -314,13 +200,27 @@ static void zend_persist_zval(zval *z) Z_ARR_P(z) = new_ptr; Z_TYPE_FLAGS_P(z) = 0; } 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_immutable(Z_ARRVAL_P(z)); + 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_persist_zval); + 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); @@ -378,21 +278,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc EG(current_execute_data) = orig_execute_data; } - if (op_array->static_variables) { - HashTable *stored = zend_shared_alloc_get_xlat_entry(op_array->static_variables); - - if (stored) { - op_array->static_variables = stored; - } else { - zend_hash_persist(op_array->static_variables, zend_persist_zval); - op_array->static_variables = zend_shared_memdup_put_free(op_array->static_variables, sizeof(HashTable)); - /* make immutable array */ - GC_SET_REFCOUNT(op_array->static_variables, 2); - GC_TYPE_INFO(op_array->static_variables) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << GC_FLAGS_SHIFT); - } - } - ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); - if (op_array->scope) { zend_class_entry *scope = zend_shared_alloc_get_xlat_entry(op_array->scope); @@ -406,61 +291,82 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc op_array->prototype = ptr; } } - } else { - /* "prototype" may be undefined if "scope" isn't set */ - op_array->prototype = NULL; - } - persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes); - if (persist_ptr) { - op_array->opcodes = persist_ptr; - if (op_array->literals) { - op_array->literals = zend_shared_alloc_get_xlat_entry(op_array->literals); - ZEND_ASSERT(op_array->literals != NULL); - } - if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) { - op_array->function_name = zend_shared_alloc_get_xlat_entry(op_array->function_name); - ZEND_ASSERT(op_array->function_name != NULL); - } - if (op_array->filename) { - op_array->filename = zend_shared_alloc_get_xlat_entry(op_array->filename); - ZEND_ASSERT(op_array->filename != NULL); - } - if (op_array->arg_info) { - zend_arg_info *arg_info = op_array->arg_info; - if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { - arg_info--; + persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes); + if (persist_ptr) { + op_array->opcodes = persist_ptr; + if (op_array->static_variables) { + op_array->static_variables = zend_shared_alloc_get_xlat_entry(op_array->static_variables); + ZEND_ASSERT(op_array->static_variables != NULL); } - arg_info = zend_shared_alloc_get_xlat_entry(arg_info); - ZEND_ASSERT(arg_info != NULL); - if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { - arg_info++; + 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); } - op_array->arg_info = arg_info; - } - if (op_array->live_range) { - op_array->live_range = zend_shared_alloc_get_xlat_entry(op_array->live_range); - ZEND_ASSERT(op_array->live_range != NULL); - } - if (op_array->doc_comment) { - if (ZCG(accel_directives).save_comments) { - op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment); - ZEND_ASSERT(op_array->doc_comment != NULL); - } else { - op_array->doc_comment = NULL; + if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) { + op_array->function_name = zend_shared_alloc_get_xlat_entry(op_array->function_name); + ZEND_ASSERT(op_array->function_name != NULL); } + if (op_array->filename) { + op_array->filename = zend_shared_alloc_get_xlat_entry(op_array->filename); + ZEND_ASSERT(op_array->filename != NULL); + } + if (op_array->arg_info) { + zend_arg_info *arg_info = op_array->arg_info; + if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + arg_info--; + } + arg_info = zend_shared_alloc_get_xlat_entry(arg_info); + ZEND_ASSERT(arg_info != NULL); + if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + arg_info++; + } + op_array->arg_info = arg_info; + } + if (op_array->live_range) { + op_array->live_range = zend_shared_alloc_get_xlat_entry(op_array->live_range); + ZEND_ASSERT(op_array->live_range != NULL); + } + if (op_array->doc_comment) { + if (ZCG(accel_directives).save_comments) { + op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment); + ZEND_ASSERT(op_array->doc_comment != NULL); + } else { + op_array->doc_comment = NULL; + } + } + if (op_array->try_catch_array) { + op_array->try_catch_array = zend_shared_alloc_get_xlat_entry(op_array->try_catch_array); + ZEND_ASSERT(op_array->try_catch_array != NULL); + } + if (op_array->vars) { + op_array->vars = zend_shared_alloc_get_xlat_entry(op_array->vars); + ZEND_ASSERT(op_array->vars != NULL); + } + ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem)))); + return; } - if (op_array->try_catch_array) { - op_array->try_catch_array = zend_shared_alloc_get_xlat_entry(op_array->try_catch_array); - ZEND_ASSERT(op_array->try_catch_array != NULL); - } - if (op_array->vars) { - op_array->vars = zend_shared_alloc_get_xlat_entry(op_array->vars); - ZEND_ASSERT(op_array->vars != NULL); - } - ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem)))); - return; + } else { + /* "prototype" may be undefined if "scope" isn't set */ + op_array->prototype = NULL; + } + + if (op_array->static_variables) { + Bucket *p; + + zend_hash_persist(op_array->static_variables); + ZEND_HASH_FOREACH_BUCKET(op_array->static_variables, p) { + ZEND_ASSERT(p->key != NULL); + zend_accel_store_interned_string(p->key); + zend_persist_zval(&p->val); + } ZEND_HASH_FOREACH_END(); + op_array->static_variables = zend_shared_memdup_put_free(op_array->static_variables, sizeof(HashTable)); + /* make immutable array */ + GC_SET_REFCOUNT(op_array->static_variables, 2); + GC_TYPE_INFO(op_array->static_variables) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << GC_FLAGS_SHIFT); } + ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); if (op_array->literals) { zval *p, *end; @@ -800,6 +706,7 @@ static void zend_persist_class_constant(zval *zv) static void zend_persist_class_entry(zval *zv) { + Bucket *p; zend_class_entry *ce = Z_PTR_P(zv); if (ce->type == ZEND_USER_CLASS) { @@ -818,7 +725,12 @@ static void zend_persist_class_entry(zval *zv) 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_persist_class_method); + 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_HASH_FOREACH_END(); HT_FLAGS(&ce->function_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS); if (ce->default_properties_table) { int i; @@ -847,7 +759,12 @@ static void zend_persist_class_entry(zval *zv) ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table); } - zend_hash_persist(&ce->constants_table, zend_persist_class_constant); + zend_hash_persist(&ce->constants_table); + ZEND_HASH_FOREACH_BUCKET(&ce->constants_table, p) { + ZEND_ASSERT(p->key != NULL); + zend_accel_store_interned_string(p->key); + zend_persist_class_constant(&p->val); + } ZEND_HASH_FOREACH_END(); HT_FLAGS(&ce->constants_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS); if (ce->info.user.filename) { @@ -865,7 +782,12 @@ static void zend_persist_class_entry(zval *zv) ce->info.user.doc_comment = NULL; } } - zend_hash_persist(&ce->properties_info, zend_persist_property_info); + zend_hash_persist(&ce->properties_info); + ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) { + ZEND_ASSERT(p->key != NULL); + zend_accel_store_interned_string(p->key); + zend_persist_property_info(&p->val); + } ZEND_HASH_FOREACH_END(); HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS); if (ce->properties_info_table) { @@ -1109,9 +1031,15 @@ static void zend_update_parent_ce(zend_class_entry *ce) static void zend_accel_persist_class_table(HashTable *class_table) { + Bucket *p; zend_class_entry *ce; - zend_hash_persist(class_table, zend_persist_class_entry); + zend_hash_persist(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); + } ZEND_HASH_FOREACH_END(); ZEND_HASH_FOREACH_PTR(class_table, ce) { zend_update_parent_ce(ce); } ZEND_HASH_FOREACH_END(); @@ -1119,6 +1047,8 @@ static void zend_accel_persist_class_table(HashTable *class_table) zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, const char **key, unsigned int key_length, int for_shm) { + Bucket *p; + script->mem = ZCG(mem); ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ @@ -1157,7 +1087,12 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script zend_map_ptr_extend(ZCSG(map_ptr_last)); zend_accel_persist_class_table(&script->script.class_table); - zend_hash_persist(&script->script.function_table, zend_persist_op_array); + zend_hash_persist(&script->script.function_table); + ZEND_HASH_FOREACH_BUCKET(&script->script.function_table, p) { + ZEND_ASSERT(p->key != NULL); + zend_accel_store_interned_string(p->key); + zend_persist_op_array(&p->val); + } ZEND_HASH_FOREACH_END(); zend_persist_op_array_ex(&script->script.main_op_array, script); ZCSG(map_ptr_last) = CG(map_ptr_last); |