This source file includes following definitions.
- zend_hash_persist
- zend_hash_persist_immutable
- zend_persist_ast
- zend_persist_zval
- zend_persist_zval_static
- zend_persist_zval_const
- zend_persist_op_array_ex
- zend_persist_op_array
- zend_persist_property_info
- zend_persist_class_entry
- zend_update_parent_ce
- zend_accel_persist_class_table
- zend_accel_script_persist
- zend_accel_script_persistable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include "zend.h"
23 #include "ZendAccelerator.h"
24 #include "zend_persist.h"
25 #include "zend_extensions.h"
26 #include "zend_shared_alloc.h"
27 #include "zend_vm.h"
28 #include "zend_constants.h"
29 #include "zend_operators.h"
30
31 #define zend_accel_store(p, size) \
32 (p = _zend_shared_memdup((void*)p, size, 1))
33 #define zend_accel_memdup(p, size) \
34 _zend_shared_memdup((void*)p, size, 0)
35
36 #define zend_accel_store_string(str) do { \
37 zend_string *new_str = zend_shared_alloc_get_xlat_entry(str); \
38 if (new_str) { \
39 zend_string_release(str); \
40 str = new_str; \
41 } else { \
42 new_str = zend_accel_memdup((void*)str, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \
43 zend_string_release(str); \
44 str = new_str; \
45 zend_string_hash_val(str); \
46 GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT; \
47 } \
48 } while (0)
49 #define zend_accel_memdup_string(str) do { \
50 str = zend_accel_memdup(str, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \
51 zend_string_hash_val(str); \
52 GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT; \
53 } while (0)
54 #define zend_accel_store_interned_string(str) do { \
55 if (!IS_ACCEL_INTERNED(str)) { \
56 zend_accel_store_string(str); \
57 } \
58 } while (0)
59 #define zend_accel_memdup_interned_string(str) do { \
60 if (!IS_ACCEL_INTERNED(str)) { \
61 zend_accel_memdup_string(str); \
62 } \
63 } while (0)
64
65 typedef void (*zend_persist_func_t)(zval*);
66
67 static void zend_persist_zval(zval *z);
68 static void zend_persist_zval_const(zval *z);
69
70 static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
71 {HT_INVALID_IDX, HT_INVALID_IDX};
72
73 static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement)
74 {
75 uint32_t idx, nIndex;
76 Bucket *p;
77
78 if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
79 HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
80 return;
81 }
82 if (ht->nNumUsed == 0) {
83 efree(HT_GET_DATA_ADDR(ht));
84 ht->nTableMask = HT_MIN_MASK;
85 HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
86 ht->u.flags &= ~HASH_FLAG_INITIALIZED;
87 return;
88 }
89 if (ht->u.flags & HASH_FLAG_PACKED) {
90 void *data = HT_GET_DATA_ADDR(ht);
91 zend_accel_store(data, HT_USED_SIZE(ht));
92 HT_SET_DATA_ADDR(ht, data);
93 } else if (ht->nNumUsed < -(int32_t)ht->nTableMask / 2) {
94
95 void *old_data = HT_GET_DATA_ADDR(ht);
96 Bucket *old_buckets = ht->arData;
97 int32_t hash_size;
98
99 if (ht->nNumUsed <= HT_MIN_SIZE) {
100 hash_size = HT_MIN_SIZE;
101 } else {
102 hash_size = -(int32_t)ht->nTableMask;
103 while (hash_size >> 1 > ht->nNumUsed) {
104 hash_size >>= 1;
105 }
106 }
107 ht->nTableMask = -hash_size;
108 ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0);
109 HT_SET_DATA_ADDR(ht, ZCG(mem));
110 ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE((hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket))));
111 HT_HASH_RESET(ht);
112 memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket));
113 efree(old_data);
114
115 for (idx = 0; idx < ht->nNumUsed; idx++) {
116 p = ht->arData + idx;
117 if (Z_TYPE(p->val) == IS_UNDEF) continue;
118
119
120 if (p->key) {
121 zend_accel_store_interned_string(p->key);
122 }
123
124
125 pPersistElement(&p->val);
126
127 nIndex = p->h | ht->nTableMask;
128 Z_NEXT(p->val) = HT_HASH(ht, nIndex);
129 HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
130 }
131 return;
132 } else {
133 void *data = ZCG(mem);
134 void *old_data = HT_GET_DATA_ADDR(ht);
135
136 ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0);
137 ZCG(mem) = (void*)((char*)data + HT_USED_SIZE(ht));
138 memcpy(data, old_data, HT_USED_SIZE(ht));
139 efree(old_data);
140 HT_SET_DATA_ADDR(ht, data);
141 }
142
143 for (idx = 0; idx < ht->nNumUsed; idx++) {
144 p = ht->arData + idx;
145 if (Z_TYPE(p->val) == IS_UNDEF) continue;
146
147
148 if (p->key) {
149 zend_accel_store_interned_string(p->key);
150 }
151
152
153 pPersistElement(&p->val);
154 }
155 }
156
157 static void zend_hash_persist_immutable(HashTable *ht)
158 {
159 uint32_t idx, nIndex;
160 Bucket *p;
161
162 if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
163 HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
164 return;
165 }
166 if (ht->nNumUsed == 0) {
167 efree(HT_GET_DATA_ADDR(ht));
168 ht->nTableMask = HT_MIN_MASK;
169 HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
170 ht->u.flags &= ~HASH_FLAG_INITIALIZED;
171 return;
172 }
173 if (ht->u.flags & HASH_FLAG_PACKED) {
174 HT_SET_DATA_ADDR(ht, zend_accel_memdup(HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht)));
175 } else if (ht->nNumUsed < -(int32_t)ht->nTableMask / 2) {
176
177 void *old_data = HT_GET_DATA_ADDR(ht);
178 Bucket *old_buckets = ht->arData;
179 int32_t hash_size;
180
181 if (ht->nNumUsed <= HT_MIN_SIZE) {
182 hash_size = HT_MIN_SIZE;
183 } else {
184 hash_size = -(int32_t)ht->nTableMask;
185 while (hash_size >> 1 > ht->nNumUsed) {
186 hash_size >>= 1;
187 }
188 }
189 ht->nTableMask = -hash_size;
190 ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0);
191 HT_SET_DATA_ADDR(ht, ZCG(mem));
192 ZCG(mem) = (void*)((char*)ZCG(mem) + (hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket)));
193 HT_HASH_RESET(ht);
194 memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket));
195 efree(old_data);
196
197 for (idx = 0; idx < ht->nNumUsed; idx++) {
198 p = ht->arData + idx;
199 if (Z_TYPE(p->val) == IS_UNDEF) continue;
200
201
202 if (p->key) {
203 zend_accel_memdup_interned_string(p->key);
204 }
205
206
207 zend_persist_zval_const(&p->val);
208
209 nIndex = p->h | ht->nTableMask;
210 Z_NEXT(p->val) = HT_HASH(ht, nIndex);
211 HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
212 }
213 return;
214 } else {
215 void *data = ZCG(mem);
216
217 ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0);
218 ZCG(mem) = (void*)((char*)data + HT_USED_SIZE(ht));
219 memcpy(data, HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht));
220 HT_SET_DATA_ADDR(ht, data);
221 }
222 for (idx = 0; idx < ht->nNumUsed; idx++) {
223 p = ht->arData + idx;
224 if (Z_TYPE(p->val) == IS_UNDEF) continue;
225
226
227 if (p->key) {
228 zend_accel_memdup_interned_string(p->key);
229 }
230
231
232 zend_persist_zval_const(&p->val);
233 }
234 }
235
236 static zend_ast *zend_persist_ast(zend_ast *ast)
237 {
238 uint32_t i;
239 zend_ast *node;
240
241 if (ast->kind == ZEND_AST_ZVAL) {
242 zend_ast_zval *copy = zend_accel_memdup(ast, sizeof(zend_ast_zval));
243 zend_persist_zval(©->val);
244 node = (zend_ast *) copy;
245 } else if (zend_ast_is_list(ast)) {
246 zend_ast_list *list = zend_ast_get_list(ast);
247 zend_ast_list *copy = zend_accel_memdup(ast,
248 sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
249 for (i = 0; i < list->children; i++) {
250 if (copy->child[i]) {
251 copy->child[i] = zend_persist_ast(copy->child[i]);
252 }
253 }
254 node = (zend_ast *) copy;
255 } else {
256 uint32_t children = zend_ast_get_num_children(ast);
257 node = zend_accel_memdup(ast, sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
258 for (i = 0; i < children; i++) {
259 if (node->child[i]) {
260 node->child[i] = zend_persist_ast(node->child[i]);
261 }
262 }
263 }
264
265 efree(ast);
266 return node;
267 }
268
269 static void zend_persist_zval(zval *z)
270 {
271 zend_uchar flags;
272 void *new_ptr;
273
274 switch (Z_TYPE_P(z)) {
275 case IS_STRING:
276 case IS_CONSTANT:
277 flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
278 zend_accel_store_interned_string(Z_STR_P(z));
279 Z_GC_FLAGS_P(z) |= flags;
280 Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
281 break;
282 case IS_ARRAY:
283 new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
284 if (new_ptr) {
285 Z_ARR_P(z) = new_ptr;
286 Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
287 } else {
288 if (Z_IMMUTABLE_P(z)) {
289 Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
290 zend_hash_persist_immutable(Z_ARRVAL_P(z));
291 } else {
292 GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
293 zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
294 zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
295
296 Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
297 GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
298 GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
299 Z_ARRVAL_P(z)->u.flags |= HASH_FLAG_STATIC_KEYS;
300 Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
301 }
302 }
303 break;
304 case IS_REFERENCE:
305 new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
306 if (new_ptr) {
307 Z_REF_P(z) = new_ptr;
308 } else {
309 zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
310 zend_persist_zval(Z_REFVAL_P(z));
311 }
312 break;
313 case IS_CONSTANT_AST:
314 new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
315 if (new_ptr) {
316 Z_AST_P(z) = new_ptr;
317 } else {
318 zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
319 Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
320 }
321 break;
322 }
323 }
324
325 static void zend_persist_zval_static(zval *z)
326 {
327 zend_uchar flags;
328 void *new_ptr;
329
330 switch (Z_TYPE_P(z)) {
331 case IS_STRING:
332 case IS_CONSTANT:
333 flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
334 zend_accel_store_interned_string(Z_STR_P(z));
335 Z_GC_FLAGS_P(z) |= flags;
336 Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
337 break;
338 case IS_ARRAY:
339 new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
340 if (new_ptr) {
341 Z_ARR_P(z) = new_ptr;
342 Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
343 } else {
344 if (Z_IMMUTABLE_P(z)) {
345 Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
346 zend_hash_persist_immutable(Z_ARRVAL_P(z));
347 } else {
348 GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
349 zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
350 zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
351
352 Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
353 GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
354 GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
355 Z_ARRVAL_P(z)->u.flags |= HASH_FLAG_STATIC_KEYS;
356 Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
357 }
358 }
359 break;
360 case IS_REFERENCE:
361 new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
362 if (new_ptr) {
363 Z_REF_P(z) = new_ptr;
364 } else {
365 zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
366 zend_persist_zval(Z_REFVAL_P(z));
367 }
368 break;
369 case IS_CONSTANT_AST:
370 new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
371 if (new_ptr) {
372 Z_AST_P(z) = new_ptr;
373 Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_IMMUTABLE;
374 } else {
375 zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
376 Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
377 Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_IMMUTABLE;
378 GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
379 }
380 break;
381 }
382 }
383
384 static void zend_persist_zval_const(zval *z)
385 {
386 zend_uchar flags;
387 void *new_ptr;
388
389 switch (Z_TYPE_P(z)) {
390 case IS_STRING:
391 case IS_CONSTANT:
392 flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
393 zend_accel_memdup_interned_string(Z_STR_P(z));
394 Z_GC_FLAGS_P(z) |= flags;
395 Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
396 break;
397 case IS_ARRAY:
398 new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
399 if (new_ptr) {
400 Z_ARR_P(z) = new_ptr;
401 Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
402 } else {
403 if (Z_IMMUTABLE_P(z)) {
404 Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
405 zend_hash_persist_immutable(Z_ARRVAL_P(z));
406 } else {
407 GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
408 zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
409 zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
410
411 Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
412 GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
413 GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
414 Z_ARRVAL_P(z)->u.flags |= HASH_FLAG_STATIC_KEYS;
415 Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
416 }
417 }
418 break;
419 case IS_REFERENCE:
420 new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
421 if (new_ptr) {
422 Z_REF_P(z) = new_ptr;
423 } else {
424 zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
425 zend_persist_zval(Z_REFVAL_P(z));
426 }
427 break;
428 case IS_CONSTANT_AST:
429 new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
430 if (new_ptr) {
431 Z_AST_P(z) = new_ptr;
432 } else {
433 zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
434 Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
435 }
436 break;
437 }
438 }
439
440 static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script)
441 {
442 int already_stored = 0;
443 zend_op *persist_ptr;
444 zval *orig_literals = NULL;
445
446 if (op_array->type != ZEND_USER_FUNCTION) {
447 return;
448 }
449
450 if (op_array->refcount && --(*op_array->refcount) == 0) {
451 efree(op_array->refcount);
452 }
453 op_array->refcount = NULL;
454
455 if (main_persistent_script) {
456 zend_execute_data *orig_execute_data = EG(current_execute_data);
457 zend_execute_data fake_execute_data;
458 zval *offset;
459
460 memset(&fake_execute_data, 0, sizeof(fake_execute_data));
461 fake_execute_data.func = (zend_function*)op_array;
462 EG(current_execute_data) = &fake_execute_data;
463 if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
464 main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset);
465 }
466 EG(current_execute_data) = orig_execute_data;
467 }
468
469 if (op_array->static_variables) {
470 HashTable *stored = zend_shared_alloc_get_xlat_entry(op_array->static_variables);
471
472 if (stored) {
473 op_array->static_variables = stored;
474 } else {
475 zend_hash_persist(op_array->static_variables, zend_persist_zval_static);
476 zend_accel_store(op_array->static_variables, sizeof(HashTable));
477
478 GC_REFCOUNT(op_array->static_variables) = 2;
479 GC_TYPE_INFO(op_array->static_variables) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << 8);
480 op_array->static_variables->u.flags |= HASH_FLAG_STATIC_KEYS;
481 op_array->static_variables->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
482 }
483 }
484
485 if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
486 already_stored = 1;
487 }
488
489 if (op_array->literals) {
490 if (already_stored) {
491 orig_literals = zend_shared_alloc_get_xlat_entry(op_array->literals);
492 ZEND_ASSERT(orig_literals != NULL);
493 op_array->literals = orig_literals;
494 } else {
495 zval *p = zend_accel_memdup(op_array->literals, sizeof(zval) * op_array->last_literal);
496 zval *end = p + op_array->last_literal;
497 orig_literals = op_array->literals;
498 op_array->literals = p;
499 while (p < end) {
500 zend_persist_zval(p);
501 p++;
502 }
503 efree(orig_literals);
504 }
505 }
506
507 if (already_stored) {
508 persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
509 ZEND_ASSERT(persist_ptr != NULL);
510 op_array->opcodes = persist_ptr;
511 } else {
512 zend_op *new_opcodes = zend_accel_memdup(op_array->opcodes, sizeof(zend_op) * op_array->last);
513 #if ZEND_USE_ABS_CONST_ADDR || ZEND_USE_ABS_JMP_ADDR
514 zend_op *opline = new_opcodes;
515 zend_op *end = new_opcodes + op_array->last;
516 int offset = 0;
517
518 for (; opline < end ; opline++, offset++) {
519 # if ZEND_USE_ABS_CONST_ADDR
520 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
521 opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
522 }
523 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
524 opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
525 }
526 # endif
527 # if ZEND_USE_ABS_JMP_ADDR
528 if (ZEND_DONE_PASS_TWO(op_array)) {
529
530 switch (opline->opcode) {
531 case ZEND_JMP:
532 case ZEND_FAST_CALL:
533 case ZEND_DECLARE_ANON_CLASS:
534 case ZEND_DECLARE_ANON_INHERITED_CLASS:
535 ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes];
536 break;
537 case ZEND_JMPZNZ:
538
539
540 case ZEND_JMPZ:
541 case ZEND_JMPNZ:
542 case ZEND_JMPZ_EX:
543 case ZEND_JMPNZ_EX:
544 case ZEND_JMP_SET:
545 case ZEND_COALESCE:
546 case ZEND_NEW:
547 case ZEND_FE_RESET_R:
548 case ZEND_FE_RESET_RW:
549 case ZEND_ASSERT_CHECK:
550 ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes];
551 break;
552 case ZEND_FE_FETCH_R:
553 case ZEND_FE_FETCH_RW:
554
555 break;
556 }
557 }
558 # endif
559 }
560 #endif
561
562 efree(op_array->opcodes);
563 op_array->opcodes = new_opcodes;
564
565 if (op_array->run_time_cache) {
566 efree(op_array->run_time_cache);
567 op_array->run_time_cache = NULL;
568 }
569 }
570
571 if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) {
572 zend_string *new_name;
573 if (already_stored) {
574 new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
575 ZEND_ASSERT(new_name != NULL);
576 op_array->function_name = new_name;
577 } else {
578 zend_accel_store_string(op_array->function_name);
579 }
580 }
581
582 if (op_array->filename) {
583
584 zend_accel_memdup_string(op_array->filename);
585 }
586
587 if (op_array->arg_info) {
588 zend_arg_info *arg_info = op_array->arg_info;
589 uint32_t num_args = op_array->num_args;
590
591 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
592 arg_info--;
593 num_args++;
594 }
595 if (already_stored) {
596 arg_info = zend_shared_alloc_get_xlat_entry(arg_info);
597 ZEND_ASSERT(arg_info != NULL);
598 } else {
599 uint32_t i;
600
601 if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
602 num_args++;
603 }
604 zend_accel_store(arg_info, sizeof(zend_arg_info) * num_args);
605 for (i = 0; i < num_args; i++) {
606 if (arg_info[i].name) {
607 zend_accel_store_interned_string(arg_info[i].name);
608 }
609 if (arg_info[i].class_name) {
610 zend_accel_store_interned_string(arg_info[i].class_name);
611 }
612 }
613 }
614 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
615 arg_info++;
616 }
617 op_array->arg_info = arg_info;
618 }
619
620 if (op_array->brk_cont_array) {
621 zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont);
622 }
623
624 if (op_array->scope) {
625 op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
626 }
627
628 if (op_array->doc_comment) {
629 if (ZCG(accel_directives).save_comments) {
630 if (already_stored) {
631 op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment);
632 ZEND_ASSERT(op_array->doc_comment != NULL);
633 } else {
634 zend_accel_store_string(op_array->doc_comment);
635 }
636 } else {
637 if (!already_stored) {
638 zend_string_release(op_array->doc_comment);
639 }
640 op_array->doc_comment = NULL;
641 }
642 }
643
644 if (op_array->try_catch_array) {
645 zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
646 }
647
648 if (op_array->vars) {
649 if (already_stored) {
650 persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars);
651 ZEND_ASSERT(persist_ptr != NULL);
652 op_array->vars = (zend_string**)persist_ptr;
653 } else {
654 int i;
655 zend_accel_store(op_array->vars, sizeof(zend_string*) * op_array->last_var);
656 for (i = 0; i < op_array->last_var; i++) {
657 zend_accel_store_interned_string(op_array->vars[i]);
658 }
659 }
660 }
661
662
663 if (op_array->scope && op_array->prototype) {
664 if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
665 op_array->prototype = (union _zend_function*)persist_ptr;
666 }
667 } else {
668 op_array->prototype = NULL;
669 }
670
671 ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem))));
672 }
673
674 static void zend_persist_op_array(zval *zv)
675 {
676 zend_op_array *op_array = Z_PTR_P(zv);
677 zend_op_array *old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
678 if (old_op_array) {
679 Z_PTR_P(zv) = old_op_array;
680 if (op_array->refcount && --(*op_array->refcount) == 0) {
681 efree(op_array->refcount);
682 }
683 return;
684 }
685 memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_op_array));
686 zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
687 Z_PTR_P(zv) = ZCG(arena_mem);
688 ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_op_array)));
689 zend_persist_op_array_ex(Z_PTR_P(zv), NULL);
690 }
691
692 static void zend_persist_property_info(zval *zv)
693 {
694 zend_property_info *prop = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv));
695
696 if (prop) {
697 Z_PTR_P(zv) = prop;
698 return;
699 }
700 memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_property_info));
701 zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
702 prop = Z_PTR_P(zv) = ZCG(arena_mem);
703 ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_property_info)));
704 prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
705 zend_accel_store_interned_string(prop->name);
706 if (prop->doc_comment) {
707 if (ZCG(accel_directives).save_comments) {
708 zend_accel_store_string(prop->doc_comment);
709 } else {
710 if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
711 zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
712 }
713 zend_string_release(prop->doc_comment);
714 prop->doc_comment = NULL;
715 }
716 }
717 }
718
719 static void zend_persist_class_entry(zval *zv)
720 {
721 zend_class_entry *ce = Z_PTR_P(zv);
722
723 if (ce->type == ZEND_USER_CLASS) {
724 memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_entry));
725 zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
726 ce = Z_PTR_P(zv) = ZCG(arena_mem);
727 ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_entry)));
728 zend_accel_store_interned_string(ce->name);
729 zend_hash_persist(&ce->function_table, zend_persist_op_array);
730 if (ce->default_properties_table) {
731 int i;
732
733 zend_accel_store(ce->default_properties_table, sizeof(zval) * ce->default_properties_count);
734 for (i = 0; i < ce->default_properties_count; i++) {
735 zend_persist_zval(&ce->default_properties_table[i]);
736 }
737 }
738 if (ce->default_static_members_table) {
739 int i;
740
741 zend_accel_store(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count);
742 for (i = 0; i < ce->default_static_members_count; i++) {
743 zend_persist_zval(&ce->default_static_members_table[i]);
744 }
745 }
746 ce->static_members_table = NULL;
747
748 zend_hash_persist(&ce->constants_table, zend_persist_zval);
749
750 if (ZEND_CE_FILENAME(ce)) {
751
752 zend_accel_memdup_string(ZEND_CE_FILENAME(ce));
753 }
754 if (ZEND_CE_DOC_COMMENT(ce)) {
755 if (ZCG(accel_directives).save_comments) {
756 zend_accel_store_string(ZEND_CE_DOC_COMMENT(ce));
757 } else {
758 if (!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) {
759 zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce));
760 zend_string_release(ZEND_CE_DOC_COMMENT(ce));
761 }
762 ZEND_CE_DOC_COMMENT(ce) = NULL;
763 }
764 }
765 zend_hash_persist(&ce->properties_info, zend_persist_property_info);
766 if (ce->num_interfaces && ce->interfaces) {
767 efree(ce->interfaces);
768 }
769 ce->interfaces = NULL;
770
771 if (ce->num_traits && ce->traits) {
772 efree(ce->traits);
773 }
774 ce->traits = NULL;
775
776 if (ce->trait_aliases) {
777 int i = 0;
778 while (ce->trait_aliases[i]) {
779 if (ce->trait_aliases[i]->trait_method) {
780 if (ce->trait_aliases[i]->trait_method->method_name) {
781 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->method_name);
782 }
783 if (ce->trait_aliases[i]->trait_method->class_name) {
784 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->class_name);
785 }
786 ce->trait_aliases[i]->trait_method->ce = NULL;
787 zend_accel_store(ce->trait_aliases[i]->trait_method,
788 sizeof(zend_trait_method_reference));
789 }
790
791 if (ce->trait_aliases[i]->alias) {
792 zend_accel_store_interned_string(ce->trait_aliases[i]->alias);
793 }
794
795 zend_accel_store(ce->trait_aliases[i], sizeof(zend_trait_alias));
796 i++;
797 }
798
799 zend_accel_store(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1));
800 }
801
802 if (ce->trait_precedences) {
803 int i = 0;
804
805 while (ce->trait_precedences[i]) {
806 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->method_name);
807 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->class_name);
808 ce->trait_precedences[i]->trait_method->ce = NULL;
809 zend_accel_store(ce->trait_precedences[i]->trait_method,
810 sizeof(zend_trait_method_reference));
811
812 if (ce->trait_precedences[i]->exclude_from_classes) {
813 int j = 0;
814
815 while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) {
816 zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_from_classes[j].class_name);
817 j++;
818 }
819 zend_accel_store(ce->trait_precedences[i]->exclude_from_classes,
820 sizeof(zend_class_entry*) * (j + 1));
821 }
822
823 zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence));
824 i++;
825 }
826 zend_accel_store(
827 ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
828 }
829 }
830 }
831
832
833
834
835
836
837
838
839
840 static int zend_update_parent_ce(zval *zv)
841 {
842 zend_class_entry *ce = Z_PTR_P(zv);
843
844 if (ce->parent) {
845 ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
846 }
847
848
849 if (ce->constructor) {
850 ce->constructor = zend_shared_alloc_get_xlat_entry(ce->constructor);
851 }
852 if (ce->destructor) {
853 ce->destructor = zend_shared_alloc_get_xlat_entry(ce->destructor);
854 }
855 if (ce->clone) {
856 ce->clone = zend_shared_alloc_get_xlat_entry(ce->clone);
857 }
858 if (ce->__get) {
859 ce->__get = zend_shared_alloc_get_xlat_entry(ce->__get);
860 }
861 if (ce->__set) {
862 ce->__set = zend_shared_alloc_get_xlat_entry(ce->__set);
863 }
864 if (ce->__call) {
865 ce->__call = zend_shared_alloc_get_xlat_entry(ce->__call);
866 }
867 if (ce->serialize_func) {
868 ce->serialize_func = zend_shared_alloc_get_xlat_entry(ce->serialize_func);
869 }
870 if (ce->unserialize_func) {
871 ce->unserialize_func = zend_shared_alloc_get_xlat_entry(ce->unserialize_func);
872 }
873 if (ce->__isset) {
874 ce->__isset = zend_shared_alloc_get_xlat_entry(ce->__isset);
875 }
876 if (ce->__unset) {
877 ce->__unset = zend_shared_alloc_get_xlat_entry(ce->__unset);
878 }
879 if (ce->__tostring) {
880 ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring);
881 }
882 if (ce->__callstatic) {
883 ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
884 }
885 if (ce->__debugInfo) {
886 ce->__debugInfo = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
887 }
888
889 return 0;
890 }
891
892 static void zend_accel_persist_class_table(HashTable *class_table)
893 {
894 zend_hash_persist(class_table, zend_persist_class_entry);
895 zend_hash_apply(class_table, (apply_func_t) zend_update_parent_ce);
896 }
897
898 zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length)
899 {
900 script->mem = ZCG(mem);
901
902 ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0);
903 zend_shared_alloc_clear_xlat_table();
904
905 zend_accel_store(script, sizeof(zend_persistent_script));
906 if (key && *key) {
907 *key = zend_accel_memdup(*key, key_length + 1);
908 }
909 zend_accel_store_string(script->full_path);
910
911 #ifdef __SSE2__
912
913 ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
914 #else
915 ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0);
916 #endif
917
918 script->arena_mem = ZCG(arena_mem) = ZCG(mem);
919 ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size);
920
921 zend_accel_persist_class_table(&script->class_table);
922 zend_hash_persist(&script->function_table, zend_persist_op_array);
923 zend_persist_op_array_ex(&script->main_op_array, script);
924
925 return script;
926 }
927
928 int zend_accel_script_persistable(zend_persistent_script *script)
929 {
930 return 1;
931 }