Coverage Report

Created: 2026-09-14 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/ext/opcache/zend_persist.c
Line
Count
Source
1
/*
2
   +----------------------------------------------------------------------+
3
   | Zend OPcache                                                         |
4
   +----------------------------------------------------------------------+
5
   | Copyright © The PHP Group and Contributors.                          |
6
   +----------------------------------------------------------------------+
7
   | This source file is subject to the Modified BSD License that is      |
8
   | bundled with this package in the file LICENSE, and is available      |
9
   | through the World Wide Web at <https://www.php.net/license/>.        |
10
   |                                                                      |
11
   | SPDX-License-Identifier: BSD-3-Clause                                |
12
   +----------------------------------------------------------------------+
13
   | Authors: Andi Gutmans <andi@php.net>                                 |
14
   |          Zeev Suraski <zeev@php.net>                                 |
15
   |          Stanislav Malyshev <stas@zend.com>                          |
16
   |          Dmitry Stogov <dmitry@php.net>                              |
17
   +----------------------------------------------------------------------+
18
*/
19
20
#include "zend.h"
21
#include "ZendAccelerator.h"
22
#include "zend_persist.h"
23
#include "zend_extensions.h"
24
#include "zend_shared_alloc.h"
25
#include "zend_vm.h"
26
#include "zend_constants.h"
27
#include "zend_operators.h"
28
#include "zend_interfaces.h"
29
#include "zend_attributes.h"
30
#include "zend_partial.h"
31
32
#ifdef HAVE_JIT
33
# include "Optimizer/zend_func_info.h"
34
# include "jit/zend_jit.h"
35
#endif
36
37
122k
#define zend_set_str_gc_flags(str) do { \
38
122k
  GC_SET_REFCOUNT(str, 2); \
39
122k
  uint32_t flags = GC_STRING | (ZSTR_IS_VALID_UTF8(str) ? IS_STR_VALID_UTF8 : 0); \
40
122k
  if (file_cache_only \
41
122k
   || (ZCG(current_persistent_script) && ZCG(current_persistent_script)->corrupted)) { \
42
0
    GC_TYPE_INFO(str) = GC_STRING | (IS_STR_INTERNED << GC_FLAGS_SHIFT); \
43
0
    flags |= (IS_STR_INTERNED << GC_FLAGS_SHIFT); \
44
122k
  } else { \
45
122k
    flags |= ((IS_STR_INTERNED | IS_STR_PERMANENT) << GC_FLAGS_SHIFT); \
46
122k
  } \
47
122k
  GC_TYPE_INFO(str) = flags; \
48
122k
} while (0)
49
50
212k
#define zend_accel_store_string(str) do { \
51
212k
    zend_string *new_str = zend_shared_alloc_get_xlat_entry(str); \
52
212k
    if (new_str) { \
53
90.1k
      zend_string_release_ex(str, 0); \
54
90.1k
      str = new_str; \
55
122k
    } else { \
56
122k
      new_str = zend_shared_memdup_put((void*)str, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \
57
122k
      zend_string_release_ex(str, 0); \
58
122k
      str = new_str; \
59
122k
      zend_string_hash_val(str); \
60
122k
      zend_set_str_gc_flags(str); \
61
122k
    } \
62
212k
  } while (0)
63
#define zend_accel_memdup_string(str) do { \
64
    zend_string *new_str = zend_shared_alloc_get_xlat_entry(str); \
65
    if (new_str) { \
66
      str = new_str; \
67
    } else { \
68
      new_str = zend_shared_memdup_put((void*)str, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \
69
      str = new_str; \
70
      zend_string_hash_val(str); \
71
      zend_set_str_gc_flags(str); \
72
    } \
73
  } while (0)
74
1.49M
#define zend_accel_store_interned_string(str) do { \
75
1.49M
    if (!IS_ACCEL_INTERNED(str)) { \
76
67.8k
      zend_accel_store_string(str); \
77
67.8k
    } \
78
1.49M
  } while (0)
79
#define zend_accel_memdup_interned_string(str) do { \
80
    if (!IS_ACCEL_INTERNED(str)) { \
81
      zend_accel_memdup_string(str); \
82
    } \
83
  } while (0)
84
85
typedef void (*zend_persist_func_t)(zval*);
86
87
static void zend_persist_zval(zval *z);
88
static void zend_persist_op_array(zval *zv);
89
90
static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
91
  {HT_INVALID_IDX, HT_INVALID_IDX};
92
93
static void zend_hash_persist(HashTable *ht)
94
251k
{
95
251k
  uint32_t idx, nIndex;
96
251k
  Bucket *p;
97
98
251k
  HT_FLAGS(ht) |= HASH_FLAG_STATIC_KEYS;
99
251k
  ht->pDestructor = NULL;
100
251k
  ht->nInternalPointer = 0;
101
102
251k
  if (HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) {
103
159k
    if (EXPECTED(!ZCG(current_persistent_script)->corrupted)) {
104
159k
      HT_SET_DATA_ADDR(ht, &ZCSG(uninitialized_bucket));
105
159k
    } else {
106
0
      HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
107
0
    }
108
159k
    return;
109
159k
  }
110
92.6k
  if (ht->nNumUsed == 0) {
111
2
    efree(HT_GET_DATA_ADDR(ht));
112
2
    ht->nTableMask = HT_MIN_MASK;
113
2
    if (EXPECTED(!ZCG(current_persistent_script)->corrupted)) {
114
2
      HT_SET_DATA_ADDR(ht, &ZCSG(uninitialized_bucket));
115
2
    } else {
116
0
      HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
117
0
    }
118
2
    HT_FLAGS(ht) |= HASH_FLAG_UNINITIALIZED;
119
2
    return;
120
2
  }
121
92.6k
  if (HT_IS_PACKED(ht)) {
122
21.7k
    void *data = HT_GET_DATA_ADDR(ht);
123
21.7k
    if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
124
0
      data = zend_shared_memdup(data, HT_PACKED_USED_SIZE(ht));
125
21.7k
    } else {
126
21.7k
      data = zend_shared_memdup_free(data, HT_PACKED_USED_SIZE(ht));
127
21.7k
    }
128
21.7k
    HT_SET_DATA_ADDR(ht, data);
129
70.9k
  } else if (ht->nNumUsed > HT_MIN_SIZE && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) {
130
    /* compact table */
131
20
    void *old_data = HT_GET_DATA_ADDR(ht);
132
20
    Bucket *old_buckets = ht->arData;
133
20
    uint32_t hash_size;
134
135
20
    hash_size = (uint32_t)(-(int32_t)ht->nTableMask);
136
40
    while (hash_size >> 2 > ht->nNumUsed) {
137
20
      hash_size >>= 1;
138
20
    }
139
20
    ht->nTableMask = (uint32_t)(-(int32_t)hash_size);
140
20
    ZEND_ASSERT(((uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
141
20
    HT_SET_DATA_ADDR(ht, ZCG(mem));
142
20
    ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE((hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket))));
143
20
    HT_HASH_RESET(ht);
144
20
    memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket));
145
20
    if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
146
20
      efree(old_data);
147
20
    }
148
149
    /* rehash */
150
308
    for (idx = 0; idx < ht->nNumUsed; idx++) {
151
288
      p = ht->arData + idx;
152
288
      if (Z_TYPE(p->val) == IS_UNDEF) continue;
153
288
      nIndex = p->h | ht->nTableMask;
154
288
      Z_NEXT(p->val) = HT_HASH(ht, nIndex);
155
288
      HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
156
288
    }
