123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353 |
- /*
- +----------------------------------------------------------------------+
- | Zend OPcache |
- +----------------------------------------------------------------------+
- | Copyright (c) The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | https://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Andi Gutmans <andi@php.net> |
- | Zeev Suraski <zeev@php.net> |
- | Stanislav Malyshev <stas@zend.com> |
- | Dmitry Stogov <dmitry@php.net> |
- +----------------------------------------------------------------------+
- */
- #include "zend.h"
- #include "ZendAccelerator.h"
- #include "zend_persist.h"
- #include "zend_extensions.h"
- #include "zend_shared_alloc.h"
- #include "zend_vm.h"
- #include "zend_constants.h"
- #include "zend_operators.h"
- #include "zend_interfaces.h"
- #include "zend_attributes.h"
- #ifdef HAVE_JIT
- # include "Optimizer/zend_func_info.h"
- # include "jit/zend_jit.h"
- #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 { \
- GC_TYPE_INFO(str) = GC_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << GC_FLAGS_SHIFT); \
- } \
- } while (0)
- #define zend_accel_store_string(str) do { \
- zend_string *new_str = zend_shared_alloc_get_xlat_entry(str); \
- if (new_str) { \
- zend_string_release_ex(str, 0); \
- str = new_str; \
- } else { \
- new_str = zend_shared_memdup_put((void*)str, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \
- zend_string_release_ex(str, 0); \
- str = new_str; \
- zend_string_hash_val(str); \
- zend_set_str_gc_flags(str); \
- } \
- } while (0)
- #define zend_accel_memdup_string(str) do { \
- zend_string *new_str = zend_shared_alloc_get_xlat_entry(str); \
- if (new_str) { \
- str = new_str; \
- } else { \
- new_str = zend_shared_memdup_put((void*)str, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \
- str = new_str; \
- zend_string_hash_val(str); \
- zend_set_str_gc_flags(str); \
- } \
- } while (0)
- #define zend_accel_store_interned_string(str) do { \
- if (!IS_ACCEL_INTERNED(str)) { \
- zend_accel_store_string(str); \
- } \
- } while (0)
- #define zend_accel_memdup_interned_string(str) do { \
- if (!IS_ACCEL_INTERNED(str)) { \
- zend_accel_memdup_string(str); \
- } \
- } while (0)
- 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};
- static void zend_hash_persist(HashTable *ht)
- {
- uint32_t idx, nIndex;
- Bucket *p;
- HT_FLAGS(ht) |= HASH_FLAG_STATIC_KEYS;
- ht->pDestructor = NULL;
- ht->nInternalPointer = 0;
- 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) {
- void *data = HT_GET_DATA_ADDR(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 */
- void *old_data = HT_GET_DATA_ADDR(ht);
- Bucket *old_buckets = ht->arData;
- uint32_t hash_size;
- 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) + 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));
- if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
- efree(old_data);
- }
- /* rehash */
- for (idx = 0; idx < ht->nNumUsed; idx++) {
- p = ht->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- nIndex = p->h | ht->nTableMask;
- Z_NEXT(p->val) = HT_HASH(ht, nIndex);
- HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
- }
- } else {
- void *data = ZCG(mem);
- void *old_data = HT_GET_DATA_ADDR(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));
- if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
- efree(old_data);
- }
- HT_SET_DATA_ADDR(ht, data);
- }
- }
- static zend_ast *zend_persist_ast(zend_ast *ast)
- {
- uint32_t i;
- zend_ast *node;
- if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
- zend_ast_zval *copy = zend_shared_memdup(ast, sizeof(zend_ast_zval));
- zend_persist_zval(©->val);
- node = (zend_ast *) copy;
- } else if (zend_ast_is_list(ast)) {
- zend_ast_list *list = zend_ast_get_list(ast);
- zend_ast_list *copy = zend_shared_memdup(ast,
- sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
- for (i = 0; i < list->children; i++) {
- if (copy->child[i]) {
- copy->child[i] = zend_persist_ast(copy->child[i]);
- }
- }
- node = (zend_ast *) copy;
- } else {
- uint32_t children = zend_ast_get_num_children(ast);
- node = zend_shared_memdup(ast, sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
- for (i = 0; i < children; i++) {
- if (node->child[i]) {
- node->child[i] = zend_persist_ast(node->child[i]);
- }
- }
- }
- return node;
- }
- static void zend_persist_zval(zval *z)
- {
- void *new_ptr;
- switch (Z_TYPE_P(z)) {
- case IS_STRING:
- zend_accel_store_interned_string(Z_STR_P(z));
- Z_TYPE_FLAGS_P(z) = 0;
- break;
- case IS_ARRAY:
- new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(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));
- } 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);
- }
- break;
- case IS_CONSTANT_AST:
- new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
- if (new_ptr) {
- Z_AST_P(z) = new_ptr;
- Z_TYPE_FLAGS_P(z) = 0;
- } 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));
- Z_TYPE_FLAGS_P(z) = 0;
- GC_SET_REFCOUNT(Z_COUNTED_P(z), 1);
- efree(old_ref);
- }
- break;
- default:
- ZEND_ASSERT(Z_TYPE_P(z) < IS_STRING);
- break;
- }
- }
- static HashTable *zend_persist_attributes(HashTable *attributes)
- {
- uint32_t i;
- zval *v;
- if (!ZCG(current_persistent_script)->corrupted && zend_accel_in_shm(attributes)) {
- return attributes;
- }
- /* Attributes for trait properties may be shared if preloading is used. */
- HashTable *xlat = zend_shared_alloc_get_xlat_entry(attributes);
- if (xlat) {
- return xlat;
- }
- 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_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);
- }
- ZVAL_PTR(v, copy);
- } ZEND_HASH_FOREACH_END();
- 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_class_name_map_ptr(zend_string *type_name)
- {
- uint32_t ret;
- if (zend_string_equals_literal_ci(type_name, "self") ||
- zend_string_equals_literal_ci(type_name, "parent")) {
- return 0;
- }
- /* We use type.name.gc.refcount to keep map_ptr of corresponding type */
- if (ZSTR_HAS_CE_CACHE(type_name)) {
- return GC_REFCOUNT(type_name);
- }
- if ((GC_FLAGS(type_name) & GC_IMMUTABLE)
- && (GC_FLAGS(type_name) & IS_STR_PERMANENT)) {
- do {
- ret = ZEND_MAP_PTR_NEW_OFFSET();
- } while (ret <= 2);
- GC_SET_REFCOUNT(type_name, ret);
- GC_ADD_FLAGS(type_name, IS_STR_CLASS_NAME_MAP_PTR);
- return ret;
- }
- return 0;
- }
- 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, zend_class_entry *scope) {
- if (ZEND_TYPE_HAS_LIST(*type)) {
- zend_type_list *list = ZEND_TYPE_LIST(*type);
- if (ZEND_TYPE_USES_ARENA(*type)) {
- 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));
- }
- ZEND_TYPE_SET_PTR(*type, list);
- }
- zend_type *single_type;
- ZEND_TYPE_FOREACH(*type, single_type) {
- if (ZEND_TYPE_HAS_NAME(*single_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) {
- zend_accel_get_class_name_map_ptr(type_name);
- }
- }
- } ZEND_TYPE_FOREACH_END();
- }
- static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script)
- {
- zend_op *persist_ptr;
- zval *orig_literals = NULL;
- if (op_array->refcount && --(*op_array->refcount) == 0) {
- efree(op_array->refcount);
- }
- op_array->refcount = NULL;
- if (main_persistent_script) {
- zend_execute_data *orig_execute_data = EG(current_execute_data);
- zend_execute_data fake_execute_data;
- zval *offset;
- memset(&fake_execute_data, 0, sizeof(fake_execute_data));
- fake_execute_data.func = (zend_function*)op_array;
- EG(current_execute_data) = &fake_execute_data;
- if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
- main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset);
- }
- EG(current_execute_data) = orig_execute_data;
- }
- if (op_array->function_name) {
- zend_string *old_name = op_array->function_name;
- zend_accel_store_interned_string(op_array->function_name);
- /* Remember old function name, so it can be released multiple times if shared. */
- if (op_array->function_name != old_name
- && !zend_shared_alloc_get_xlat_entry(&op_array->function_name)) {
- zend_shared_alloc_register_xlat_entry(&op_array->function_name, old_name);
- }
- }
- if (op_array->scope) {
- zend_class_entry *scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
- if (scope) {
- op_array->scope = scope;
- }
- if (op_array->prototype) {
- zend_function *ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype);
- if (ptr) {
- op_array->prototype = ptr;
- }
- }
- 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);
- }
- 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->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->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) {
- 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);
- }
- if (op_array->dynamic_func_defs) {
- op_array->dynamic_func_defs = zend_shared_alloc_get_xlat_entry(op_array->dynamic_func_defs);
- ZEND_ASSERT(op_array->dynamic_func_defs != 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->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);
- 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) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT);
- }
- if (op_array->literals) {
- zval *p, *end;
- orig_literals = op_array->literals;
- #if ZEND_USE_ABS_CONST_ADDR
- p = zend_shared_memdup_put_free(op_array->literals, sizeof(zval) * op_array->last_literal);
- #else
- p = zend_shared_memdup_put(op_array->literals, sizeof(zval) * op_array->last_literal);
- #endif
- end = p + op_array->last_literal;
- op_array->literals = p;
- while (p < end) {
- zend_persist_zval(p);
- p++;
- }
- }
- {
- zend_op *new_opcodes = zend_shared_memdup_put(op_array->opcodes, sizeof(zend_op) * op_array->last);
- zend_op *opline = new_opcodes;
- zend_op *end = new_opcodes + op_array->last;
- int offset = 0;
- for (; opline < end ; opline++, offset++) {
- #if ZEND_USE_ABS_CONST_ADDR
- if (opline->op1_type == IS_CONST) {
- opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
- if (opline->opcode == ZEND_SEND_VAL
- || opline->opcode == ZEND_SEND_VAL_EX
- || opline->opcode == ZEND_QM_ASSIGN) {
- /* Update handlers to eliminate REFCOUNTED check */
- zend_vm_set_opcode_handler_ex(opline, 1 << Z_TYPE_P(opline->op1.zv), 0, 0);
- }
- }
- if (opline->op2_type == IS_CONST) {
- opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
- }
- #else
- if (opline->op1_type == IS_CONST) {
- opline->op1.constant =
- (char*)(op_array->literals +
- ((zval*)((char*)(op_array->opcodes + (opline - new_opcodes)) +
- (int32_t)opline->op1.constant) - orig_literals)) -
- (char*)opline;
- if (opline->opcode == ZEND_SEND_VAL
- || opline->opcode == ZEND_SEND_VAL_EX
- || opline->opcode == ZEND_QM_ASSIGN) {
- zend_vm_set_opcode_handler_ex(opline, 0, 0, 0);
- }
- }
- if (opline->op2_type == IS_CONST) {
- opline->op2.constant =
- (char*)(op_array->literals +
- ((zval*)((char*)(op_array->opcodes + (opline - new_opcodes)) +
- (int32_t)opline->op2.constant) - orig_literals)) -
- (char*)opline;
- }
- #endif
- #if ZEND_USE_ABS_JMP_ADDR
- if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
- /* fix jumps to point to new array */
- switch (opline->opcode) {
- case ZEND_JMP:
- case ZEND_FAST_CALL:
- opline->op1.jmp_addr = &new_opcodes[opline->op1.jmp_addr - op_array->opcodes];
- break;
- case ZEND_JMPZNZ:
- /* relative extended_value don't have to be changed */
- /* break omitted intentionally */
- case ZEND_JMPZ:
- case ZEND_JMPNZ:
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- case ZEND_JMP_SET:
- case ZEND_COALESCE:
- case ZEND_FE_RESET_R:
- case ZEND_FE_RESET_RW:
- case ZEND_ASSERT_CHECK:
- case ZEND_JMP_NULL:
- opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes];
- break;
- case ZEND_CATCH:
- if (!(opline->extended_value & ZEND_LAST_CATCH)) {
- opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes];
- }
- break;
- case ZEND_FE_FETCH_R:
- case ZEND_FE_FETCH_RW:
- case ZEND_SWITCH_LONG:
- case ZEND_SWITCH_STRING:
- case ZEND_MATCH:
- /* relative extended_value don't have to be changed */
- break;
- }
- }
- #endif
- }
- efree(op_array->opcodes);
- op_array->opcodes = new_opcodes;
- }
- if (op_array->filename) {
- zend_accel_store_string(op_array->filename);
- }
- if (op_array->arg_info) {
- zend_arg_info *arg_info = op_array->arg_info;
- uint32_t num_args = op_array->num_args;
- uint32_t i;
- if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
- arg_info--;
- num_args++;
- }
- if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
- num_args++;
- }
- arg_info = zend_shared_memdup_put_free(arg_info, sizeof(zend_arg_info) * num_args);
- for (i = 0; i < num_args; i++) {
- if (arg_info[i].name) {
- zend_accel_store_interned_string(arg_info[i].name);
- }
- zend_persist_type(&arg_info[i].type, op_array->scope);
- }
- 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_memdup_put_free(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
- }
- if (op_array->doc_comment) {
- if (ZCG(accel_directives).save_comments) {
- zend_accel_store_interned_string(op_array->doc_comment);
- } else {
- zend_string_release_ex(op_array->doc_comment, 0);
- op_array->doc_comment = NULL;
- }
- }
- if (op_array->attributes) {
- op_array->attributes = zend_persist_attributes(op_array->attributes);
- }
- if (op_array->try_catch_array) {
- op_array->try_catch_array = zend_shared_memdup_put_free(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
- }
- if (op_array->vars) {
- int i;
- op_array->vars = zend_shared_memdup_put_free(op_array->vars, sizeof(zend_string*) * op_array->last_var);
- for (i = 0; i < op_array->last_var; i++) {
- zend_accel_store_interned_string(op_array->vars[i]);
- }
- }
- 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))));
- }
- 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);
- 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);
- }
- }
- #ifdef HAVE_JIT
- if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS) {
- zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
- }
- #endif
- } else {
- /* 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, zend_class_entry *ce)
- {
- zend_op_array *op_array = Z_PTR_P(zv);
- zend_op_array *old_op_array;
- if (op_array->type != ZEND_USER_FUNCTION) {
- ZEND_ASSERT(op_array->type == ZEND_INTERNAL_FUNCTION);
- if (op_array->fn_flags & ZEND_ACC_ARENA_ALLOCATED) {
- old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
- if (old_op_array) {
- Z_PTR_P(zv) = old_op_array;
- } else {
- op_array = Z_PTR_P(zv) = zend_shared_memdup_put(op_array, sizeof(zend_internal_function));
- if (op_array->scope) {
- void *persist_ptr;
- if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->scope))) {
- op_array->scope = (zend_class_entry*)persist_ptr;
- }
- if (op_array->prototype) {
- if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
- op_array->prototype = (zend_function*)persist_ptr;
- }
- }
- }
- }
- }
- return;
- }
- if ((op_array->fn_flags & ZEND_ACC_IMMUTABLE)
- && !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;
- if (op_array->refcount && --(*op_array->refcount) == 0) {
- efree(op_array->refcount);
- }
- /* If op_array is shared, the function name refcount is still incremented for each use,
- * so we need to release it here. We remembered the original function name in xlat. */
- zend_string *old_function_name =
- zend_shared_alloc_get_xlat_entry(&old_op_array->function_name);
- if (old_function_name) {
- zend_string_release_ex(old_function_name, 0);
- }
- return;
- }
- 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 (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
- op_array->fn_flags |= ZEND_ACC_IMMUTABLE;
- if (ce->ce_flags & ZEND_ACC_LINKED) {
- 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, 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;
- prop = zend_shared_memdup_put(prop, sizeof(zend_property_info));
- ce = zend_shared_alloc_get_xlat_entry(prop->ce);
- if (ce) {
- prop->ce = ce;
- }
- zend_accel_store_interned_string(prop->name);
- if (prop->doc_comment) {
- if (ZCG(accel_directives).save_comments) {
- zend_accel_store_interned_string(prop->doc_comment);
- } else {
- if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
- zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
- }
- zend_string_release_ex(prop->doc_comment, 0);
- prop->doc_comment = NULL;
- }
- }
- if (prop->attributes) {
- prop->attributes = zend_persist_attributes(prop->attributes);
- }
- zend_persist_type(&prop->type, ce);
- return prop;
- }
- static void zend_persist_class_constant(zval *zv)
- {
- zend_class_constant *c = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv));
- zend_class_entry *ce;
- if (c) {
- Z_PTR_P(zv) = c;
- return;
- } else if (!ZCG(current_persistent_script)->corrupted
- && zend_accel_in_shm(Z_PTR_P(zv))) {
- return;
- }
- 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) {
- c->ce = ce;
- }
- if (c->doc_comment) {
- if (ZCG(accel_directives).save_comments) {
- zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
- if (doc_comment) {
- c->doc_comment = doc_comment;
- } else {
- zend_accel_store_interned_string(c->doc_comment);
- }
- } else {
- zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
- if (!doc_comment) {
- zend_shared_alloc_register_xlat_entry(c->doc_comment, c->doc_comment);
- zend_string_release_ex(c->doc_comment, 0);
- }
- c->doc_comment = NULL;
- }
- }
- if (c->attributes) {
- c->attributes = zend_persist_attributes(c->attributes);
- }
- }
- zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce)
- {
- Bucket *p;
- 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) {
- return new_ce;
- }
- ce = zend_shared_memdup_put(ce, sizeof(zend_class_entry));
- if (EXPECTED(!ZCG(current_persistent_script)->corrupted)) {
- ce->ce_flags |= ZEND_ACC_IMMUTABLE;
- if ((ce->ce_flags & ZEND_ACC_LINKED)
- && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
- ZEND_MAP_PTR_NEW(ce->mutable_data);
- } else {
- ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
- }
- } else {
- ce->ce_flags |= ZEND_ACC_FILE_CACHED;
- }
- ce->inheritance_cache = NULL;
- if (!(ce->ce_flags & ZEND_ACC_CACHED)) {
- if (ZSTR_HAS_CE_CACHE(ce->name)) {
- ZSTR_SET_CE_CACHE_EX(ce->name, NULL, 0);
- }
- zend_accel_store_interned_string(ce->name);
- if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS)
- && !ZCG(current_persistent_script)->corrupted) {
- zend_accel_get_class_name_map_ptr(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, ce);
- } ZEND_HASH_FOREACH_END();
- HT_FLAGS(&ce->function_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
- if (ce->default_properties_table) {
- int i;
- ce->default_properties_table = zend_shared_memdup_free(ce->default_properties_table, sizeof(zval) * ce->default_properties_count);
- for (i = 0; i < ce->default_properties_count; i++) {
- zend_persist_zval(&ce->default_properties_table[i]);
- }
- }
- 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);
- /* Persist only static properties in this class.
- * Static properties from parent classes will be handled in class_copy_ctor */
- i = (ce->parent && (ce->ce_flags & ZEND_ACC_LINKED)) ? ce->parent->default_static_members_count : 0;
- for (; i < ce->default_static_members_count; i++) {
- zend_persist_zval(&ce->default_static_members_table[i]);
- }
- if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
- 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);
- }
- }
- }
- 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);
- zend_hash_persist(&ce->properties_info);
- ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) {
- zend_property_info *prop = Z_PTR(p->val);
- ZEND_ASSERT(p->key != NULL);
- zend_accel_store_interned_string(p->key);
- if (prop->ce == orig_ce) {
- Z_PTR(p->val) = zend_persist_property_info(prop);
- } else {
- prop = zend_shared_alloc_get_xlat_entry(prop);
- if (prop) {
- Z_PTR(p->val) = prop;
- } else {
- /* This can happen if preloading is used and we inherit a property from an
- * internal class. In that case we should keep pointing to the internal
- * property, without any adjustments. */
- }
- }
- } ZEND_HASH_FOREACH_END();
- HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
- if (ce->properties_info_table) {
- int i;
- size_t size = sizeof(zend_property_info *) * ce->default_properties_count;
- ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
- 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]) {
- zend_property_info *prop_info = zend_shared_alloc_get_xlat_entry(
- ce->properties_info_table[i]);
- if (prop_info) {
- ce->properties_info_table[i] = prop_info;
- }
- }
- }
- }
- 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;
- for (i = 0; i < ce->num_interfaces; i++) {
- zend_accel_store_interned_string(ce->interface_names[i].name);
- zend_accel_store_interned_string(ce->interface_names[i].lc_name);
- }
- ce->interface_names = zend_shared_memdup_free(ce->interface_names, sizeof(zend_class_name) * ce->num_interfaces);
- }
- if (ce->num_traits) {
- uint32_t i = 0;
- for (i = 0; i < ce->num_traits; i++) {
- zend_accel_store_interned_string(ce->trait_names[i].name);
- zend_accel_store_interned_string(ce->trait_names[i].lc_name);
- }
- ce->trait_names = zend_shared_memdup_free(ce->trait_names, sizeof(zend_class_name) * ce->num_traits);
- i = 0;
- if (ce->trait_aliases) {
- while (ce->trait_aliases[i]) {
- if (ce->trait_aliases[i]->trait_method.method_name) {
- zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method.method_name);
- }
- if (ce->trait_aliases[i]->trait_method.class_name) {
- zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method.class_name);
- }
- if (ce->trait_aliases[i]->alias) {
- zend_accel_store_interned_string(ce->trait_aliases[i]->alias);
- }
- ce->trait_aliases[i] = zend_shared_memdup_free(ce->trait_aliases[i], sizeof(zend_trait_alias));
- i++;
- }
- ce->trait_aliases = zend_shared_memdup_free(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1));
- }
- if (ce->trait_precedences) {
- uint32_t j;
- i = 0;
- while (ce->trait_precedences[i]) {
- zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method.method_name);
- zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method.class_name);
- for (j = 0; j < ce->trait_precedences[i]->num_excludes; j++) {
- zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_class_names[j]);
- }
- ce->trait_precedences[i] = zend_shared_memdup_free(ce->trait_precedences[i], sizeof(zend_trait_precedence) + (ce->trait_precedences[i]->num_excludes - 1) * sizeof(zend_string*));
- i++;
- }
- ce->trait_precedences = zend_shared_memdup_free(
- ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
- }
- }
- if (ce->backed_enum_table) {
- ce->backed_enum_table = zend_persist_backed_enum_table(ce->backed_enum_table);
- }
- }
- return ce;
- }
- void zend_update_parent_ce(zend_class_entry *ce)
- {
- if (ce->ce_flags & ZEND_ACC_LINKED) {
- if (ce->parent) {
- int i, end;
- zend_class_entry *parent = ce->parent;
- if (parent->type == ZEND_USER_CLASS) {
- zend_class_entry *p = zend_shared_alloc_get_xlat_entry(parent);
- if (p) {
- ce->parent = parent = p;
- }
- }
- /* Create indirections to static properties from parent classes */
- i = parent->default_static_members_count - 1;
- while (parent && parent->default_static_members_table) {
- end = parent->parent ? parent->parent->default_static_members_count : 0;
- for (; i >= end; i--) {
- zval *p = &ce->default_static_members_table[i];
- ZVAL_INDIRECT(p, &parent->default_static_members_table[i]);
- }
- parent = parent->parent;
- }
- }
- if (ce->num_interfaces) {
- uint32_t i = 0;
- ce->interfaces = zend_shared_memdup_free(ce->interfaces, sizeof(zend_class_entry*) * ce->num_interfaces);
- for (i = 0; i < ce->num_interfaces; i++) {
- if (ce->interfaces[i]->type == ZEND_USER_CLASS) {
- zend_class_entry *tmp = zend_shared_alloc_get_xlat_entry(ce->interfaces[i]);
- if (tmp != NULL) {
- ce->interfaces[i] = tmp;
- }
- }
- }
- }
- if (ce->iterator_funcs_ptr) {
- memset(ce->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
- if (zend_class_implements_interface(ce, zend_ce_aggregate)) {
- ce->iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&ce->function_table, "getiterator", sizeof("getiterator") - 1);
- }
- if (zend_class_implements_interface(ce, zend_ce_iterator)) {
- ce->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&ce->function_table, "rewind", sizeof("rewind") - 1);
- ce->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&ce->function_table, "valid", sizeof("valid") - 1);
- ce->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&ce->function_table, "key", sizeof("key") - 1);
- ce->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&ce->function_table, "current", sizeof("current") - 1);
- ce->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&ce->function_table, "next", sizeof("next") - 1);
- }
- }
- }
- /* update methods */
- if (ce->constructor) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->constructor);
- if (tmp != NULL) {
- ce->constructor = tmp;
- }
- }
- if (ce->destructor) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->destructor);
- if (tmp != NULL) {
- ce->destructor = tmp;
- }
- }
- if (ce->clone) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->clone);
- if (tmp != NULL) {
- ce->clone = tmp;
- }
- }
- if (ce->__get) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__get);
- if (tmp != NULL) {
- ce->__get = tmp;
- }
- }
- if (ce->__set) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__set);
- if (tmp != NULL) {
- ce->__set = tmp;
- }
- }
- if (ce->__call) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__call);
- if (tmp != NULL) {
- ce->__call = tmp;
- }
- }
- if (ce->__serialize) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__serialize);
- if (tmp != NULL) {
- ce->__serialize = tmp;
- }
- }
- if (ce->__unserialize) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__unserialize);
- if (tmp != NULL) {
- ce->__unserialize = tmp;
- }
- }
- if (ce->__isset) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__isset);
- if (tmp != NULL) {
- ce->__isset = tmp;
- }
- }
- if (ce->__unset) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__unset);
- if (tmp != NULL) {
- ce->__unset = tmp;
- }
- }
- if (ce->__tostring) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__tostring);
- if (tmp != NULL) {
- ce->__tostring = tmp;
- }
- }
- if (ce->__callstatic) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
- if (tmp != NULL) {
- ce->__callstatic = tmp;
- }
- }
- if (ce->__debugInfo) {
- zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
- if (tmp != NULL) {
- ce->__debugInfo = tmp;
- }
- }
- }
- static void zend_accel_persist_class_table(HashTable *class_table)
- {
- Bucket *p;
- zend_class_entry *ce;
- #ifdef HAVE_JIT
- bool orig_jit_on = JIT_G(on);
- JIT_G(on) = 0;
- #endif
- zend_hash_persist(class_table);
- ZEND_HASH_FOREACH_BUCKET(class_table, p) {
- ZEND_ASSERT(p->key != NULL);
- zend_accel_store_interned_string(p->key);
- 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)) {
- ce = Z_PTR(p->val);
- zend_update_parent_ce(ce);
- }
- } ZEND_HASH_FOREACH_END();
- #ifdef HAVE_JIT
- JIT_G(on) = orig_jit_on;
- if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS &&
- !ZCG(current_persistent_script)->corrupted) {
- zend_op_array *op_array;
- ZEND_HASH_FOREACH_BUCKET(class_table, p) {
- if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
- ce = Z_PTR(p->val);
- ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
- if (op_array->type == ZEND_USER_FUNCTION) {
- if (op_array->scope == ce
- && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
- zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
- for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
- zend_jit_op_array(op_array->dynamic_func_defs[i], ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
- }
- }
- }
- } ZEND_HASH_FOREACH_END();
- }
- } ZEND_HASH_FOREACH_END();
- ZEND_HASH_FOREACH_BUCKET(class_table, p) {
- if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
- ce = Z_PTR(p->val);
- ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
- if (op_array->type == ZEND_USER_FUNCTION) {
- if ((op_array->scope != ce
- || (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))
- && (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC
- || JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST
- || JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS
- || JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE)) {
- void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
- if (jit_extension) {
- ZEND_SET_FUNC_INFO(op_array, jit_extension);
- }
- }
- }
- } ZEND_HASH_FOREACH_END();
- }
- } ZEND_HASH_FOREACH_END();
- }
- #endif
- }
- zend_error_info **zend_persist_warnings(uint32_t num_warnings, zend_error_info **warnings) {
- if (warnings) {
- warnings = zend_shared_memdup_free(warnings, num_warnings * sizeof(zend_error_info *));
- for (uint32_t i = 0; i < num_warnings; i++) {
- warnings[i] = zend_shared_memdup_free(warnings[i], sizeof(zend_error_info));
- zend_accel_store_string(warnings[i]->filename);
- zend_accel_store_string(warnings[i]->message);
- }
- }
- return warnings;
- }
- zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, int for_shm)
- {
- Bucket *p;
- script->mem = ZCG(mem);
- ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
- script = zend_shared_memdup_free(script, sizeof(zend_persistent_script));
- script->corrupted = 0;
- ZCG(current_persistent_script) = script;
- if (!for_shm) {
- /* script is not going to be saved in SHM */
- script->corrupted = 1;
- }
- zend_accel_store_interned_string(script->script.filename);
- #if defined(__AVX__) || defined(__SSE2__)
- /* Align to 64-byte boundary */
- ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
- #else
- ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
- #endif
- #ifdef HAVE_JIT
- if (JIT_G(on) && for_shm) {
- zend_jit_unprotect();
- }
- #endif
- 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_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);
- 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);
- }
- #ifdef HAVE_JIT
- if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS) {
- zend_jit_op_array(&script->script.main_op_array, &script->script);
- }
- #endif
- }
- script->warnings = zend_persist_warnings(script->num_warnings, script->warnings);
- if (for_shm) {
- ZCSG(map_ptr_last) = CG(map_ptr_last);
- }
- #ifdef HAVE_JIT
- if (JIT_G(on) && for_shm) {
- if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_SCRIPT) {
- zend_jit_script(&script->script);
- }
- zend_jit_protect();
- }
- #endif
- script->corrupted = 0;
- ZCG(current_persistent_script) = NULL;
- return script;
- }
|