zend_persist.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend OPcache |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | https://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@php.net> |
  16. | Zeev Suraski <zeev@php.net> |
  17. | Stanislav Malyshev <stas@zend.com> |
  18. | Dmitry Stogov <dmitry@php.net> |
  19. +----------------------------------------------------------------------+
  20. */
  21. #include "zend.h"
  22. #include "ZendAccelerator.h"
  23. #include "zend_persist.h"
  24. #include "zend_extensions.h"
  25. #include "zend_shared_alloc.h"
  26. #include "zend_vm.h"
  27. #include "zend_constants.h"
  28. #include "zend_operators.h"
  29. #include "zend_interfaces.h"
  30. #include "zend_attributes.h"
  31. #ifdef HAVE_JIT
  32. # include "Optimizer/zend_func_info.h"
  33. # include "jit/zend_jit.h"
  34. #endif
  35. #define zend_set_str_gc_flags(str) do { \
  36. GC_SET_REFCOUNT(str, 2); \
  37. if (file_cache_only) { \
  38. GC_TYPE_INFO(str) = GC_STRING | (IS_STR_INTERNED << GC_FLAGS_SHIFT); \
  39. } else { \
  40. GC_TYPE_INFO(str) = GC_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << GC_FLAGS_SHIFT); \
  41. } \
  42. } while (0)
  43. #define zend_accel_store_string(str) do { \
  44. zend_string *new_str = zend_shared_alloc_get_xlat_entry(str); \
  45. if (new_str) { \
  46. zend_string_release_ex(str, 0); \
  47. str = new_str; \
  48. } else { \
  49. new_str = zend_shared_memdup_put((void*)str, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \
  50. zend_string_release_ex(str, 0); \
  51. str = new_str; \
  52. zend_string_hash_val(str); \
  53. zend_set_str_gc_flags(str); \
  54. } \
  55. } while (0)
  56. #define zend_accel_memdup_string(str) do { \
  57. zend_string *new_str = zend_shared_alloc_get_xlat_entry(str); \
  58. if (new_str) { \
  59. str = new_str; \
  60. } else { \
  61. new_str = zend_shared_memdup_put((void*)str, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \
  62. str = new_str; \
  63. zend_string_hash_val(str); \
  64. zend_set_str_gc_flags(str); \
  65. } \
  66. } while (0)
  67. #define zend_accel_store_interned_string(str) do { \
  68. if (!IS_ACCEL_INTERNED(str)) { \
  69. zend_accel_store_string(str); \
  70. } \
  71. } while (0)
  72. #define zend_accel_memdup_interned_string(str) do { \
  73. if (!IS_ACCEL_INTERNED(str)) { \
  74. zend_accel_memdup_string(str); \
  75. } \
  76. } while (0)
  77. typedef void (*zend_persist_func_t)(zval*);
  78. static void zend_persist_zval(zval *z);
  79. static void zend_persist_op_array(zval *zv);
  80. static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
  81. {HT_INVALID_IDX, HT_INVALID_IDX};
  82. static void zend_hash_persist(HashTable *ht)
  83. {
  84. uint32_t idx, nIndex;
  85. Bucket *p;
  86. HT_FLAGS(ht) |= HASH_FLAG_STATIC_KEYS;
  87. ht->pDestructor = NULL;
  88. ht->nInternalPointer = 0;
  89. if (HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) {
  90. if (EXPECTED(!ZCG(current_persistent_script)->corrupted)) {
  91. HT_SET_DATA_ADDR(ht, &ZCSG(uninitialized_bucket));
  92. } else {
  93. HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
  94. }
  95. return;
  96. }
  97. if (ht->nNumUsed == 0) {
  98. efree(HT_GET_DATA_ADDR(ht));
  99. ht->nTableMask = HT_MIN_MASK;
  100. if (EXPECTED(!ZCG(current_persistent_script)->corrupted)) {
  101. HT_SET_DATA_ADDR(ht, &ZCSG(uninitialized_bucket));
  102. } else {
  103. HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
  104. }
  105. HT_FLAGS(ht) |= HASH_FLAG_UNINITIALIZED;
  106. return;
  107. }
  108. if (HT_FLAGS(ht) & HASH_FLAG_PACKED) {
  109. void *data = HT_GET_DATA_ADDR(ht);
  110. if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
  111. data = zend_shared_memdup(data, HT_USED_SIZE(ht));
  112. } else {
  113. data = zend_shared_memdup_free(data, HT_USED_SIZE(ht));
  114. }
  115. HT_SET_DATA_ADDR(ht, data);
  116. } else if (ht->nNumUsed > HT_MIN_SIZE && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) {
  117. /* compact table */
  118. void *old_data = HT_GET_DATA_ADDR(ht);
  119. Bucket *old_buckets = ht->arData;
  120. uint32_t hash_size;
  121. hash_size = (uint32_t)(-(int32_t)ht->nTableMask);
  122. while (hash_size >> 2 > ht->nNumUsed) {
  123. hash_size >>= 1;
  124. }
  125. ht->nTableMask = (uint32_t)(-(int32_t)hash_size);
  126. ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
  127. HT_SET_DATA_ADDR(ht, ZCG(mem));
  128. ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE((hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket))));
  129. HT_HASH_RESET(ht);
  130. memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket));
  131. if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
  132. efree(old_data);
  133. }
  134. /* rehash */
  135. for (idx = 0; idx < ht->nNumUsed; idx++) {
  136. p = ht->arData + idx;
  137. if (Z_TYPE(p->val) == IS_UNDEF) continue;
  138. nIndex = p->h | ht->nTableMask;
  139. Z_NEXT(p->val) = HT_HASH(ht, nIndex);
  140. HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
  141. }
  142. } else {
  143. void *data = ZCG(mem);
  144. void *old_data = HT_GET_DATA_ADDR(ht);
  145. ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
  146. ZCG(mem) = (void*)((char*)data + ZEND_ALIGNED_SIZE(HT_USED_SIZE(ht)));
  147. memcpy(data, old_data, HT_USED_SIZE(ht));
  148. if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
  149. efree(old_data);
  150. }
  151. HT_SET_DATA_ADDR(ht, data);
  152. }
  153. }
  154. static zend_ast *zend_persist_ast(zend_ast *ast)
  155. {
  156. uint32_t i;
  157. zend_ast *node;
  158. if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
  159. zend_ast_zval *copy = zend_shared_memdup(ast, sizeof(zend_ast_zval));
  160. zend_persist_zval(&copy->val);
  161. node = (zend_ast *) copy;
  162. } else if (zend_ast_is_list(ast)) {
  163. zend_ast_list *list = zend_ast_get_list(ast);
  164. zend_ast_list *copy = zend_shared_memdup(ast,
  165. sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
  166. for (i = 0; i < list->children; i++) {
  167. if (copy->child[i]) {
  168. copy->child[i] = zend_persist_ast(copy->child[i]);
  169. }
  170. }
  171. node = (zend_ast *) copy;
  172. } else {
  173. uint32_t children = zend_ast_get_num_children(ast);
  174. node = zend_shared_memdup(ast, sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
  175. for (i = 0; i < children; i++) {
  176. if (node->child[i]) {
  177. node->child[i] = zend_persist_ast(node->child[i]);
  178. }
  179. }
  180. }
  181. return node;
  182. }
  183. static void zend_persist_zval(zval *z)
  184. {
  185. void *new_ptr;
  186. switch (Z_TYPE_P(z)) {
  187. case IS_STRING:
  188. zend_accel_store_interned_string(Z_STR_P(z));
  189. Z_TYPE_FLAGS_P(z) = 0;
  190. break;
  191. case IS_ARRAY:
  192. new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
  193. if (new_ptr) {
  194. Z_ARR_P(z) = new_ptr;
  195. Z_TYPE_FLAGS_P(z) = 0;
  196. } else if (!ZCG(current_persistent_script)->corrupted
  197. && zend_accel_in_shm(Z_ARR_P(z))) {
  198. /* pass */
  199. } else {
  200. Bucket *p;
  201. if (!Z_REFCOUNTED_P(z)) {
  202. Z_ARR_P(z) = zend_shared_memdup_put(Z_ARR_P(z), sizeof(zend_array));
  203. } else {
  204. GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
  205. Z_ARR_P(z) = zend_shared_memdup_put_free(Z_ARR_P(z), sizeof(zend_array));
  206. }
  207. zend_hash_persist(Z_ARRVAL_P(z));
  208. ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(z), p) {
  209. if (p->key) {
  210. zend_accel_store_interned_string(p->key);
  211. }
  212. zend_persist_zval(&p->val);
  213. } ZEND_HASH_FOREACH_END();
  214. /* make immutable array */
  215. Z_TYPE_FLAGS_P(z) = 0;
  216. GC_SET_REFCOUNT(Z_COUNTED_P(z), 2);
  217. GC_ADD_FLAGS(Z_COUNTED_P(z), IS_ARRAY_IMMUTABLE);
  218. }
  219. break;
  220. case IS_CONSTANT_AST:
  221. new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
  222. if (new_ptr) {
  223. Z_AST_P(z) = new_ptr;
  224. Z_TYPE_FLAGS_P(z) = 0;
  225. } else if (ZCG(current_persistent_script)->corrupted
  226. || !zend_accel_in_shm(Z_AST_P(z))) {
  227. zend_ast_ref *old_ref = Z_AST_P(z);
  228. Z_AST_P(z) = zend_shared_memdup_put(Z_AST_P(z), sizeof(zend_ast_ref));
  229. zend_persist_ast(GC_AST(old_ref));
  230. Z_TYPE_FLAGS_P(z) = 0;
  231. GC_SET_REFCOUNT(Z_COUNTED_P(z), 1);
  232. efree(old_ref);
  233. }
  234. break;
  235. default:
  236. ZEND_ASSERT(Z_TYPE_P(z) < IS_STRING);
  237. break;
  238. }
  239. }
  240. static HashTable *zend_persist_attributes(HashTable *attributes)
  241. {
  242. uint32_t i;
  243. zval *v;
  244. if (!ZCG(current_persistent_script)->corrupted && zend_accel_in_shm(attributes)) {
  245. return attributes;
  246. }
  247. /* Attributes for trait properties may be shared if preloading is used. */
  248. HashTable *xlat = zend_shared_alloc_get_xlat_entry(attributes);
  249. if (xlat) {
  250. return xlat;
  251. }
  252. zend_hash_persist(attributes);
  253. ZEND_HASH_FOREACH_VAL(attributes, v) {
  254. zend_attribute *attr = Z_PTR_P(v);
  255. zend_attribute *copy = zend_shared_memdup_put_free(attr, ZEND_ATTRIBUTE_SIZE(attr->argc));
  256. zend_accel_store_interned_string(copy->name);
  257. zend_accel_store_interned_string(copy->lcname);
  258. for (i = 0; i < copy->argc; i++) {
  259. if (copy->args[i].name) {
  260. zend_accel_store_interned_string(copy->args[i].name);
  261. }
  262. zend_persist_zval(&copy->args[i].value);
  263. }
  264. ZVAL_PTR(v, copy);
  265. } ZEND_HASH_FOREACH_END();
  266. HashTable *ptr = zend_shared_memdup_put_free(attributes, sizeof(HashTable));
  267. GC_SET_REFCOUNT(ptr, 2);
  268. GC_TYPE_INFO(ptr) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT);
  269. return ptr;
  270. }
  271. uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name)
  272. {
  273. uint32_t ret;
  274. if (zend_string_equals_literal_ci(type_name, "self") ||
  275. zend_string_equals_literal_ci(type_name, "parent")) {
  276. return 0;
  277. }
  278. /* We use type.name.gc.refcount to keep map_ptr of corresponding type */
  279. if (ZSTR_HAS_CE_CACHE(type_name)) {
  280. return GC_REFCOUNT(type_name);
  281. }
  282. if ((GC_FLAGS(type_name) & GC_IMMUTABLE)
  283. && (GC_FLAGS(type_name) & IS_STR_PERMANENT)) {
  284. do {
  285. ret = ZEND_MAP_PTR_NEW_OFFSET();
  286. } while (ret <= 2);
  287. GC_SET_REFCOUNT(type_name, ret);
  288. GC_ADD_FLAGS(type_name, IS_STR_CLASS_NAME_MAP_PTR);
  289. return ret;
  290. }
  291. return 0;
  292. }
  293. static HashTable *zend_persist_backed_enum_table(HashTable *backed_enum_table)
  294. {
  295. HashTable *ptr;
  296. Bucket *p;
  297. zend_hash_persist(backed_enum_table);
  298. ZEND_HASH_FOREACH_BUCKET(backed_enum_table, p) {
  299. if (p->key != NULL) {
  300. zend_accel_store_interned_string(p->key);
  301. }
  302. zend_persist_zval(&p->val);
  303. } ZEND_HASH_FOREACH_END();
  304. ptr = zend_shared_memdup_free(backed_enum_table, sizeof(HashTable));
  305. GC_SET_REFCOUNT(ptr, 2);
  306. GC_TYPE_INFO(ptr) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT);
  307. return ptr;
  308. }
  309. static void zend_persist_type(zend_type *type, zend_class_entry *scope) {
  310. if (ZEND_TYPE_HAS_LIST(*type)) {
  311. zend_type_list *list = ZEND_TYPE_LIST(*type);
  312. if (ZEND_TYPE_USES_ARENA(*type)) {
  313. list = zend_shared_memdup_put(list, ZEND_TYPE_LIST_SIZE(list->num_types));
  314. ZEND_TYPE_FULL_MASK(*type) &= ~_ZEND_TYPE_ARENA_BIT;
  315. } else {
  316. list = zend_shared_memdup_put_free(list, ZEND_TYPE_LIST_SIZE(list->num_types));
  317. }
  318. ZEND_TYPE_SET_PTR(*type, list);
  319. }
  320. zend_type *single_type;
  321. ZEND_TYPE_FOREACH(*type, single_type) {
  322. if (ZEND_TYPE_HAS_NAME(*single_type)) {
  323. zend_string *type_name = ZEND_TYPE_NAME(*single_type);
  324. zend_accel_store_interned_string(type_name);
  325. ZEND_TYPE_SET_PTR(*single_type, type_name);
  326. if (!ZCG(current_persistent_script)->corrupted) {
  327. zend_accel_get_class_name_map_ptr(type_name);
  328. }
  329. }
  330. } ZEND_TYPE_FOREACH_END();
  331. }
  332. static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script)
  333. {
  334. zend_op *persist_ptr;
  335. zval *orig_literals = NULL;
  336. if (op_array->refcount && --(*op_array->refcount) == 0) {
  337. efree(op_array->refcount);
  338. }
  339. op_array->refcount = NULL;
  340. if (main_persistent_script) {
  341. zend_execute_data *orig_execute_data = EG(current_execute_data);
  342. zend_execute_data fake_execute_data;
  343. zval *offset;
  344. memset(&fake_execute_data, 0, sizeof(fake_execute_data));
  345. fake_execute_data.func = (zend_function*)op_array;
  346. EG(current_execute_data) = &fake_execute_data;
  347. if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
  348. main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset);
  349. }
  350. EG(current_execute_data) = orig_execute_data;
  351. }
  352. if (op_array->function_name) {
  353. zend_string *old_name = op_array->function_name;
  354. zend_accel_store_interned_string(op_array->function_name);
  355. /* Remember old function name, so it can be released multiple times if shared. */
  356. if (op_array->function_name != old_name
  357. && !zend_shared_alloc_get_xlat_entry(&op_array->function_name)) {
  358. zend_shared_alloc_register_xlat_entry(&op_array->function_name, old_name);
  359. }
  360. }
  361. if (op_array->scope) {
  362. zend_class_entry *scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
  363. if (scope) {
  364. op_array->scope = scope;
  365. }
  366. if (op_array->prototype) {
  367. zend_function *ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype);
  368. if (ptr) {
  369. op_array->prototype = ptr;
  370. }
  371. }
  372. persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
  373. if (persist_ptr) {
  374. op_array->opcodes = persist_ptr;
  375. if (op_array->static_variables) {
  376. op_array->static_variables = zend_shared_alloc_get_xlat_entry(op_array->static_variables);
  377. ZEND_ASSERT(op_array->static_variables != NULL);
  378. }
  379. if (op_array->literals) {
  380. op_array->literals = zend_shared_alloc_get_xlat_entry(op_array->literals);
  381. ZEND_ASSERT(op_array->literals != NULL);
  382. }
  383. if (op_array->filename) {
  384. op_array->filename = zend_shared_alloc_get_xlat_entry(op_array->filename);
  385. ZEND_ASSERT(op_array->filename != NULL);
  386. }
  387. if (op_array->arg_info) {
  388. zend_arg_info *arg_info = op_array->arg_info;
  389. if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  390. arg_info--;
  391. }
  392. arg_info = zend_shared_alloc_get_xlat_entry(arg_info);
  393. ZEND_ASSERT(arg_info != NULL);
  394. if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  395. arg_info++;
  396. }
  397. op_array->arg_info = arg_info;
  398. }
  399. if (op_array->live_range) {
  400. op_array->live_range = zend_shared_alloc_get_xlat_entry(op_array->live_range);
  401. ZEND_ASSERT(op_array->live_range != NULL);
  402. }
  403. if (op_array->doc_comment) {
  404. if (ZCG(accel_directives).save_comments) {
  405. op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment);
  406. ZEND_ASSERT(op_array->doc_comment != NULL);
  407. } else {
  408. op_array->doc_comment = NULL;
  409. }
  410. }
  411. if (op_array->attributes) {
  412. op_array->attributes = zend_shared_alloc_get_xlat_entry(op_array->attributes);
  413. ZEND_ASSERT(op_array->attributes != NULL);
  414. }
  415. if (op_array->try_catch_array) {
  416. op_array->try_catch_array = zend_shared_alloc_get_xlat_entry(op_array->try_catch_array);
  417. ZEND_ASSERT(op_array->try_catch_array != NULL);
  418. }
  419. if (op_array->vars) {
  420. op_array->vars = zend_shared_alloc_get_xlat_entry(op_array->vars);
  421. ZEND_ASSERT(op_array->vars != NULL);
  422. }
  423. if (op_array->dynamic_func_defs) {
  424. op_array->dynamic_func_defs = zend_shared_alloc_get_xlat_entry(op_array->dynamic_func_defs);
  425. ZEND_ASSERT(op_array->dynamic_func_defs != NULL);
  426. }
  427. ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem))));
  428. return;
  429. }
  430. } else {
  431. /* "prototype" may be undefined if "scope" isn't set */
  432. op_array->prototype = NULL;
  433. }
  434. if (op_array->scope
  435. && !(op_array->fn_flags & ZEND_ACC_CLOSURE)
  436. && (op_array->scope->ce_flags & ZEND_ACC_CACHED)) {
  437. return;
  438. }
  439. if (op_array->static_variables && !zend_accel_in_shm(op_array->static_variables)) {
  440. Bucket *p;
  441. zend_hash_persist(op_array->static_variables);
  442. ZEND_HASH_FOREACH_BUCKET(op_array->static_variables, p) {
  443. ZEND_ASSERT(p->key != NULL);
  444. zend_accel_store_interned_string(p->key);
  445. zend_persist_zval(&p->val);
  446. } ZEND_HASH_FOREACH_END();
  447. op_array->static_variables = zend_shared_memdup_put_free(op_array->static_variables, sizeof(HashTable));
  448. /* make immutable array */
  449. GC_SET_REFCOUNT(op_array->static_variables, 2);
  450. GC_TYPE_INFO(op_array->static_variables) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT);
  451. }
  452. if (op_array->literals) {
  453. zval *p, *end;
  454. orig_literals = op_array->literals;
  455. #if ZEND_USE_ABS_CONST_ADDR
  456. p = zend_shared_memdup_put_free(op_array->literals, sizeof(zval) * op_array->last_literal);
  457. #else
  458. p = zend_shared_memdup_put(op_array->literals, sizeof(zval) * op_array->last_literal);
  459. #endif
  460. end = p + op_array->last_literal;
  461. op_array->literals = p;
  462. while (p < end) {
  463. zend_persist_zval(p);
  464. p++;
  465. }
  466. }
  467. {
  468. zend_op *new_opcodes = zend_shared_memdup_put(op_array->opcodes, sizeof(zend_op) * op_array->last);
  469. zend_op *opline = new_opcodes;
  470. zend_op *end = new_opcodes + op_array->last;
  471. int offset = 0;
  472. for (; opline < end ; opline++, offset++) {
  473. #if ZEND_USE_ABS_CONST_ADDR
  474. if (opline->op1_type == IS_CONST) {
  475. opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
  476. if (opline->opcode == ZEND_SEND_VAL
  477. || opline->opcode == ZEND_SEND_VAL_EX
  478. || opline->opcode == ZEND_QM_ASSIGN) {
  479. /* Update handlers to eliminate REFCOUNTED check */
  480. zend_vm_set_opcode_handler_ex(opline, 1 << Z_TYPE_P(opline->op1.zv), 0, 0);
  481. }
  482. }
  483. if (opline->op2_type == IS_CONST) {
  484. opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
  485. }
  486. #else
  487. if (opline->op1_type == IS_CONST) {
  488. opline->op1.constant =
  489. (char*)(op_array->literals +
  490. ((zval*)((char*)(op_array->opcodes + (opline - new_opcodes)) +
  491. (int32_t)opline->op1.constant) - orig_literals)) -
  492. (char*)opline;
  493. if (opline->opcode == ZEND_SEND_VAL
  494. || opline->opcode == ZEND_SEND_VAL_EX
  495. || opline->opcode == ZEND_QM_ASSIGN) {
  496. zend_vm_set_opcode_handler_ex(opline, 0, 0, 0);
  497. }
  498. }
  499. if (opline->op2_type == IS_CONST) {
  500. opline->op2.constant =
  501. (char*)(op_array->literals +
  502. ((zval*)((char*)(op_array->opcodes + (opline - new_opcodes)) +
  503. (int32_t)opline->op2.constant) - orig_literals)) -
  504. (char*)opline;
  505. }
  506. #endif
  507. #if ZEND_USE_ABS_JMP_ADDR
  508. if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
  509. /* fix jumps to point to new array */
  510. switch (opline->opcode) {
  511. case ZEND_JMP:
  512. case ZEND_FAST_CALL:
  513. opline->op1.jmp_addr = &new_opcodes[opline->op1.jmp_addr - op_array->opcodes];
  514. break;
  515. case ZEND_JMPZNZ:
  516. /* relative extended_value don't have to be changed */
  517. /* break omitted intentionally */
  518. case ZEND_JMPZ:
  519. case ZEND_JMPNZ:
  520. case ZEND_JMPZ_EX:
  521. case ZEND_JMPNZ_EX:
  522. case ZEND_JMP_SET:
  523. case ZEND_COALESCE:
  524. case ZEND_FE_RESET_R:
  525. case ZEND_FE_RESET_RW:
  526. case ZEND_ASSERT_CHECK:
  527. case ZEND_JMP_NULL:
  528. opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes];
  529. break;
  530. case ZEND_CATCH:
  531. if (!(opline->extended_value & ZEND_LAST_CATCH)) {
  532. opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes];
  533. }
  534. break;
  535. case ZEND_FE_FETCH_R:
  536. case ZEND_FE_FETCH_RW:
  537. case ZEND_SWITCH_LONG:
  538. case ZEND_SWITCH_STRING:
  539. case ZEND_MATCH:
  540. /* relative extended_value don't have to be changed */
  541. break;
  542. }
  543. }
  544. #endif
  545. }
  546. efree(op_array->opcodes);
  547. op_array->opcodes = new_opcodes;
  548. }
  549. if (op_array->filename) {
  550. zend_accel_store_string(op_array->filename);
  551. }
  552. if (op_array->arg_info) {
  553. zend_arg_info *arg_info = op_array->arg_info;
  554. uint32_t num_args = op_array->num_args;
  555. uint32_t i;
  556. if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  557. arg_info--;
  558. num_args++;
  559. }
  560. if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
  561. num_args++;
  562. }
  563. arg_info = zend_shared_memdup_put_free(arg_info, sizeof(zend_arg_info) * num_args);
  564. for (i = 0; i < num_args; i++) {
  565. if (arg_info[i].name) {
  566. zend_accel_store_interned_string(arg_info[i].name);
  567. }
  568. zend_persist_type(&arg_info[i].type, op_array->scope);
  569. }
  570. if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  571. arg_info++;
  572. }
  573. op_array->arg_info = arg_info;
  574. }
  575. if (op_array->live_range) {
  576. op_array->live_range = zend_shared_memdup_put_free(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
  577. }
  578. if (op_array->doc_comment) {
  579. if (ZCG(accel_directives).save_comments) {
  580. zend_accel_store_interned_string(op_array->doc_comment);
  581. } else {
  582. zend_string_release_ex(op_array->doc_comment, 0);
  583. op_array->doc_comment = NULL;
  584. }
  585. }
  586. if (op_array->attributes) {
  587. op_array->attributes = zend_persist_attributes(op_array->attributes);
  588. }
  589. if (op_array->try_catch_array) {
  590. 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);
  591. }
  592. if (op_array->vars) {
  593. int i;
  594. op_array->vars = zend_shared_memdup_put_free(op_array->vars, sizeof(zend_string*) * op_array->last_var);
  595. for (i = 0; i < op_array->last_var; i++) {
  596. zend_accel_store_interned_string(op_array->vars[i]);
  597. }
  598. }
  599. if (op_array->num_dynamic_func_defs) {
  600. op_array->dynamic_func_defs = zend_shared_memdup_put_free(
  601. op_array->dynamic_func_defs, sizeof(zend_function *) * op_array->num_dynamic_func_defs);
  602. for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
  603. zval tmp;
  604. ZVAL_PTR(&tmp, op_array->dynamic_func_defs[i]);
  605. zend_persist_op_array(&tmp);
  606. op_array->dynamic_func_defs[i] = Z_PTR(tmp);
  607. }
  608. }
  609. ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem))));
  610. }
  611. static void zend_persist_op_array(zval *zv)
  612. {
  613. zend_op_array *op_array = Z_PTR_P(zv);
  614. zend_op_array *old_op_array;
  615. ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
  616. old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
  617. if (!old_op_array) {
  618. op_array = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_op_array));
  619. zend_persist_op_array_ex(op_array, NULL);
  620. if (!ZCG(current_persistent_script)->corrupted) {
  621. op_array->fn_flags |= ZEND_ACC_IMMUTABLE;
  622. ZEND_MAP_PTR_NEW(op_array->run_time_cache);
  623. if (op_array->static_variables) {
  624. ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
  625. }
  626. }
  627. #ifdef HAVE_JIT
  628. if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS) {
  629. zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
  630. }
  631. #endif
  632. } else {
  633. /* This can happen during preloading, if a dynamic function definition is declared. */
  634. Z_PTR_P(zv) = old_op_array;
  635. }
  636. }
  637. static void zend_persist_class_method(zval *zv, zend_class_entry *ce)
  638. {
  639. zend_op_array *op_array = Z_PTR_P(zv);
  640. zend_op_array *old_op_array;
  641. if (op_array->type != ZEND_USER_FUNCTION) {
  642. ZEND_ASSERT(op_array->type == ZEND_INTERNAL_FUNCTION);
  643. if (op_array->fn_flags & ZEND_ACC_ARENA_ALLOCATED) {
  644. old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
  645. if (old_op_array) {
  646. Z_PTR_P(zv) = old_op_array;
  647. } else {
  648. op_array = Z_PTR_P(zv) = zend_shared_memdup_put(op_array, sizeof(zend_internal_function));
  649. if (op_array->scope) {
  650. void *persist_ptr;
  651. if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->scope))) {
  652. op_array->scope = (zend_class_entry*)persist_ptr;
  653. }
  654. if (op_array->prototype) {
  655. if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
  656. op_array->prototype = (zend_function*)persist_ptr;
  657. }
  658. }
  659. }
  660. }
  661. }
  662. return;
  663. }
  664. if ((op_array->fn_flags & ZEND_ACC_IMMUTABLE)
  665. && !ZCG(current_persistent_script)->corrupted
  666. && zend_accel_in_shm(op_array)) {
  667. zend_shared_alloc_register_xlat_entry(op_array, op_array);
  668. return;
  669. }
  670. old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
  671. if (old_op_array) {
  672. Z_PTR_P(zv) = old_op_array;
  673. if (op_array->refcount && --(*op_array->refcount) == 0) {
  674. efree(op_array->refcount);
  675. }
  676. /* If op_array is shared, the function name refcount is still incremented for each use,
  677. * so we need to release it here. We remembered the original function name in xlat. */
  678. zend_string *old_function_name =
  679. zend_shared_alloc_get_xlat_entry(&old_op_array->function_name);
  680. if (old_function_name) {
  681. zend_string_release_ex(old_function_name, 0);
  682. }
  683. return;
  684. }
  685. op_array = Z_PTR_P(zv) = zend_shared_memdup_put(op_array, sizeof(zend_op_array));
  686. zend_persist_op_array_ex(op_array, NULL);
  687. if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
  688. op_array->fn_flags |= ZEND_ACC_IMMUTABLE;
  689. if (ce->ce_flags & ZEND_ACC_LINKED) {
  690. ZEND_MAP_PTR_NEW(op_array->run_time_cache);
  691. if (op_array->static_variables) {
  692. ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
  693. }
  694. } else {
  695. ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
  696. ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL);
  697. }
  698. }
  699. }
  700. static zend_property_info *zend_persist_property_info(zend_property_info *prop)
  701. {
  702. zend_class_entry *ce;
  703. prop = zend_shared_memdup_put(prop, sizeof(zend_property_info));
  704. ce = zend_shared_alloc_get_xlat_entry(prop->ce);
  705. if (ce) {
  706. prop->ce = ce;
  707. }
  708. zend_accel_store_interned_string(prop->name);
  709. if (prop->doc_comment) {
  710. if (ZCG(accel_directives).save_comments) {
  711. zend_accel_store_interned_string(prop->doc_comment);
  712. } else {
  713. if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
  714. zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
  715. }
  716. zend_string_release_ex(prop->doc_comment, 0);
  717. prop->doc_comment = NULL;
  718. }
  719. }
  720. if (prop->attributes) {
  721. prop->attributes = zend_persist_attributes(prop->attributes);
  722. }
  723. zend_persist_type(&prop->type, ce);
  724. return prop;
  725. }
  726. static void zend_persist_class_constant(zval *zv)
  727. {
  728. zend_class_constant *c = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv));
  729. zend_class_entry *ce;
  730. if (c) {
  731. Z_PTR_P(zv) = c;
  732. return;
  733. } else if (!ZCG(current_persistent_script)->corrupted
  734. && zend_accel_in_shm(Z_PTR_P(zv))) {
  735. return;
  736. }
  737. c = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_class_constant));
  738. zend_persist_zval(&c->value);
  739. ce = zend_shared_alloc_get_xlat_entry(c->ce);
  740. if (ce) {
  741. c->ce = ce;
  742. }
  743. if (c->doc_comment) {
  744. if (ZCG(accel_directives).save_comments) {
  745. zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
  746. if (doc_comment) {
  747. c->doc_comment = doc_comment;
  748. } else {
  749. zend_accel_store_interned_string(c->doc_comment);
  750. }
  751. } else {
  752. zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
  753. if (!doc_comment) {
  754. zend_shared_alloc_register_xlat_entry(c->doc_comment, c->doc_comment);
  755. zend_string_release_ex(c->doc_comment, 0);
  756. }
  757. c->doc_comment = NULL;
  758. }
  759. }
  760. if (c->attributes) {
  761. c->attributes = zend_persist_attributes(c->attributes);
  762. }
  763. }
  764. zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce)
  765. {
  766. Bucket *p;
  767. zend_class_entry *ce = orig_ce;
  768. if (ce->type == ZEND_USER_CLASS) {
  769. /* The same zend_class_entry may be reused by class_alias */
  770. zend_class_entry *new_ce = zend_shared_alloc_get_xlat_entry(ce);
  771. if (new_ce) {
  772. return new_ce;
  773. }
  774. ce = zend_shared_memdup_put(ce, sizeof(zend_class_entry));
  775. if (EXPECTED(!ZCG(current_persistent_script)->corrupted)) {
  776. ce->ce_flags |= ZEND_ACC_IMMUTABLE;
  777. if ((ce->ce_flags & ZEND_ACC_LINKED)
  778. && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
  779. ZEND_MAP_PTR_NEW(ce->mutable_data);
  780. } else {
  781. ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
  782. }
  783. } else {
  784. ce->ce_flags |= ZEND_ACC_FILE_CACHED;
  785. }
  786. ce->inheritance_cache = NULL;
  787. if (!(ce->ce_flags & ZEND_ACC_CACHED)) {
  788. if (ZSTR_HAS_CE_CACHE(ce->name)) {
  789. ZSTR_SET_CE_CACHE_EX(ce->name, NULL, 0);
  790. }
  791. zend_accel_store_interned_string(ce->name);
  792. if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS)
  793. && !ZCG(current_persistent_script)->corrupted) {
  794. zend_accel_get_class_name_map_ptr(ce->name);
  795. }
  796. if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_LINKED)) {
  797. zend_accel_store_interned_string(ce->parent_name);
  798. }
  799. }
  800. zend_hash_persist(&ce->function_table);
  801. ZEND_HASH_FOREACH_BUCKET(&ce->function_table, p) {
  802. ZEND_ASSERT(p->key != NULL);
  803. zend_accel_store_interned_string(p->key);
  804. zend_persist_class_method(&p->val, ce);
  805. } ZEND_HASH_FOREACH_END();
  806. HT_FLAGS(&ce->function_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
  807. if (ce->default_properties_table) {
  808. int i;
  809. ce->default_properties_table = zend_shared_memdup_free(ce->default_properties_table, sizeof(zval) * ce->default_properties_count);
  810. for (i = 0; i < ce->default_properties_count; i++) {
  811. zend_persist_zval(&ce->default_properties_table[i]);
  812. }
  813. }
  814. if (ce->default_static_members_table) {
  815. int i;
  816. ce->default_static_members_table = zend_shared_memdup_free(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count);
  817. /* Persist only static properties in this class.
  818. * Static properties from parent classes will be handled in class_copy_ctor */
  819. i = (ce->parent && (ce->ce_flags & ZEND_ACC_LINKED)) ? ce->parent->default_static_members_count : 0;
  820. for (; i < ce->default_static_members_count; i++) {
  821. zend_persist_zval(&ce->default_static_members_table[i]);
  822. }
  823. if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
  824. if (ce->ce_flags & ZEND_ACC_LINKED) {
  825. ZEND_MAP_PTR_NEW(ce->static_members_table);
  826. } else {
  827. ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
  828. }
  829. }
  830. }
  831. zend_hash_persist(&ce->constants_table);
  832. ZEND_HASH_FOREACH_BUCKET(&ce->constants_table, p) {
  833. ZEND_ASSERT(p->key != NULL);
  834. zend_accel_store_interned_string(p->key);
  835. zend_persist_class_constant(&p->val);
  836. } ZEND_HASH_FOREACH_END();
  837. HT_FLAGS(&ce->constants_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
  838. zend_hash_persist(&ce->properties_info);
  839. ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) {
  840. zend_property_info *prop = Z_PTR(p->val);
  841. ZEND_ASSERT(p->key != NULL);
  842. zend_accel_store_interned_string(p->key);
  843. if (prop->ce == orig_ce) {
  844. Z_PTR(p->val) = zend_persist_property_info(prop);
  845. } else {
  846. prop = zend_shared_alloc_get_xlat_entry(prop);
  847. if (prop) {
  848. Z_PTR(p->val) = prop;
  849. } else {
  850. /* This can happen if preloading is used and we inherit a property from an
  851. * internal class. In that case we should keep pointing to the internal
  852. * property, without any adjustments. */
  853. }
  854. }
  855. } ZEND_HASH_FOREACH_END();
  856. HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
  857. if (ce->properties_info_table) {
  858. int i;
  859. size_t size = sizeof(zend_property_info *) * ce->default_properties_count;
  860. ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
  861. ce->properties_info_table = zend_shared_memdup(
  862. ce->properties_info_table, size);
  863. for (i = 0; i < ce->default_properties_count; i++) {
  864. if (ce->properties_info_table[i]) {
  865. zend_property_info *prop_info = zend_shared_alloc_get_xlat_entry(
  866. ce->properties_info_table[i]);
  867. if (prop_info) {
  868. ce->properties_info_table[i] = prop_info;
  869. }
  870. }
  871. }
  872. }
  873. if (ce->iterator_funcs_ptr) {
  874. ce->iterator_funcs_ptr = zend_shared_memdup(ce->iterator_funcs_ptr, sizeof(zend_class_iterator_funcs));
  875. }
  876. if (ce->ce_flags & ZEND_ACC_CACHED) {
  877. return ce;
  878. }
  879. ce->ce_flags |= ZEND_ACC_CACHED;
  880. if (ce->info.user.filename) {
  881. zend_accel_store_string(ce->info.user.filename);
  882. }
  883. if (ce->info.user.doc_comment) {
  884. if (ZCG(accel_directives).save_comments) {
  885. zend_accel_store_interned_string(ce->info.user.doc_comment);
  886. } else {
  887. if (!zend_shared_alloc_get_xlat_entry(ce->info.user.doc_comment)) {
  888. zend_shared_alloc_register_xlat_entry(ce->info.user.doc_comment, ce->info.user.doc_comment);
  889. zend_string_release_ex(ce->info.user.doc_comment, 0);
  890. }
  891. ce->info.user.doc_comment = NULL;
  892. }
  893. }
  894. if (ce->attributes) {
  895. ce->attributes = zend_persist_attributes(ce->attributes);
  896. }
  897. if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_LINKED)) {
  898. uint32_t i = 0;
  899. for (i = 0; i < ce->num_interfaces; i++) {
  900. zend_accel_store_interned_string(ce->interface_names[i].name);
  901. zend_accel_store_interned_string(ce->interface_names[i].lc_name);
  902. }
  903. ce->interface_names = zend_shared_memdup_free(ce->interface_names, sizeof(zend_class_name) * ce->num_interfaces);
  904. }
  905. if (ce->num_traits) {
  906. uint32_t i = 0;
  907. for (i = 0; i < ce->num_traits; i++) {
  908. zend_accel_store_interned_string(ce->trait_names[i].name);
  909. zend_accel_store_interned_string(ce->trait_names[i].lc_name);
  910. }
  911. ce->trait_names = zend_shared_memdup_free(ce->trait_names, sizeof(zend_class_name) * ce->num_traits);
  912. i = 0;
  913. if (ce->trait_aliases) {
  914. while (ce->trait_aliases[i]) {
  915. if (ce->trait_aliases[i]->trait_method.method_name) {
  916. zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method.method_name);
  917. }
  918. if (ce->trait_aliases[i]->trait_method.class_name) {
  919. zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method.class_name);
  920. }
  921. if (ce->trait_aliases[i]->alias) {
  922. zend_accel_store_interned_string(ce->trait_aliases[i]->alias);
  923. }
  924. ce->trait_aliases[i] = zend_shared_memdup_free(ce->trait_aliases[i], sizeof(zend_trait_alias));
  925. i++;
  926. }
  927. ce->trait_aliases = zend_shared_memdup_free(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1));
  928. }
  929. if (ce->trait_precedences) {
  930. uint32_t j;
  931. i = 0;
  932. while (ce->trait_precedences[i]) {
  933. zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method.method_name);
  934. zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method.class_name);
  935. for (j = 0; j < ce->trait_precedences[i]->num_excludes; j++) {
  936. zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_class_names[j]);
  937. }
  938. 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*));
  939. i++;
  940. }
  941. ce->trait_precedences = zend_shared_memdup_free(
  942. ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
  943. }
  944. }
  945. if (ce->backed_enum_table) {
  946. ce->backed_enum_table = zend_persist_backed_enum_table(ce->backed_enum_table);
  947. }
  948. }
  949. return ce;
  950. }
  951. void zend_update_parent_ce(zend_class_entry *ce)
  952. {
  953. if (ce->ce_flags & ZEND_ACC_LINKED) {
  954. if (ce->parent) {
  955. int i, end;
  956. zend_class_entry *parent = ce->parent;
  957. if (parent->type == ZEND_USER_CLASS) {
  958. zend_class_entry *p = zend_shared_alloc_get_xlat_entry(parent);
  959. if (p) {
  960. ce->parent = parent = p;
  961. }
  962. }
  963. /* Create indirections to static properties from parent classes */
  964. i = parent->default_static_members_count - 1;
  965. while (parent && parent->default_static_members_table) {
  966. end = parent->parent ? parent->parent->default_static_members_count : 0;
  967. for (; i >= end; i--) {
  968. zval *p = &ce->default_static_members_table[i];
  969. ZVAL_INDIRECT(p, &parent->default_static_members_table[i]);
  970. }
  971. parent = parent->parent;
  972. }
  973. }
  974. if (ce->num_interfaces) {
  975. uint32_t i = 0;
  976. ce->interfaces = zend_shared_memdup_free(ce->interfaces, sizeof(zend_class_entry*) * ce->num_interfaces);
  977. for (i = 0; i < ce->num_interfaces; i++) {
  978. if (ce->interfaces[i]->type == ZEND_USER_CLASS) {
  979. zend_class_entry *tmp = zend_shared_alloc_get_xlat_entry(ce->interfaces[i]);
  980. if (tmp != NULL) {
  981. ce->interfaces[i] = tmp;
  982. }
  983. }
  984. }
  985. }
  986. if (ce->iterator_funcs_ptr) {
  987. memset(ce->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
  988. if (zend_class_implements_interface(ce, zend_ce_aggregate)) {
  989. ce->iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&ce->function_table, "getiterator", sizeof("getiterator") - 1);
  990. }
  991. if (zend_class_implements_interface(ce, zend_ce_iterator)) {
  992. ce->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&ce->function_table, "rewind", sizeof("rewind") - 1);
  993. ce->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&ce->function_table, "valid", sizeof("valid") - 1);
  994. ce->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&ce->function_table, "key", sizeof("key") - 1);
  995. ce->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&ce->function_table, "current", sizeof("current") - 1);
  996. ce->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&ce->function_table, "next", sizeof("next") - 1);
  997. }
  998. }
  999. }
  1000. /* update methods */
  1001. if (ce->constructor) {
  1002. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->constructor);
  1003. if (tmp != NULL) {
  1004. ce->constructor = tmp;
  1005. }
  1006. }
  1007. if (ce->destructor) {
  1008. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->destructor);
  1009. if (tmp != NULL) {
  1010. ce->destructor = tmp;
  1011. }
  1012. }
  1013. if (ce->clone) {
  1014. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->clone);
  1015. if (tmp != NULL) {
  1016. ce->clone = tmp;
  1017. }
  1018. }
  1019. if (ce->__get) {
  1020. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__get);
  1021. if (tmp != NULL) {
  1022. ce->__get = tmp;
  1023. }
  1024. }
  1025. if (ce->__set) {
  1026. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__set);
  1027. if (tmp != NULL) {
  1028. ce->__set = tmp;
  1029. }
  1030. }
  1031. if (ce->__call) {
  1032. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__call);
  1033. if (tmp != NULL) {
  1034. ce->__call = tmp;
  1035. }
  1036. }
  1037. if (ce->__serialize) {
  1038. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__serialize);
  1039. if (tmp != NULL) {
  1040. ce->__serialize = tmp;
  1041. }
  1042. }
  1043. if (ce->__unserialize) {
  1044. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__unserialize);
  1045. if (tmp != NULL) {
  1046. ce->__unserialize = tmp;
  1047. }
  1048. }
  1049. if (ce->__isset) {
  1050. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__isset);
  1051. if (tmp != NULL) {
  1052. ce->__isset = tmp;
  1053. }
  1054. }
  1055. if (ce->__unset) {
  1056. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__unset);
  1057. if (tmp != NULL) {
  1058. ce->__unset = tmp;
  1059. }
  1060. }
  1061. if (ce->__tostring) {
  1062. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__tostring);
  1063. if (tmp != NULL) {
  1064. ce->__tostring = tmp;
  1065. }
  1066. }
  1067. if (ce->__callstatic) {
  1068. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
  1069. if (tmp != NULL) {
  1070. ce->__callstatic = tmp;
  1071. }
  1072. }
  1073. if (ce->__debugInfo) {
  1074. zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
  1075. if (tmp != NULL) {
  1076. ce->__debugInfo = tmp;
  1077. }
  1078. }
  1079. }
  1080. static void zend_accel_persist_class_table(HashTable *class_table)
  1081. {
  1082. Bucket *p;
  1083. zend_class_entry *ce;
  1084. #ifdef HAVE_JIT
  1085. bool orig_jit_on = JIT_G(on);
  1086. JIT_G(on) = 0;
  1087. #endif
  1088. zend_hash_persist(class_table);
  1089. ZEND_HASH_FOREACH_BUCKET(class_table, p) {
  1090. ZEND_ASSERT(p->key != NULL);
  1091. zend_accel_store_interned_string(p->key);
  1092. Z_CE(p->val) = zend_persist_class_entry(Z_CE(p->val));
  1093. } ZEND_HASH_FOREACH_END();
  1094. ZEND_HASH_FOREACH_BUCKET(class_table, p) {
  1095. if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
  1096. ce = Z_PTR(p->val);
  1097. zend_update_parent_ce(ce);
  1098. }
  1099. } ZEND_HASH_FOREACH_END();
  1100. #ifdef HAVE_JIT
  1101. JIT_G(on) = orig_jit_on;
  1102. if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS &&
  1103. !ZCG(current_persistent_script)->corrupted) {
  1104. zend_op_array *op_array;
  1105. ZEND_HASH_FOREACH_BUCKET(class_table, p) {
  1106. if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
  1107. ce = Z_PTR(p->val);
  1108. ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
  1109. if (op_array->type == ZEND_USER_FUNCTION) {
  1110. if (op_array->scope == ce
  1111. && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
  1112. zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
  1113. for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
  1114. zend_jit_op_array(op_array->dynamic_func_defs[i], ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
  1115. }
  1116. }
  1117. }
  1118. } ZEND_HASH_FOREACH_END();
  1119. }
  1120. } ZEND_HASH_FOREACH_END();
  1121. ZEND_HASH_FOREACH_BUCKET(class_table, p) {
  1122. if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
  1123. ce = Z_PTR(p->val);
  1124. ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
  1125. if (op_array->type == ZEND_USER_FUNCTION) {
  1126. if ((op_array->scope != ce
  1127. || (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))
  1128. && (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC
  1129. || JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST
  1130. || JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS
  1131. || JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE)) {
  1132. void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
  1133. if (jit_extension) {
  1134. ZEND_SET_FUNC_INFO(op_array, jit_extension);
  1135. }
  1136. }
  1137. }
  1138. } ZEND_HASH_FOREACH_END();
  1139. }
  1140. } ZEND_HASH_FOREACH_END();
  1141. }
  1142. #endif
  1143. }
  1144. zend_error_info **zend_persist_warnings(uint32_t num_warnings, zend_error_info **warnings) {
  1145. if (warnings) {
  1146. warnings = zend_shared_memdup_free(warnings, num_warnings * sizeof(zend_error_info *));
  1147. for (uint32_t i = 0; i < num_warnings; i++) {
  1148. warnings[i] = zend_shared_memdup_free(warnings[i], sizeof(zend_error_info));
  1149. zend_accel_store_string(warnings[i]->filename);
  1150. zend_accel_store_string(warnings[i]->message);
  1151. }
  1152. }
  1153. return warnings;
  1154. }
  1155. zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, int for_shm)
  1156. {
  1157. Bucket *p;
  1158. script->mem = ZCG(mem);
  1159. ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
  1160. script = zend_shared_memdup_free(script, sizeof(zend_persistent_script));
  1161. script->corrupted = 0;
  1162. ZCG(current_persistent_script) = script;
  1163. if (!for_shm) {
  1164. /* script is not going to be saved in SHM */
  1165. script->corrupted = 1;
  1166. }
  1167. zend_accel_store_interned_string(script->script.filename);
  1168. #if defined(__AVX__) || defined(__SSE2__)
  1169. /* Align to 64-byte boundary */
  1170. ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
  1171. #else
  1172. ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
  1173. #endif
  1174. #ifdef HAVE_JIT
  1175. if (JIT_G(on) && for_shm) {
  1176. zend_jit_unprotect();
  1177. }
  1178. #endif
  1179. zend_map_ptr_extend(ZCSG(map_ptr_last));
  1180. zend_accel_persist_class_table(&script->script.class_table);
  1181. zend_hash_persist(&script->script.function_table);
  1182. ZEND_HASH_FOREACH_BUCKET(&script->script.function_table, p) {
  1183. ZEND_ASSERT(p->key != NULL);
  1184. zend_accel_store_interned_string(p->key);
  1185. zend_persist_op_array(&p->val);
  1186. } ZEND_HASH_FOREACH_END();
  1187. zend_persist_op_array_ex(&script->script.main_op_array, script);
  1188. if (!script->corrupted) {
  1189. ZEND_MAP_PTR_INIT(script->script.main_op_array.run_time_cache, NULL);
  1190. if (script->script.main_op_array.static_variables) {
  1191. ZEND_MAP_PTR_NEW(script->script.main_op_array.static_variables_ptr);
  1192. }
  1193. #ifdef HAVE_JIT
  1194. if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS) {
  1195. zend_jit_op_array(&script->script.main_op_array, &script->script);
  1196. }
  1197. #endif
  1198. }
  1199. script->warnings = zend_persist_warnings(script->num_warnings, script->warnings);
  1200. if (for_shm) {
  1201. ZCSG(map_ptr_last) = CG(map_ptr_last);
  1202. }
  1203. #ifdef HAVE_JIT
  1204. if (JIT_G(on) && for_shm) {
  1205. if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_SCRIPT) {
  1206. zend_jit_script(&script->script);
  1207. }
  1208. zend_jit_protect();
  1209. }
  1210. #endif
  1211. script->corrupted = 0;
  1212. ZCG(current_persistent_script) = NULL;
  1213. return script;
  1214. }