157
70.8k
  } else {
158
70.8k
    void *data = ZCG(mem);
159
70.8k
    void *old_data = HT_GET_DATA_ADDR(ht);
160
161
70.8k
    ZEND_ASSERT(((uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
162
70.8k
    ZCG(mem) = (void*)((char*)data + ZEND_ALIGNED_SIZE(HT_USED_SIZE(ht)));
163
70.8k
    memcpy(data, old_data, HT_USED_SIZE(ht));
164
70.8k
    if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
165
70.8k
      efree(old_data);
166
70.8k
    }
167
70.8k
    HT_SET_DATA_ADDR(ht, data);
168
70.8k
  }
169
92.6k
}
170
171
static zend_ast *zend_persist_ast(zend_ast *ast)
172
24.0k
{
173
24.0k
  uint32_t i;
174
24.0k
  zend_ast *node;
175
176
24.0k
  if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
177
14.2k
    zend_ast_zval *copy = zend_shared_memdup(ast, sizeof(zend_ast_zval));
178
14.2k
    zend_persist_zval(&copy->val);
179
14.2k
    node = (zend_ast *) copy;
180
14.2k
  } else if (zend_ast_is_list(ast)) {
181
1.48k
    zend_ast_list *list = zend_ast_get_list(ast);
182
1.48k
    zend_ast_list *copy = zend_shared_memdup(ast,
183
1.48k
      sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
184
3.34k
    for (i = 0; i < list->children; i++) {
185
1.85k
      if (copy->child[i]) {
186
1.85k
        copy->child[i] = zend_persist_ast(copy->child[i]);
187
1.85k
      }
188
1.85k
    }
189
1.48k
    node = (zend_ast *) copy;
190
8.39k
  } else if (ast->kind == ZEND_AST_OP_ARRAY) {
191
66
    zend_ast_op_array *copy = zend_shared_memdup(ast, sizeof(zend_ast_op_array));
192
66
    zval z;
193
66
    ZVAL_PTR(&z, copy->op_array);
194
66
    zend_persist_op_array(&z);
195
66
    copy->op_array = Z_PTR(z);
196
66
    node = (zend_ast *) copy;
197
8.32k
  } else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
198
444
    zend_ast_fcc *copy = zend_shared_memdup(ast, sizeof(zend_ast_fcc));
199
444
    if (!ZCG(current_persistent_script)->corrupted) {
200
444
      ZEND_MAP_PTR_NEW(copy->fptr);
201
444
      copy->attr |= ZEND_PARTIAL_CACHEABLE_IN_SHM;
202
444
    }
203
444
    if (copy->filename) {
204
160
      zend_accel_store_interned_string(copy->filename);
205
160
    }
206
444
    if (copy->name) {
207
160
      zend_accel_store_interned_string(copy->name);
208
160
    }
209
444
    copy->args = zend_persist_ast(copy->args);
210
444
    node = (zend_ast *) copy;
211
7.88k
  } else if (zend_ast_is_decl(ast)) {
212
    /* Not implemented. */
213
0
    ZEND_UNREACHABLE();
214
7.88k
  } else {
215
7.88k
    uint32_t children = zend_ast_get_num_children(ast);
216
7.88k
    node = zend_shared_memdup(ast, zend_ast_size(children));
217
25.8k
    for (i = 0; i < children; i++) {
218
17.9k
      if (node->child[i]) {
219
16.1k
        node->child[i] = zend_persist_ast(node->child[i]);
220
16.1k
      }
221
17.9k
    }
222
7.88k
  }
223
224
24.0k
  return node;
225
24.0k
}
226
227
static void zend_persist_zval(zval *z)
228
1.19M
{
229
1.19M
  void *new_ptr;
230
231
1.19M
  switch (Z_TYPE_P(z)) {
232
736k
    case IS_STRING:
233
736k
      zend_accel_store_interned_string(Z_STR_P(z));
234
736k
      Z_TYPE_FLAGS_P(z) = 0;
235
736k
      break;
236
27.4k
    case IS_ARRAY:
237
27.4k
      new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
238
27.4k
      if (new_ptr) {
239
686
        Z_ARR_P(z) = new_ptr;
240
686
        Z_TYPE_FLAGS_P(z) = 0;
241
26.7k
      } else if (!ZCG(current_persistent_script)->corrupted
242
26.7k
       && zend_accel_in_shm(Z_ARR_P(z))) {
243
        /* pass */
244
26.5k
      } else {
245
26.5k
        HashTable *ht;
246
247
26.5k
        if (!Z_REFCOUNTED_P(z)) {
248
4.53k
          ht = zend_shared_memdup_put(Z_ARR_P(z), sizeof(zend_array));
249
22.0k
        } else {
250
22.0k
          GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
251
22.0k
          ht = zend_shared_memdup_put_free(Z_ARR_P(z), sizeof(zend_array));
252
22.0k
        }
253
26.5k
        Z_ARR_P(z) = ht;
254
26.5k
        zend_hash_persist(ht);
255
26.5k
        if (HT_IS_PACKED(ht)) {
256
18.5k
          zval *zv;
257
258
498k
          ZEND_HASH_PACKED_FOREACH_VAL(ht, zv) {
259
498k
            zend_persist_zval(zv);
260
498k
          } ZEND_HASH_FOREACH_END();
261
18.5k
        } else {
262
8.07k
          Bucket *p;
263
264
38.0k
          ZEND_HASH_MAP_FOREACH_BUCKET(ht, p) {
265
38.0k
            if (p->key) {
266
5.39k
              zend_accel_store_interned_string(p->key);
267
5.39k
            }
268
38.0k
            zend_persist_zval(&p->val);
269
38.0k
          } ZEND_HASH_FOREACH_END();
270
8.07k
        }
271
        /* make immutable array */
272
26.5k
        Z_TYPE_FLAGS_P(z) = 0;
273
26.5k
        GC_SET_REFCOUNT(Z_COUNTED_P(z), 2);
274
26.5k
        GC_ADD_FLAGS(Z_COUNTED_P(z), IS_ARRAY_IMMUTABLE);
275
26.5k
      }
276
27.4k
      break;
277
27.4k
    case IS_CONSTANT_AST:
278
5.88k
      new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
279
5.88k
      if (new_ptr) {
280
58
        Z_AST_P(z) = new_ptr;
281
58
        Z_TYPE_FLAGS_P(z) = 0;
282
5.82k
      } else if (ZCG(current_persistent_script)->corrupted
283
5.82k
       || !zend_accel_in_shm(Z_AST_P(z))) {
284
5.67k
        zend_ast_ref *old_ref = Z_AST_P(z);
285
5.67k
        Z_AST_P(z) = zend_shared_memdup_put(Z_AST_P(z), sizeof(zend_ast_ref));
286
5.67k
        zend_persist_ast(GC_AST(old_ref));
287
5.67k
        Z_TYPE_FLAGS_P(z) = 0;
288
5.67k
        GC_SET_REFCOUNT(Z_COUNTED_P(z), 1);
289
5.67k
        GC_ADD_FLAGS(Z_COUNTED_P(z), GC_IMMUTABLE);
290
5.67k
        efree(old_ref);
291
5.67k
      }
292
5.88k
      break;
293
200
    case IS_PTR:
294
200
      break;
295
426k
    default:
296
426k
      ZEND_ASSERT(Z_TYPE_P(z) < IS_STRING);
297
426k
      break;
298
1.19M
  }
299
1.19M
}
300
301
static HashTable *zend_persist_attributes(HashTable *attributes)
302
3.34k
{
303
3.34k
  uint32_t i;
304
3.34k
  zval *v;
305
306
3.34k
  if (!ZCG(current_persistent_script)->corrupted && zend_accel_in_shm(attributes)) {
307
90
    return attributes;
308
90
  }
309
310
  /* Attributes for trait properties may be shared if preloading is used. */
311
3.25k
  HashTable *xlat = zend_shared_alloc_get_xlat_entry(attributes);
312
3.25k
  if (xlat) {
313
0
    return xlat;
314
0
  }
315
316
3.25k
  zend_hash_persist(attributes);
317
318
15.4k
  ZEND_HASH_PACKED_FOREACH_VAL(attributes, v) {
319
15.4k
    zend_attribute *attr = Z_PTR_P(v);
320
15.4k
    zend_attribute *copy = zend_shared_memdup_put_free(attr, ZEND_ATTRIBUTE_SIZE(attr->argc));
321
322
15.4k
    zend_accel_store_interned_string(copy->name);
323
15.4k
    zend_accel_store_interned_string(copy->lcname);
324
15.4k
    if (copy->validation_error) {
325
128
      zend_accel_store_interned_string(copy->validation_error);
326
128
    }
327
328
15.4k
    for (i = 0; i < copy->argc; i++) {
329
1.45k
      if (copy->args[i].name) {
330
172
        zend_accel_store_interned_string(copy->args[i].name);
331
172
      }
332
1.45k
      zend_persist_zval(&copy->args[i].value);
333
1.45k
    }
334
335
15.4k
    ZVAL_PTR(v, copy);
336
15.4k
  } ZEND_HASH_FOREACH_END();
337
338
3.25k
  HashTable *ptr = zend_shared_memdup_put_free(attributes, sizeof(HashTable));
339
3.25k
  GC_SET_REFCOUNT(ptr, 2);
340
3.25k
  GC_TYPE_INFO(ptr) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT);
341
342
3.25k
  return ptr;
343
3.25k
}
344
345
uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name)
346
36.1k
{
347
36.1k
  uint32_t ret;
348
349
36.1k
  if (zend_string_equals_ci(type_name, ZSTR_KNOWN(ZEND_STR_SELF)) ||
350
36.0k
      zend_string_equals_ci(type_name, ZSTR_KNOWN(ZEND_STR_PARENT))) {
351
170
    return 0;
352
170
  }
353
354
  /* We use type.name.gc.refcount to keep map_ptr of corresponding type */
355
35.9k
  if (ZSTR_HAS_CE_CACHE(type_name)) {
356
33.7k
    return GC_REFCOUNT(type_name);
357
33.7k
  }
358
359
2.20k
  if ((GC_FLAGS(type_name) & GC_IMMUTABLE)
360
2.20k
   && (GC_FLAGS(type_name) & IS_STR_PERMANENT)) {
361
2.20k
    do {
362
2.20k
      ret = ZEND_MAP_PTR_NEW_OFFSET();
363
2.20k
    } while (ret <= 2);
364
2.20k
    GC_SET_REFCOUNT(type_name, ret);
365
2.20k
    GC_ADD_FLAGS(type_name, IS_STR_CLASS_NAME_MAP_PTR);
366
2.20k
    return ret;
367
2.20k
  }
368
369
0
  return 0;
370
2.20k
}
371
372
71.3k
static void zend_persist_type(zend_type *type) {
373
71.3k
  if (ZEND_TYPE_HAS_LIST(*type)) {
374
2.18k
    zend_type_list *list = ZEND_TYPE_LIST(*type);
375
2.18k
    if (ZEND_TYPE_USES_ARENA(*type) || zend_accel_in_shm(list)) {
376
2.18k
      list = zend_shared_memdup_put(list, ZEND_TYPE_LIST_SIZE(list->num_types));
377
2.18k
      ZEND_TYPE_FULL_MASK(*type) &= ~_ZEND_TYPE_ARENA_BIT;
378
2.18k
    } else {
379
0
      list = zend_shared_memdup_put_free(list, ZEND_TYPE_LIST_SIZE(list->num_types));
380
0
    }
381
2.18k
    ZEND_TYPE_SET_PTR(*type, list);
382
2.18k
  }
383
384
71.3k
  zend_type *single_type;
385
144k
  ZEND_TYPE_FOREACH_MUTABLE(*type, single_type) {
386
144k
    if (ZEND_TYPE_HAS_LIST(*single_type)) {
387
650
      zend_persist_type(single_type);
388
650
      continue;
389
650
    }
390
72.7k
    if (ZEND_TYPE_HAS_NAME(*single_type)) {
391
8.77k
      zend_string *type_name = ZEND_TYPE_NAME(*single_type);
392
8.77k
      zend_accel_store_interned_string(type_name);
393
8.77k
      ZEND_TYPE_SET_PTR(*single_type, type_name);
394
8.77k
      if (!ZCG(current_persistent_script)->corrupted) {
395
8.77k
        zend_accel_get_class_name_map_ptr(type_name);
396
8.77k
      }
397
8.77k
    }
398
72.7k
  } ZEND_TYPE_FOREACH_END();
399
71.3k
}
400
401
static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script)
402
121k
{
403
121k
  zend_op *persist_ptr;
404
121k
  zval *orig_literals = NULL;
405
406
121k
  if (op_array->refcount && --(*op_array->refcount) == 0) {
407
114k
    efree(op_array->refcount);
408
114k
  }
409
121k
  op_array->refcount = NULL;
410
411
121k
  if (main_persistent_script) {
412
61.8k
    zend_execute_data *orig_execute_data = EG(current_execute_data);
413
61.8k
    zend_execute_data fake_execute_data;
414
61.8k
    zval *offset;
415
416
61.8k
    memset(&fake_execute_data, 0, sizeof(fake_execute_data));
417
61.8k
    fake_execute_data.func = (zend_function*)op_array;
418
61.8k
    EG(current_execute_data) = &fake_execute_data;
419
61.8k
    if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
420
100
      main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset);
421
100
    }
422
61.8k
    EG(current_execute_data) = orig_execute_data;
423
61.8k
  }
424
425
121k
  if (op_array->function_name) {
426
60.1k
    zend_string *old_name = op_array->function_name;
427
60.1k
    zend_accel_store_interned_string(op_array->function_name);
428
    /* Remember old function name, so it can be released multiple times if shared. */
429
60.1k
    if (op_array->function_name != old_name
430
1.18k
        && !zend_shared_alloc_get_xlat_entry(&op_array->function_name)) {
431
1.18k
      zend_shared_alloc_register_xlat_entry(&op_array->function_name, old_name);
432
1.18k
    }
433
60.1k
  }
434
435
121k
  if (op_array->scope) {
436
32.2k
    zend_class_entry *scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
437
438
32.2k
    if (scope) {
439
32.2k
      op_array->scope = scope;
440
32.2k
    }
441
442
32.2k
    if (op_array->prototype) {
443
4.09k
      zend_function *ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype);
444
445
4.09k
      if (ptr) {
446
935
        op_array->prototype = ptr;
447
935
      }
448
4.09k
    }
449
450
32.2k
    persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
451
32.2k
    if (persist_ptr) {
452
0
      op_array->opcodes = persist_ptr;
453
0
      if (op_array->static_variables) {
454
0
        op_array->static_variables = zend_shared_alloc_get_xlat_entry(op_array->static_variables);
455
0
        ZEND_ASSERT(op_array->static_variables != NULL);
456
0
      }
457
0
      if (op_array->literals) {
458
0
        op_array->literals = zend_shared_alloc_get_xlat_entry(op_array->literals);
459
0
        ZEND_ASSERT(op_array->literals != NULL);
460
0
      }
461
0
      if (op_array->filename) {
462
0
        op_array->filename = zend_shared_alloc_get_xlat_entry(op_array->filename);
463
0
        ZEND_ASSERT(op_array->filename != NULL);
464
0
      }
465
0
      if (op_array->arg_info) {
466
0
        zend_arg_info *arg_info = op_array->arg_info;
467
0
        if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
468
0
          arg_info--;
469
0
        }
470
0
        arg_info = zend_shared_alloc_get_xlat_entry(arg_info);
471
0
        ZEND_ASSERT(arg_info != NULL);
472
0
        if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
473
0
          arg_info++;
474
0
        }
475
0
        op_array->arg_info = arg_info;
476
0
      }
477
0
      if (op_array->live_range) {
478
0
        op_array->live_range = zend_shared_alloc_get_xlat_entry(op_array->live_range);
479
0
        ZEND_ASSERT(op_array->live_range != NULL);
480
0
      }
481
0
      if (op_array->doc_comment) {
482
0
        if (ZCG(accel_directives).save_comments) {
483
0
          op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment);
484
0
          ZEND_ASSERT(op_array->doc_comment != NULL);
485
0
        } else {
486
0
          op_array->doc_comment = NULL;
487
0
        }
488
0
      }
489
0
      if (op_array->attributes) {
490
0
        op_array->attributes = zend_shared_alloc_get_xlat_entry(op_array->attributes);
491
0
        ZEND_ASSERT(op_array->attributes != NULL);
492
0
      }
493
494
0
      if (op_array->try_catch_array) {
495
0
        op_array->try_catch_array = zend_shared_alloc_get_xlat_entry(op_array->try_catch_array);
496
0
        ZEND_ASSERT(op_array->try_catch_array != NULL);
497
0
      }
498
0
      if (op_array->vars) {
499
0
        op_array->vars = zend_shared_alloc_get_xlat_entry(op_array->vars);
500
0
        ZEND_ASSERT(op_array->vars != NULL);
501
0
      }
502
0
      if (op_array->dynamic_func_defs) {
503
0
        op_array->dynamic_func_defs = zend_shared_alloc_get_xlat_entry(op_array->dynamic_func_defs);
504
0
        ZEND_ASSERT(op_array->dynamic_func_defs != NULL);
505
0
      }
506
0
      ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem))));
507
0
      return;
508
0
    }
509
89.7k
  } else {
510
    /* "prototype" may be undefined if "scope" isn't set */
511
89.7k
    op_array->prototype = NULL;
512
89.7k
  }
513
514
121k
  if (op_array->scope
515
32.2k
   && !(op_array->fn_flags & ZEND_ACC_CLOSURE)
516
32.2k
   && (op_array->scope->ce_flags & ZEND_ACC_CACHED)) {
517
5.35k
    return;
518
5.35k
  }
519
520
116k
  if (op_array->static_variables && !zend_accel_in_shm(op_array->static_variables)) {
521
3.38k
    Bucket *p;
522
523
3.38k
    zend_hash_persist(op_array->static_variables);
524
28.4k
    ZEND_HASH_MAP_FOREACH_BUCKET(op_array->static_variables, p) {
525
28.4k
      ZEND_ASSERT(p->key != NULL);
526
28.4k
      zend_accel_store_interned_string(p->key);
527
10.8k
      zend_persist_zval(&p->val);
528
10.8k
    } ZEND_HASH_FOREACH_END();
529
3.38k
    op_array->static_variables = zend_shared_memdup_put_free(op_array->static_variables, sizeof(HashTable));
530
    /* make immutable array */
531
3.38k
    GC_SET_REFCOUNT(op_array->static_variables, 2);
532
3.38k
    GC_TYPE_INFO(op_array->static_variables) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT);
533
3.38k
  }
534
535
116k
  if (op_array->literals) {
536
114k
    zval *p, *end;
537
538
114k
    orig_literals = op_array->literals;
539
#if ZEND_USE_ABS_CONST_ADDR
540
    p = zend_shared_memdup_put_free(op_array->literals, sizeof(zval) * op_array->last_literal);
541
#else
542
114k
    p = zend_shared_memdup_put(op_array->literals, sizeof(zval) * op_array->last_literal);
543
114k
#endif
544
114k
    end = p + op_array->last_literal;
545
114k
    op_array->literals = p;
546
1.01M
    while (p < end) {
547
902k
      zend_persist_zval(p);
548
902k
      p++;
549
902k
    }
550
114k
  }
551
552
116k
  {
553
116k
    zend_op *new_opcodes = zend_shared_memdup_put(op_array->opcodes, sizeof(zend_op) * op_array->last);
554
116k
    zend_op *opline = new_opcodes;
555
116k
    zend_op *end = new_opcodes + op_array->last;
556
557
2.81M
    for (; opline < end ; opline++) {
558
#if ZEND_USE_ABS_CONST_ADDR
559
      if (opline->op1_type == IS_CONST) {
560
        opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
561
        if (opline->opcode == ZEND_SEND_VAL
562
         || opline->opcode == ZEND_SEND_VAL_EX
563
         || opline->opcode == ZEND_QM_ASSIGN) {
564
          /* Update handlers to eliminate REFCOUNTED check */
565
          zend_vm_set_opcode_handler_ex(opline, 1 << Z_TYPE_P(opline->op1.zv), 0, 0);
566
        }
567
      }
568
      if (opline->op2_type == IS_CONST) {
569
        opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
570
      }
571
#else
572
2.69M
      if (opline->op1_type == IS_CONST) {
573
492k
        opline->op1.constant =
574
492k
          (char*)(op_array->literals +
575
492k
            ((zval*)((char*)(op_array->opcodes + (opline - new_opcodes)) +
576
492k
            (int32_t)opline->op1.constant) - orig_literals)) -
577
492k
          (char*)opline;
578
492k
        if (opline->opcode == ZEND_SEND_VAL
579
428k
         || opline->opcode == ZEND_SEND_VAL_EX
580
414k
         || opline->opcode == ZEND_QM_ASSIGN) {
581
90.0k
          zend_vm_set_opcode_handler_ex(opline, 0, 0, 0);
582
90.0k
        }
583
492k
      }
584
2.69M
      if (opline->op2_type == IS_CONST) {
585
693k
        opline->op2.constant =
586
693k
          (char*)(op_array->literals +
587
693k
            ((zval*)((char*)(op_array->opcodes + (opline - new_opcodes)) +
588
693k
            (int32_t)opline->op2.constant) - orig_literals)) -
589
693k
          (char*)opline;
590
693k
      }
591
2.69M
#endif
592
#if ZEND_USE_ABS_JMP_ADDR
593
      if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
594
        /* fix jumps to point to new array */
595
        switch (opline->opcode) {
596
          case ZEND_JMP:
597
          case ZEND_FAST_CALL:
598
            opline->op1.jmp_addr = &new_opcodes[opline->op1.jmp_addr - op_array->opcodes];
599
            break;
600
          case ZEND_JMPZ:
601
          case ZEND_JMPNZ:
602
          case ZEND_JMPZ_EX:
603
          case ZEND_JMPNZ_EX:
604
          case ZEND_JMP_SET:
605
          case ZEND_COALESCE:
606
          case ZEND_FE_RESET_R:
607
          case ZEND_FE_RESET_RW:
608
          case ZEND_ASSERT_CHECK:
609
          case ZEND_JMP_NULL:
610
          case ZEND_BIND_INIT_STATIC_OR_JMP:
611
          case ZEND_JMP_FRAMELESS:
612
            opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes];
613
            break;
614
          case ZEND_CATCH:
615
            if (!(opline->extended_value & ZEND_LAST_CATCH)) {
616
              opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes];
617
            }
618
            break;
619
          case ZEND_FE_FETCH_R:
620
          case ZEND_FE_FETCH_RW:
621
          case ZEND_SWITCH_LONG:
622
          case ZEND_SWITCH_STRING:
623
          case ZEND_MATCH:
624
            /* relative extended_value don't have to be changed */
625
            break;
626
        }
627
      }
628
#endif
629
2.69M
      if (opline->opcode == ZEND_OP_DATA && (opline-1)->opcode == ZEND_DECLARE_ATTRIBUTED_CONST) {
630
200
        zval *literal = RT_CONSTANT(opline, opline->op1);
631
200
        HashTable *attributes = Z_PTR_P(literal);
632
200
        attributes = zend_persist_attributes(attributes);
633
200
        ZVAL_PTR(literal, attributes);
634
200
      }
635
636
2.69M
      if (opline->opcode == ZEND_CALLABLE_CONVERT_PARTIAL) {
637
1.27k
        if (!ZCG(current_persistent_script)->corrupted) {
638
1.27k
          opline->extended_value |= ZEND_PARTIAL_CACHEABLE_IN_SHM;
639
1.27k
        }
640
1.27k
      }
641
2.69M
    }
642
643
116k
    efree(op_array->opcodes);
644
116k
    op_array->opcodes = new_opcodes;
645
116k
  }
646
647
116k
  if (op_array->filename) {
648
116k
    zend_accel_store_string(op_array->filename);
649
116k
  }
650
651
116k
  if (op_array->arg_info) {
652
29.6k
    zend_arg_info *arg_info = op_array->arg_info;
653
29.6k
    uint32_t num_args = op_array->num_args;
654
29.6k
    uint32_t i;
655
656
29.6k
    if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
657
9.50k
      arg_info--;
658
9.50k
      num_args++;
659
9.50k
    }
660
29.6k
    if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
661
740
      num_args++;
662
740
    }
663
29.6k
    arg_info = zend_shared_memdup_put_free(arg_info, sizeof(zend_arg_info) * num_args);
664
75.7k
    for (i = 0; i < num_args; i++) {
665
46.1k
      if (arg_info[i].name) {
666
36.6k
        zend_accel_store_interned_string(arg_info[i].name);
667
36.6k
      }
668
46.1k
      zend_persist_type(&arg_info[i].type);
669
46.1k
      if (arg_info[i].doc_comment) {
670
0
        zend_accel_store_interned_string(arg_info[i].doc_comment);
671
0
      }
672
46.1k
    }
673
29.6k
    if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
674
9.50k
      arg_info++;
675
9.50k
    }
676
29.6k
    op_array->arg_info = arg_info;
677
29.6k
  }
678
679
116k
  if (op_array->live_range) {
680
56.7k
    op_array->live_range = zend_shared_memdup_put_free(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
681
56.7k
  }
682
683
116k
  if (op_array->doc_comment) {
684
46
    if (ZCG(accel_directives).save_comments) {
685
46
      zend_accel_store_interned_string(op_array->doc_comment);
686
46
    } else {
687
0
      zend_string_release_ex(op_array->doc_comment, 0);
688
0
      op_array->doc_comment = NULL;
689
0
    }
690
46
  }
691
692
116k
  if (op_array->attributes) {
693
1.11k
    op_array->attributes = zend_persist_attributes(op_array->attributes);
694
1.11k
  }
695
696
116k
  if (op_array->try_catch_array) {
697
21.1k
    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);
698
21.1k
  }
699
700
116k
  if (op_array->vars) {
701
79.9k
    int i;
702
79.9k
    op_array->vars = zend_shared_memdup_put_free(op_array->vars, sizeof(zend_string*) * op_array->last_var);
703
467k
    for (i = 0; i < op_array->last_var; i++) {
704
387k
      zend_accel_store_interned_string(op_array->vars[i]);
705
387k
    }
706
79.9k
  }
707
708
116k
  if (op_array->num_dynamic_func_defs) {
709
6.88k
    op_array->dynamic_func_defs = zend_shared_memdup_put_free(
710
6.88k
      op_array->dynamic_func_defs, sizeof(zend_function *) * op_array->num_dynamic_func_defs);
711
17.1k
    for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
712
10.2k
      zval tmp;
713
10.2k
      ZVAL_PTR(&tmp, op_array->dynamic_func_defs[i]);
714
10.2k
      zend_persist_op_array(&tmp);
715
10.2k
      op_array->dynamic_func_defs[i] = Z_PTR(tmp);
716
10.2k
    }
717
6.88k
  }
718
719
116k
  ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem))));
720
116k
}
721
722
static void zend_persist_op_array(zval *zv)
723
27.8k
{
724
27.8k
  zend_op_array *op_array = Z_PTR_P(zv);
725
27.8k
  zend_op_array *old_op_array;
726
27.8k
  ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
727
728
27.8k
  old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
729
27.8k
  if (!old_op_array) {
730
27.8k
    op_array = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_op_array));
731
27.8k
    zend_persist_op_array_ex(op_array, NULL);
732
27.8k
    if (!ZCG(current_persistent_script)->corrupted) {
733
27.8k
      op_array->fn_flags |= ZEND_ACC_IMMUTABLE;
734
27.8k
      ZEND_MAP_PTR_NEW(op_array->run_time_cache);
735
27.8k
      if (op_array->static_variables) {
736
3.14k
        ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
737
3.14k
      }
738
27.8k
    }
739
27.8k
#ifdef HAVE_JIT
740
27.8k
    if (JIT_G(on)
741
0
     && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS
742
0
     && (!ZCG(current_persistent_script)
743
0
      || !ZCG(current_persistent_script)->corrupted)) {
744
0
      zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
745
0
    }
746
27.8k
#endif
747
27.8k
  } else {
748
    /* This can happen during preloading, if a dynamic function definition is declared. */
749
0
    Z_PTR_P(zv) = old_op_array;
750
0
  }
751
27.8k
}
752
753
static zend_op_array *zend_persist_class_method(zend_op_array *op_array, const zend_class_entry *ce)
754
39.7k
{
755
39.7k
  zend_op_array *old_op_array;
756
757
39.7k
  if (op_array->type != ZEND_USER_FUNCTION) {
758
4.81k
    ZEND_ASSERT(op_array->type == ZEND_INTERNAL_FUNCTION);
759
4.81k
    if (op_array->fn_flags & ZEND_ACC_ARENA_ALLOCATED) {
760
4.81k
      old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
761
4.81k
      if (old_op_array) {
762
0
        return old_op_array;
763
4.81k
      } else {
764
4.81k
        op_array = zend_shared_memdup_put(op_array, sizeof(zend_internal_function));
765
4.81k
        if (op_array->scope) {
766
4.81k
          void *persist_ptr;
767
768
4.81k
          if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->scope))) {
769
0
            op_array->scope = (zend_class_entry*)persist_ptr;
770
0
          }
771
4.81k
          if (op_array->prototype) {
772
2.16k
            if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
773
0
              op_array->prototype = (zend_function*)persist_ptr;
774
0
            }
775
2.16k
          }
776
4.81k
        }
777
        // Real dynamically created internal functions like enum methods must have their own run_time_cache pointer. They're always on the same scope as their defining class.
778
        // However, copies - as caused by inheritance of internal methods - must retain the original run_time_cache pointer, shared with the source function.
779
4.81k
        if (!op_array->scope || (op_array->scope == ce && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))) {
780
0
          if (op_array->fn_flags & ZEND_ACC_PRELOADED) {
781
0
            ZEND_MAP_PTR_NEW_STATIC(op_array->run_time_cache);
782
0
          } else {
783
0
            ZEND_MAP_PTR_NEW(op_array->run_time_cache);
784
0
          }
785
0
        }
786
4.81k
      }
787
4.81k
    }
788
4.81k
    return op_array;
789
4.81k
  }
790
791
34.9k
  if ((op_array->fn_flags & ZEND_ACC_IMMUTABLE)
792
558
   && !ZCG(current_persistent_script)->corrupted
793
558
   && zend_accel_in_shm(op_array)) {
794
550
    zend_shared_alloc_register_xlat_entry(op_array, op_array);
795
550
    return op_array;
796
550
  }
797
798
34.3k
  old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
799
34.3k
  if (old_op_array) {
800
2.14k
    if (op_array->refcount && --(*op_array->refcount) == 0) {
801
1.83k
      efree(op_array->refcount);
802
1.83k
    }
803
804
    /* If op_array is shared, the function name refcount is still incremented for each use,
805
     * so we need to release it here. We remembered the original function name in xlat. */
806
2.14k
    zend_string *old_function_name =
807
2.14k
      zend_shared_alloc_get_xlat_entry(&old_op_array->function_name);
808
2.14k
    if (old_function_name) {
809
20
      zend_string_release_ex(old_function_name, 0);
810
20
    }
811
2.14k
    return old_op_array;
812
2.14k
  }
813
814
32.2k
  op_array = zend_shared_memdup_put(op_array, sizeof(zend_op_array));
815
32.2k
  zend_persist_op_array_ex(op_array, NULL);
816
32.2k
  if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
817
32.2k
    op_array->fn_flags |= ZEND_ACC_IMMUTABLE;
818
32.2k
    if (ce->ce_flags & ZEND_ACC_LINKED) {
819
27.2k
      ZEND_MAP_PTR_NEW(op_array->run_time_cache);
820
27.2k
      if (op_array->static_variables) {
821
228
        ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
822
228
      }
823
27.2k
    } else {
824
5.04k
      ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
825
5.04k
      ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL);
826
5.04k
    }
827
32.2k
  }
828
32.2k
  return op_array;
829
34.3k
}
830
831
static zend_property_info *zend_persist_property_info(zend_property_info *prop)
832
19.2k
{
833
19.2k
  zend_class_entry *ce;
834
19.2k
  prop = zend_shared_memdup_put(prop, sizeof(zend_property_info));
835
19.2k
  ce = zend_shared_alloc_get_xlat_entry(prop->ce);
836
19.2k
  if (ce) {
837
19.2k
    prop->ce = ce;
838
19.2k
  }
839
19.2k
  zend_accel_store_interned_string(prop->name);
840
19.2k
  if (prop->doc_comment) {
841
360
    if (ZCG(accel_directives).save_comments) {
842
360
      zend_accel_store_interned_string(prop->doc_comment);
843
360
    } else {
844
0
      if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
845
0
        zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
846
0
      }
847
0
      zend_string_release_ex(prop->doc_comment, 0);
848
0
      prop->doc_comment = NULL;
849
0
    }
850
360
  }
851
19.2k
  if (prop->attributes) {
852
202
    prop->attributes = zend_persist_attributes(prop->attributes);
853
202
  }
854
19.2k
  if (prop->prototype) {
855
19.2k
    const zend_property_info *new_prototype = (const zend_property_info *) zend_shared_alloc_get_xlat_entry(prop->prototype);
856
19.2k
    if (new_prototype) {
857
19.1k
      prop->prototype = new_prototype;
858
19.1k
    }
859
19.2k
  }
860
19.2k
  if (prop->hooks) {
861
1.97k
    prop->hooks = zend_shared_memdup_put(prop->hooks, ZEND_PROPERTY_HOOK_STRUCT_SIZE);
862
5.91k
    for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
863
3.94k
      if (prop->hooks[i]) {
864
2.55k
        zend_op_array *hook = zend_persist_class_method(&prop->hooks[i]->op_array, ce);
865
2.55k
#ifdef HAVE_JIT
866
2.55k
        if (JIT_G(on)
867
0
         && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS
868
0
         && (!ZCG(current_persistent_script)
869
0
          || !ZCG(current_persistent_script)->corrupted)) {
870
0
          if (hook->scope == ce && !(hook->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
871
0
            zend_jit_op_array(hook, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
872
0
          }
873
0
        }
874
2.55k
#endif
875
2.55k
        const zend_property_info *new_prop_info = (const zend_property_info *) zend_shared_alloc_get_xlat_entry(hook->prop_info);
876
2.55k
        if (new_prop_info) {
877
2.49k
          hook->prop_info = new_prop_info;
878
2.49k
        }
879
2.55k
        prop->hooks[i] = (zend_function *) hook;
880
2.55k
      }
881
3.94k
    }
882
1.97k
  }
883
19.2k
  zend_persist_type(&prop->type);
884
19.2k
  return prop;
885
19.2k
}
886
887
static void zend_persist_class_constant(zval *zv)
888
6.49k
{
889
6.49k
  const zend_class_constant *orig_c = Z_PTR_P(zv);
890
6.49k
  zend_class_constant *c = zend_shared_alloc_get_xlat_entry(orig_c);
891
6.49k
  zend_class_entry *ce;
892
893
6.49k
  if (c) {
894
260
    Z_PTR_P(zv) = c;
895
260
    return;
896
6.23k
  } else if (((orig_c->ce->ce_flags & ZEND_ACC_IMMUTABLE) && !(Z_CONSTANT_FLAGS(orig_c->value) & CONST_OWNED))
897
6.08k
   || orig_c->ce->type == ZEND_INTERNAL_CLASS) {
898
    /* Class constant comes from a different file in shm or internal class, keep existing pointer. */
899
974
    return;
900
5.25k
  } else if (!ZCG(current_persistent_script)->corrupted
901
5.25k
   && zend_accel_in_shm(Z_PTR_P(zv))) {
902
0
    return;
903
0
  }
904
5.25k
  c = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_class_constant));
905
5.25k
  zend_persist_zval(&c->value);
906
5.25k
  ce = zend_shared_alloc_get_xlat_entry(c->ce);
907
5.25k
  if (ce) {
908
5.23k
    c->ce = ce;
909
5.23k
  }
910
5.25k
  if (c->doc_comment) {
911
30
    if (ZCG(accel_directives).save_comments) {
912
30
      zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
913
30
      if (doc_comment) {
914
0
        c->doc_comment = doc_comment;
915
30
      } else {
916
30
        zend_accel_store_interned_string(c->doc_comment);
917
30
      }
918
30
    } else {
919
0
      zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
920
0
      if (!doc_comment) {
921
0
        zend_shared_alloc_register_xlat_entry(c->doc_comment, c->doc_comment);
922
0
        zend_string_release_ex(c->doc_comment, 0);
923
0
      }
924
0
      c->doc_comment = NULL;
925
0
    }
926
30
  }
927
5.25k
  if (c->attributes) {
928
342
    c->attributes = zend_persist_attributes(c->attributes);
929
342
  }
930
5.25k
  zend_persist_type(&c->type);
931
5.25k
}
932
933
zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce)
934
31.6k
{
935
31.6k
  Bucket *p;
936
31.6k
  zend_class_entry *ce = orig_ce;
937
938
31.6k
  if (ce->type == ZEND_USER_CLASS) {
939
    /* The same zend_class_entry may be reused by class_alias */
940
31.6k
    zend_class_entry *new_ce = zend_shared_alloc_get_xlat_entry(ce);
941
31.6k
    if (new_ce) {
942
0
      return new_ce;
943
0
    }
944
31.6k
    ce = zend_shared_memdup_put(ce, sizeof(zend_class_entry));
945
31.6k
    if (EXPECTED(!ZCG(current_persistent_script)->corrupted)) {
946
31.6k
      ce->ce_flags |= ZEND_ACC_IMMUTABLE;
947
31.6k
      if ((ce->ce_flags & ZEND_ACC_LINKED)
948
25.8k
       && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
949
908
        ZEND_MAP_PTR_NEW(ce->mutable_data);
950
30.7k
      } else {
951
30.7k
        ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
952
30.7k
      }
953
31.6k
    } else {
954
0
      ce->ce_flags |= ZEND_ACC_FILE_CACHED;
955
0
    }
956
31.6k
    ce->inheritance_cache = NULL;
957
958
31.6k
    if (!(ce->ce_flags & ZEND_ACC_CACHED)) {
959
28.2k
      if (ZSTR_HAS_CE_CACHE(ce->name)) {
960
25.7k
        ZSTR_SET_CE_CACHE_EX(ce->name, NULL, 0);
961
25.7k
      }
962
28.2k
      zend_accel_store_interned_string(ce->name);
963
28.2k
      if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS)
964
27.3k
       && !ZCG(current_persistent_script)->corrupted) {
965
27.3k
        zend_accel_get_class_name_map_ptr(ce->name);
966
27.3k
      }
967
28.2k
      if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_LINKED)) {
968
1.39k
        zend_accel_store_interned_string(ce->parent_name);
969
1.39k
      }
970
28.2k
    }
971
972
31.6k
    zend_hash_persist(&ce->function_table);
973
137k
    ZEND_HASH_MAP_FOREACH_BUCKET(&ce->function_table, p) {
974
137k
      ZEND_ASSERT(p->key != NULL);
975
137k
      zend_accel_store_interned_string(p->key);
976
37.2k
      Z_PTR(p->val) = zend_persist_class_method(Z_PTR(p->val), ce);
977
37.2k
    } ZEND_HASH_FOREACH_END();
978
31.6k
    HT_FLAGS(&ce->function_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
979
31.6k
    if (ce->default_properties_table) {
980
11.1k
        int i;
981
982
11.1k
      ce->default_properties_table = zend_shared_memdup_free(ce->default_properties_table, sizeof(zval) * ce->default_properties_count);
983
29.4k
      for (i = 0; i < ce->default_properties_count; i++) {
984
18.3k
        zend_persist_zval(&ce->default_properties_table[i]);
985
18.3k
      }
986
11.1k
    }
987
31.6k
    if (ce->default_static_members_table) {
988
1.99k
      ce->default_static_members_table = zend_shared_memdup_free(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count);
989
990
      /* Persist only static properties in this class.
991
       * Static properties from parent classes will be handled in class_copy_ctor and are marked with IS_INDIRECT */
992
5.50k
      for (uint32_t i = 0; i < ce->default_static_members_count; i++) {
993
3.51k
        if (Z_TYPE(ce->default_static_members_table[i]) != IS_INDIRECT) {
994
3.06k
          zend_persist_zval(&ce->default_static_members_table[i]);
995
3.06k
        }
996
3.51k
      }
997
1.99k
      if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
998
1.99k
        if (ce->ce_flags & ZEND_ACC_LINKED) {
999
1.90k
          ZEND_MAP_PTR_NEW(ce->static_members_table);
1000
1.90k
        } else {
1001
84
          ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
1002
84
        }
1003
1.99k
      }
1004
1.99k
    }
1005
1006
31.6k
    zend_hash_persist(&ce->constants_table);
1007
76.2k
    ZEND_HASH_MAP_FOREACH_BUCKET(&ce->constants_table, p) {
1008
76.2k
      ZEND_ASSERT(p->key != NULL);
1009
76.2k
      zend_accel_store_interned_string(p->key);
1010
6.49k
      zend_persist_class_constant(&p->val);
1011
6.49k
    } ZEND_HASH_FOREACH_END();
1012
31.6k
    HT_FLAGS(&ce->constants_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
1013
1014
31.6k
    zend_hash_persist(&ce->properties_info);
1015
108k
    ZEND_HASH_MAP_FOREACH_BUCKET(&ce->properties_info, p) {
1016
108k
      zend_property_info *prop = Z_PTR(p->val);
1017
108k
      ZEND_ASSERT(p->key != NULL);
1018
108k
      zend_accel_store_interned_string(p->key);
1019
22.6k
      if (prop->ce == orig_ce) {
1020
19.2k
        Z_PTR(p->val) = zend_persist_property_info(prop);
1021
19.2k
      } else {
1022
3.33k
        prop = zend_shared_alloc_get_xlat_entry(prop);
1023
3.33k
        if (prop) {
1024
1.61k
          Z_PTR(p->val) = prop;
1025
1.71k
        } else {
1026
          /* This can happen if preloading is used and we inherit a property from an
1027
           * internal class. In that case we should keep pointing to the internal
1028
           * property, without any adjustments. */
1029
1.71k
        }
1030
3.33k
      }
1031
22.6k
    } ZEND_HASH_FOREACH_END();
1032
31.6k
    HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
1033
1034
31.6k
    if (ce->properties_info_table) {
1035
9.47k
      int i;
1036
1037
9.47k
      size_t size = sizeof(zend_property_info *) * ce->default_properties_count;
1038
9.47k
      ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
1039
9.47k
      ce->properties_info_table = zend_shared_memdup(
1040
9.47k
        ce->properties_info_table, size);
1041
1042
25.5k
      for (i = 0; i < ce->default_properties_count; i++) {
1043
16.0k
        if (ce->properties_info_table[i]) {
1044
15.6k
          zend_property_info *prop_info = zend_shared_alloc_get_xlat_entry(
1045
15.6k
            ce->properties_info_table[i]);
1046
15.6k
          if (prop_info) {
1047
14.2k
            ce->properties_info_table[i] = prop_info;
1048
14.2k
          }
1049
15.6k
        }
1050
16.0k
      }
1051
9.47k
    }
1052
1053
31.6k
    if (ce->iterator_funcs_ptr) {
1054
314
      ce->iterator_funcs_ptr = zend_shared_memdup(ce->iterator_funcs_ptr, sizeof(zend_class_iterator_funcs));
1055
314
    }
1056
31.6k
    if (ce->arrayaccess_funcs_ptr) {
1057
376
      ce->arrayaccess_funcs_ptr = zend_shared_memdup(ce->arrayaccess_funcs_ptr, sizeof(zend_class_arrayaccess_funcs));
1058
376
    }
1059
1060
31.6k
    if (ce->ce_flags & ZEND_ACC_CACHED) {
1061
3.40k
      return ce;
1062
3.40k
    }
1063
1064
28.2k
    ce->ce_flags |= ZEND_ACC_CACHED;
1065
1066
28.2k
    if (ce->info.user.filename) {
1067
28.2k
      zend_accel_store_string(ce->info.user.filename);
1068
28.2k
    }
1069
1070
28.2k
    if (ce->doc_comment) {
1071
40
      if (ZCG(accel_directives).save_comments) {
1072
40
        zend_accel_store_interned_string(ce->doc_comment);
1073
40
      } else {
1074
0
        if (!zend_shared_alloc_get_xlat_entry(ce->doc_comment)) {
1075
0
          zend_shared_alloc_register_xlat_entry(ce->doc_comment, ce->doc_comment);
1076
0
          zend_string_release_ex(ce->doc_comment, 0);
1077
0
        }
1078
0
        ce->doc_comment = NULL;
1079
0
      }
1080
40
    }
1081
1082
28.2k
    if (ce->attributes) {
1083
1.48k
      ce->attributes = zend_persist_attributes(ce->attributes);
1084
1.48k
    }
1085
1086
28.2k
    if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_LINKED)) {
1087
3.45k
      uint32_t i = 0;
1088
1089
7.69k
      for (i = 0; i < ce->num_interfaces; i++) {
1090
4.24k
        zend_accel_store_interned_string(ce->interface_names[i].name);
1091
4.24k
        zend_accel_store_interned_string(ce->interface_names[i].lc_name);
1092
4.24k
      }
1093
3.45k
      ce->interface_names = zend_shared_memdup_free(ce->interface_names, sizeof(zend_class_name) * ce->num_interfaces);
1094
3.45k
    }
1095
1096
28.2k
    if (ce->num_traits) {
1097
1.49k
      uint32_t i = 0;
1098
1099
3.38k
      for (i = 0; i < ce->num_traits; i++) {
1100
1.89k
        zend_accel_store_interned_string(ce->trait_names[i].name);
1101
1.89k
        zend_accel_store_interned_string(ce->trait_names[i].lc_name);
1102
1.89k
      }
1103
1.49k
      ce->trait_names = zend_shared_memdup_free(ce->trait_names, sizeof(zend_class_name) * ce->num_traits);
1104
1105
1.49k
      i = 0;
1106
1.49k
      if (ce->trait_aliases) {
1107
676
        while (ce->trait_aliases[i]) {
1108
450
          if (ce->trait_aliases[i]->trait_method.method_name) {
1109
450
            zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method.method_name);
1110
450
          }
1111
450
          if (ce->trait_aliases[i]->trait_method.class_name) {
1112
176
            zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method.class_name);
1113
176
          }
1114
1115
450
          if (ce->trait_aliases[i]->alias) {
1116
304
            zend_accel_store_interned_string(ce->trait_aliases[i]->alias);
1117
304
          }
1118
1119
450
          ce->trait_aliases[i] = zend_shared_memdup_free(ce->trait_aliases[i], sizeof(zend_trait_alias));
1120
450
          i++;
1121
450
        }
1122
1123
226
        ce->trait_aliases = zend_shared_memdup_free(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1));
1124
226
      }
1125
1126
1.49k
      if (ce->trait_precedences) {
1127
84
        uint32_t j;
1128
1129
84
        i = 0;
1130
190
        while (ce->trait_precedences[i]) {
1131
106
          zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method.method_name);
1132
106
          zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method.class_name);
1133
1134
218
          for (j = 0; j < ce->trait_precedences[i]->num_excludes; j++) {
1135
112
            zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_class_names[j]);
1136
112
          }
1137
1138
106
          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*));
1139
106
          i++;
1140
106
        }
1141
84
        ce->trait_precedences = zend_shared_memdup_free(
1142
84
          ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
1143
84
      }
1144
1.49k
    }
1145
1146
28.2k
    ZEND_ASSERT(ce->backed_enum_table == NULL);
1147
28.2k
  }
1148
1149
28.2k
  return ce;
1150
31.6k
}
1151
1152
void zend_update_parent_ce(zend_class_entry *ce)
1153
31.6k
{
1154
31.6k
  if (ce->ce_flags & ZEND_ACC_LINKED) {
1155
25.8k
    if (ce->parent) {
1156
3.91k
      int i, end;
1157
3.91k
      zend_class_entry *parent = ce->parent;
1158
1159
3.91k
      if (parent->type == ZEND_USER_CLASS) {
1160
3.48k
        zend_class_entry *p = zend_shared_alloc_get_xlat_entry(parent);
1161
1162
3.48k
        if (p) {
1163
2.80k
          ce->parent = parent = p;
1164
2.80k
        }
1165
3.48k
      }
1166
1167
      /* Create indirections to static properties from parent classes */
1168
3.91k
      i = parent->default_static_members_count - 1;
1169
4.20k
      while (parent && parent->default_static_members_table) {
1170
296
        end = parent->parent ? parent->parent->default_static_members_count : 0;
1171
746
        for (; i >= end; i--) {
1172
450
          zval *p = &ce->default_static_members_table[i];
1173
          /* The static property may have been overridden by a trait
1174
           * during inheritance. In that case, the property default
1175
           * value is replaced by zend_declare_typed_property() at the
1176
           * property index of the parent property. Make sure we only
1177
           * point to the parent property value if the child value was
1178
           * already indirect. */
1179
450
          if (Z_TYPE_P(p) == IS_INDIRECT) {
1180
450
            ZVAL_INDIRECT(p, &parent->default_static_members_table[i]);
1181
450
          }
1182
450
        }
1183
1184
296
        parent = parent->parent;
1185
296
      }
1186
3.91k
    }
1187
1188
25.8k
    if (ce->num_interfaces) {
1189
2.39k
      uint32_t i = 0;
1190
1191
2.39k
      ce->interfaces = zend_shared_memdup_free(ce->interfaces, sizeof(zend_class_entry*) * ce->num_interfaces);
1192
5.78k
      for (i = 0; i < ce->num_interfaces; i++) {
1193
3.39k
        if (ce->interfaces[i]->type == ZEND_USER_CLASS) {
1194
1.19k
          zend_class_entry *tmp = zend_shared_alloc_get_xlat_entry(ce->interfaces[i]);
1195
1.19k
          if (tmp != NULL) {
1196
0
            ce->interfaces[i] = tmp;
1197
0
          }
1198
1.19k
        }
1199
3.39k
      }
1200
2.39k
    }
1201
1202
25.8k
    if (ce->iterator_funcs_ptr) {
1203
314
      memset(ce->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
1204
314
      if (zend_class_implements_interface(ce, zend_ce_aggregate)) {
1205
200
        ce->iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&ce->function_table, "getiterator", sizeof("getiterator") - 1);
1206
200
      }
1207
314
      if (zend_class_implements_interface(ce, zend_ce_iterator)) {
1208
114
        ce->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&ce->function_table, "rewind", sizeof("rewind") - 1);
1209
114
        ce->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&ce->function_table, "valid", sizeof("valid") - 1);
1210
114
        ce->iterator_funcs_ptr->zf_key = zend_hash_find_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_KEY));
1211
114
        ce->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&ce->function_table, "current", sizeof("current") - 1);
1212
114
        ce->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&ce->function_table, "next", sizeof("next") - 1);
1213
114
      }
1214
314
    }
1215
1216
25.8k
    if (ce->arrayaccess_funcs_ptr) {
1217
376
      ZEND_ASSERT(zend_class_implements_interface(ce, zend_ce_arrayaccess));
1218
376
      ce->arrayaccess_funcs_ptr->zf_offsetget = zend_hash_str_find_ptr(&ce->function_table, "offsetget", sizeof("offsetget") - 1);
1219
376
      ce->arrayaccess_funcs_ptr->zf_offsetexists = zend_hash_str_find_ptr(&ce->function_table, "offsetexists", sizeof("offsetexists") - 1);
1220
376
      ce->arrayaccess_funcs_ptr->zf_offsetset = zend_hash_str_find_ptr(&ce->function_table, "offsetset", sizeof("offsetset") - 1);
1221
376
      ce->arrayaccess_funcs_ptr->zf_offsetunset = zend_hash_str_find_ptr(&ce->function_table, "offsetunset", sizeof("offsetunset") - 1);
1222
376
    }
1223
25.8k
  }
1224
1225
  /* update methods */
1226
31.6k
  if (ce->constructor) {
1227
4.36k
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->constructor);
1228
4.36k
    if (tmp != NULL) {
1229
4.16k
      ce->constructor = tmp;
1230
4.16k
    }
1231
4.36k
  }
1232
31.6k
  if (ce->destructor) {
1233
1.94k
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->destructor);
1234
1.94k
    if (tmp != NULL) {
1235
1.94k
      ce->destructor = tmp;
1236
1.94k
    }
1237
1.94k
  }
1238
31.6k
  if (ce->clone) {
1239
420
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->clone);
1240
420
    if (tmp != NULL) {
1241
264
      ce->clone = tmp;
1242
264
    }
1243
420
  }
1244
31.6k
  if (ce->__get) {
1245
1.22k
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__get);
1246
1.22k
    if (tmp != NULL) {
1247
1.22k
      ce->__get = tmp;
1248
1.22k
    }
1249
1.22k
  }
1250
31.6k
  if (ce->__set) {
1251
831
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__set);
1252
831
    if (tmp != NULL) {
1253
831
      ce->__set = tmp;
1254
831
    }
1255
831
  }
1256
31.6k
  if (ce->__call) {
1257
732
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__call);
1258
732
    if (tmp != NULL) {
1259
732
      ce->__call = tmp;
1260
732
    }
1261
732
  }
1262
31.6k
  if (ce->__serialize) {
1263
218
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__serialize);
1264
218
    if (tmp != NULL) {
1265
68
      ce->__serialize = tmp;
1266
68
    }
1267
218
  }
1268
31.6k
  if (ce->__unserialize) {
1269
214
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__unserialize);
1270
214
    if (tmp != NULL) {
1271
64
      ce->__unserialize = tmp;
1272
64
    }
1273
214
  }
1274
31.6k
  if (ce->__isset) {
1275
508
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__isset);
1276
508
    if (tmp != NULL) {
1277
508
      ce->__isset = tmp;
1278
508
    }
1279
508
  }
1280
31.6k
  if (ce->__unset) {
1281
190
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__unset);
1282
190
    if (tmp != NULL) {
1283
190
      ce->__unset = tmp;
1284
190
    }
1285
190
  }
1286
31.6k
  if (ce->__tostring) {
1287
1.32k
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__tostring);
1288
1.32k
    if (tmp != NULL) {
1289
1.17k
      ce->__tostring = tmp;
1290
1.17k
    }
1291
1.32k
  }
1292
31.6k
  if (ce->__callstatic) {
1293
448
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
1294
448
    if (tmp != NULL) {
1295
448
      ce->__callstatic = tmp;
1296
448
    }
1297
448
  }
1298
31.6k
  if (ce->__debugInfo) {
1299
174
    zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
1300
174
    if (tmp != NULL) {
1301
120
      ce->__debugInfo = tmp;
1302
120
    }
1303
174
  }
1304
31.6k
}
1305
1306
#ifdef HAVE_JIT
1307
static void zend_accel_persist_jit_op_array(zend_op_array *op_array, const zend_class_entry *ce)
1308
0
{
1309
0
  if (op_array->type == ZEND_USER_FUNCTION) {
1310
0
    if (op_array->scope == ce
1311
0
     && !(op_array->fn_flags & ZEND_ACC_ABSTRACT)
1312
0
     && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
1313
0
      zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
1314
0
      for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
1315
0
        zend_jit_op_array(op_array->dynamic_func_defs[i], ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
1316
0
      }
1317
0
    }
1318
0
  }
1319
0
}
1320
1321
static void zend_accel_persist_link_func_info(zend_op_array *op_array, const zend_class_entry *ce)
1322
0
{
1323
0
  if (op_array->type == ZEND_USER_FUNCTION
1324
0
   && !(op_array->fn_flags & ZEND_ACC_ABSTRACT)) {
1325
0
    if ((op_array->scope != ce
1326
0
     || (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))
1327
0
      && (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC
1328
0
      || JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST
1329
0
      || JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS
1330
0
      || JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE)) {
1331
0
      void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
1332
1333
0
      if (jit_extension) {
1334
0
        ZEND_SET_FUNC_INFO(op_array, jit_extension);
1335
0
      }
1336
0
    }
1337
0
  }
1338
0
}
1339
#endif
1340
1341
static void zend_accel_persist_class_table(HashTable *class_table)
1342
61.8k
{
1343
61.8k
  Bucket *p;
1344
61.8k
  zend_class_entry *ce;
1345
61.8k
#ifdef HAVE_JIT
1346
61.8k
  bool orig_jit_on = JIT_G(on);
1347
1348
61.8k
  JIT_G(on) = 0;
1349
61.8k
#endif
1350
61.8k
  zend_hash_persist(class_table);
1351
180k
  ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) {
1352
180k
    ZEND_ASSERT(p->key != NULL);
1353
180k
    zend_accel_store_interned_string(p->key);
1354
28.2k
    Z_CE(p->val) = zend_persist_class_entry(Z_CE(p->val));
1355
28.2k
  } ZEND_HASH_FOREACH_END();
1356
180k
  ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) {
1357
180k
    if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
1358
28.2k
      ce = Z_PTR(p->val);
1359
28.2k
      zend_update_parent_ce(ce);
1360
28.2k
    }
1361
180k
  } ZEND_HASH_FOREACH_END();
1362
61.8k
#ifdef HAVE_JIT
1363
61.8k
  JIT_G(on) = orig_jit_on;
1364
61.8k
  if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS &&
1365
0
      !ZCG(current_persistent_script)->corrupted) {
1366
0
      zend_op_array *op_array;
1367
0
    zend_property_info *prop;
1368
1369
0
      ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) {
1370
0
      if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
1371
0
        ce = Z_PTR(p->val);
1372
0
        ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
1373
0
          zend_accel_persist_jit_op_array(op_array, ce);
1374
0
        } ZEND_HASH_FOREACH_END();
1375
1376
0
        if (ce->num_hooked_props > 0) {
1377
0
          ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) {
1378
0
            if (prop->hooks) {
1379
0
              for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
1380
0
                if (prop->hooks[i]) {
1381
0
                  op_array = &prop->hooks[i]->op_array;
1382
0
                  zend_accel_persist_jit_op_array(op_array, ce);
1383
0
                }
1384
0
              }
1385
0
            }
1386
0
          } ZEND_HASH_FOREACH_END();
1387
0
        }
1388
0
      }
1389
0
    } ZEND_HASH_FOREACH_END();
1390
0
      ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) {
1391
0
      if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
1392
0
        ce = Z_PTR(p->val);
1393
0
        ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
1394
0
          zend_accel_persist_link_func_info(op_array, ce);
1395
0
        } ZEND_HASH_FOREACH_END();
1396
1397
0
        if (ce->num_hooked_props > 0) {
1398
0
          ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) {
1399
0
            if (prop->hooks) {
1400
0
              for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
1401
0
                if (prop->hooks[i]) {
1402
0
                  op_array = &prop->hooks[i]->op_array;
1403
0
                  zend_accel_persist_link_func_info(op_array, ce);
1404
0
                }
1405
0
              }
1406
0
            }
1407
0
          } ZEND_HASH_FOREACH_END();
1408
0
        }
1409
0
      }
1410
0
    } ZEND_HASH_FOREACH_END();
1411
0
  }
1412
61.8k
#endif
1413
61.8k
}
1414
1415
65.2k
zend_error_info **zend_persist_warnings(uint32_t num_warnings, zend_error_info **warnings) {
1416
65.2k
  if (warnings) {
1417
64
    warnings = zend_shared_memdup(warnings, num_warnings * sizeof(zend_error_info *));
1418
130
    for (uint32_t i = 0; i < num_warnings; i++) {
1419
66
      zend_accel_store_string(warnings[i]->filename);
1420
66
      zend_accel_store_string(warnings[i]->message);
1421
66
      warnings[i] = zend_shared_memdup(warnings[i], sizeof(zend_error_info));
1422
66
    }
1423
64
  }
1424
65.2k
  return warnings;
1425
65.2k
}
1426
1427
static zend_early_binding *zend_persist_early_bindings(
1428
61.8k
    uint32_t num_early_bindings, zend_early_binding *early_bindings) {
1429
61.8k
  if (early_bindings) {
1430
569
    early_bindings = zend_shared_memdup_free(
1431
569
      early_bindings, num_early_bindings * sizeof(zend_early_binding));
1432
2.01k
    for (uint32_t i = 0; i < num_early_bindings; i++) {
1433
1.44k
      zend_accel_store_interned_string(early_bindings[i].lcname);
1434
1.44k
      zend_accel_store_interned_string(early_bindings[i].rtd_key);
1435
1.44k
      zend_accel_store_interned_string(early_bindings[i].lc_parent_name);
1436
1.44k
    }
1437
569
  }
1438
61.8k
  return early_bindings;
1439
61.8k
}
1440
1441
zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, bool for_shm)
1442
61.8k
{
1443
61.8k
  Bucket *p;
1444
1445
61.8k
  script->mem = ZCG(mem);
1446
1447
61.8k
  ZEND_ASSERT(((uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
1448
1449
61.8k
  script = zend_shared_memdup_free(script, sizeof(zend_persistent_script));
1450
61.8k
  script->corrupted = false;
1451
61.8k
  ZCG(current_persistent_script) = script;
1452
1453
61.8k
  if (!for_shm) {
1454
    /* script is not going to be saved in SHM */
1455
0
    script->corrupted = true;
1456
0
  }
1457
1458
61.8k
  zend_accel_store_interned_string(script->script.filename);
1459
1460
61.8k
#if defined(__AVX__) || defined(__SSE2__)
1461
  /* Align to 64-byte boundary */
1462
61.8k
  ZCG(mem) = (void*)(((uintptr_t)ZCG(mem) + 63L) & ~63L);
1463
#else
1464
  ZEND_ASSERT(((uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
1465
#endif
1466
1467
61.8k
#ifdef HAVE_JIT
1468
61.8k
  if (JIT_G(on) && for_shm) {
1469
0
    zend_jit_unprotect();
1470
0
  }
1471
61.8k
#endif
1472
1473
61.8k
  zend_map_ptr_extend(ZCSG(map_ptr_last));
1474
1475
61.8k
  zend_accel_persist_class_table(&script->script.class_table);
1476
61.8k
  zend_hash_persist(&script->script.function_table);
1477
158k
  ZEND_HASH_MAP_FOREACH_BUCKET(&script->script.function_table, p) {
1478
158k
    ZEND_ASSERT(p->key != NULL);
1479
158k
    zend_accel_store_interned_string(p->key);
1480
17.5k
    zend_persist_op_array(&p->val);
1481
17.5k
  } ZEND_HASH_FOREACH_END();
1482
61.8k
  zend_persist_op_array_ex(&script->script.main_op_array, script);
1483
61.8k
  if (!script->corrupted) {
1484
61.8k
    ZEND_MAP_PTR_INIT(script->script.main_op_array.run_time_cache, NULL);
1485
61.8k
    if (script->script.main_op_array.static_variables) {
1486
72
      ZEND_MAP_PTR_NEW(script->script.main_op_array.static_variables_ptr);
1487
72
    }
1488
61.8k
#ifdef HAVE_JIT
1489
61.8k
    if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS) {
1490
0
      zend_jit_op_array(&script->script.main_op_array, &script->script);
1491
0
    }
1492
61.8k
#endif
1493
61.8k
  }
1494
61.8k
  script->warnings = zend_persist_warnings(script->num_warnings, script->warnings);
1495
61.8k
  script->early_bindings = zend_persist_early_bindings(
1496
61.8k
    script->num_early_bindings, script->early_bindings);
1497
1498
61.8k
  if (for_shm) {
1499
61.8k
    ZCSG(map_ptr_last) = CG(map_ptr_last);
1500
61.8k
    ZCSG(map_ptr_static_last) = zend_map_ptr_static_last;
1501
61.8k
  }
1502
1503
61.8k
#ifdef HAVE_JIT
1504
61.8k
  if (JIT_G(on) && for_shm) {
1505
0
    if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_SCRIPT) {
1506
0
      zend_jit_script(&script->script);
1507
0
    }
1508
0
    zend_jit_protect();
1509
0
  }
1510
61.8k
#endif
1511
1512
61.8k
  script->corrupted = false;
1513
61.8k
  ZCG(current_persistent_script) = NULL;
1514
1515
61.8k
  return script;
1516
61.8k
}