1 /*
2 +----------------------------------------------------------------------+
3 | Zend OPcache |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2016 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@zend.com> |
16 | Zeev Suraski <zeev@zend.com> |
17 | Stanislav Malyshev <stas@zend.com> |
18 | Dmitry Stogov <dmitry@zend.com> |
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 TSRMLS_CC))
33 #define zend_accel_memdup(p, size) \
34 _zend_shared_memdup((void*)p, size, 0 TSRMLS_CC)
35
36 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
37 # define zend_accel_memdup_interned_string(str, len) \
38 IS_INTERNED(str) ? str : zend_accel_memdup(str, len)
39
40 # define zend_accel_store_interned_string(str, len) do { \
41 if (!IS_INTERNED(str)) { zend_accel_store(str, len); } \
42 } while (0)
43 #else
44 # define zend_accel_memdup_interned_string(str, len) \
45 zend_accel_memdup(str, len)
46
47 # define zend_accel_store_interned_string(str, len) \
48 zend_accel_store(str, len)
49 #endif
50
51 typedef void (*zend_persist_func_t)(void * TSRMLS_DC);
52
53 static void zend_persist_zval_ptr(zval **zp TSRMLS_DC);
54 static void zend_persist_zval(zval *z TSRMLS_DC);
55
56 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
57 static const Bucket *uninitialized_bucket = NULL;
58 #endif
59
zend_hash_persist(HashTable * ht,void (* pPersistElement)(void * pElement TSRMLS_DC),size_t el_size TSRMLS_DC)60 static void zend_hash_persist(HashTable *ht, void (*pPersistElement)(void *pElement TSRMLS_DC), size_t el_size TSRMLS_DC)
61 {
62 Bucket *p = ht->pListHead;
63 uint i;
64
65 while (p) {
66 Bucket *q = p;
67
68 /* persist bucket and key */
69 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
70 p = zend_accel_memdup(p, sizeof(Bucket));
71 if (p->nKeyLength) {
72 p->arKey = zend_accel_memdup_interned_string(p->arKey, p->nKeyLength);
73 }
74 #else
75 p = zend_accel_memdup(p, sizeof(Bucket) - 1 + p->nKeyLength);
76 #endif
77
78 /* persist data pointer in bucket */
79 if (!p->pDataPtr) {
80 zend_accel_store(p->pData, el_size);
81 } else {
82 /* Update p->pData to point to the new p->pDataPtr address, after the bucket relocation */
83 p->pData = &p->pDataPtr;
84 }
85
86 /* persist the data itself */
87 if (pPersistElement) {
88 pPersistElement(p->pData TSRMLS_CC);
89 }
90
91 /* update linked lists */
92 if (p->pLast) {
93 p->pLast->pNext = p;
94 }
95 if (p->pNext) {
96 p->pNext->pLast = p;
97 }
98 if (p->pListLast) {
99 p->pListLast->pListNext = p;
100 }
101 if (p->pListNext) {
102 p->pListNext->pListLast = p;
103 }
104
105 p = p->pListNext;
106
107 /* delete the old non-persistent bucket */
108 efree(q);
109 }
110
111 /* update linked lists */
112 if (ht->pListHead) {
113 ht->pListHead = zend_shared_alloc_get_xlat_entry(ht->pListHead);
114 }
115 if (ht->pListTail) {
116 ht->pListTail = zend_shared_alloc_get_xlat_entry(ht->pListTail);
117 }
118 if (ht->pInternalPointer) {
119 ht->pInternalPointer = zend_shared_alloc_get_xlat_entry(ht->pInternalPointer);
120 }
121
122 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
123 /* Check if HastTable is initialized */
124 if (ht->nTableMask) {
125 #endif
126 if (ht->nNumOfElements) {
127 /* update hash table */
128 for (i = 0; i < ht->nTableSize; i++) {
129 if (ht->arBuckets[i]) {
130 ht->arBuckets[i] = zend_shared_alloc_get_xlat_entry(ht->arBuckets[i]);
131 }
132 }
133 }
134 zend_accel_store(ht->arBuckets, sizeof(Bucket*) * ht->nTableSize);
135 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
136 } else {
137 ht->arBuckets = (Bucket**)&uninitialized_bucket;
138 }
139 #endif
140 }
141
142 #if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
zend_persist_ast(zend_ast * ast TSRMLS_DC)143 static zend_ast *zend_persist_ast(zend_ast *ast TSRMLS_DC)
144 {
145 int i;
146 zend_ast *node;
147
148 if (ast->kind == ZEND_CONST) {
149 node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zval));
150 node->u.val = (zval*)(node + 1);
151 zend_persist_zval(node->u.val TSRMLS_CC);
152 } else {
153 node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
154 for (i = 0; i < ast->children; i++) {
155 if ((&node->u.child)[i]) {
156 (&node->u.child)[i] = zend_persist_ast((&node->u.child)[i] TSRMLS_CC);
157 }
158 }
159 }
160 efree(ast);
161 return node;
162 }
163 #endif
164
zend_persist_zval(zval * z TSRMLS_DC)165 static void zend_persist_zval(zval *z TSRMLS_DC)
166 {
167 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
168 switch (z->type & IS_CONSTANT_TYPE_MASK) {
169 #else
170 switch (z->type & ~IS_CONSTANT_INDEX) {
171 #endif
172 case IS_STRING:
173 case IS_CONSTANT:
174 zend_accel_store_interned_string(z->value.str.val, z->value.str.len + 1);
175 break;
176 case IS_ARRAY:
177 #if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
178 case IS_CONSTANT_ARRAY:
179 #endif
180 zend_accel_store(z->value.ht, sizeof(HashTable));
181 zend_hash_persist(z->value.ht, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
182 break;
183 #if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
184 case IS_CONSTANT_AST:
185 Z_AST_P(z) = zend_persist_ast(Z_AST_P(z) TSRMLS_CC);
186 break;
187 #endif
188 }
189 }
190
191 static void zend_persist_zval_ptr(zval **zp TSRMLS_DC)
192 {
193 zval *new_ptr = zend_shared_alloc_get_xlat_entry(*zp);
194
195 if (new_ptr) {
196 *zp = new_ptr;
197 } else {
198 /* Attempt to store only if we didn't store this zval_ptr yet */
199 zend_accel_store(*zp, sizeof(zval));
200 zend_persist_zval(*zp TSRMLS_CC);
201 }
202 }
203
204 static void zend_protect_zval(zval *z TSRMLS_DC)
205 {
206 PZ_SET_ISREF_P(z);
207 PZ_SET_REFCOUNT_P(z, 2);
208 }
209
210 static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script TSRMLS_DC)
211 {
212 zend_op *persist_ptr;
213 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
214 int has_jmp = 0;
215 #endif
216 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
217 zend_literal *orig_literals = NULL;
218 #endif
219
220 if (op_array->type != ZEND_USER_FUNCTION) {
221 return;
222 }
223
224 #if ZEND_EXTENSION_API_NO <= PHP_5_3_X_API_NO
225 op_array->size = op_array->last;
226 #endif
227
228 if (--(*op_array->refcount) == 0) {
229 efree(op_array->refcount);
230 }
231 op_array->refcount = NULL;
232
233 if (op_array->filename) {
234 /* do not free! PHP has centralized filename storage, compiler will free it */
235 op_array->filename = zend_accel_memdup(op_array->filename, strlen(op_array->filename) + 1);
236 }
237
238 if (main_persistent_script) {
239 zend_bool orig_in_execution = EG(in_execution);
240 zend_op_array *orig_op_array = EG(active_op_array);
241 zval offset;
242
243 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
244 main_persistent_script->early_binding = -1;
245 #endif
246 EG(in_execution) = 1;
247 EG(active_op_array) = op_array;
248 if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &offset TSRMLS_CC)) {
249 main_persistent_script->compiler_halt_offset = Z_LVAL(offset);
250 }
251 EG(active_op_array) = orig_op_array;
252 EG(in_execution) = orig_in_execution;
253 }
254
255 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
256 if (op_array->literals) {
257 orig_literals = zend_shared_alloc_get_xlat_entry(op_array->literals);
258 if (orig_literals) {
259 op_array->literals = orig_literals;
260 } else {
261 zend_literal *p = zend_accel_memdup(op_array->literals, sizeof(zend_literal) * op_array->last_literal);
262 zend_literal *end = p + op_array->last_literal;
263 orig_literals = op_array->literals;
264 op_array->literals = p;
265 while (p < end) {
266 zend_persist_zval(&p->constant TSRMLS_CC);
267 zend_protect_zval(&p->constant TSRMLS_CC);
268 p++;
269 }
270 efree(orig_literals);
271 }
272 }
273 #endif
274
275 if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes))) {
276 op_array->opcodes = persist_ptr;
277 } else {
278 zend_op *new_opcodes = zend_accel_memdup(op_array->opcodes, sizeof(zend_op) * op_array->last);
279 zend_op *opline = new_opcodes;
280 zend_op *end = new_opcodes + op_array->last;
281 int offset = 0;
282
283 for (; opline < end ; opline++, offset++) {
284 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
285 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
286 opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
287 #else
288 zend_persist_zval(&opline->op1.u.constant TSRMLS_CC);
289 zend_protect_zval(&opline->op1.u.constant TSRMLS_CC);
290 #endif
291 }
292 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
293 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
294 opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
295 #else
296 zend_persist_zval(&opline->op2.u.constant TSRMLS_CC);
297 zend_protect_zval(&opline->op2.u.constant TSRMLS_CC);
298 #endif
299 }
300
301 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
302 switch (opline->opcode) {
303 case ZEND_JMP:
304 has_jmp = 1;
305 if (ZEND_DONE_PASS_TWO(op_array)) {
306 ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes];
307 }
308 break;
309 case ZEND_JMPZ:
310 case ZEND_JMPNZ:
311 case ZEND_JMPZ_EX:
312 case ZEND_JMPNZ_EX:
313 has_jmp = 1;
314 if (ZEND_DONE_PASS_TWO(op_array)) {
315 ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes];
316 }
317 break;
318 case ZEND_JMPZNZ:
319 case ZEND_BRK:
320 case ZEND_CONT:
321 has_jmp = 1;
322 break;
323 case ZEND_DECLARE_INHERITED_CLASS:
324 if (main_persistent_script && ZCG(accel_directives).inherited_hack) {
325 if (!has_jmp &&
326 ((opline + 2) >= end ||
327 (opline + 1)->opcode != ZEND_FETCH_CLASS ||
328 (opline + 2)->opcode != ZEND_ADD_INTERFACE)) {
329
330 zend_uint *opline_num = &main_persistent_script->early_binding;
331
332 while ((int)*opline_num != -1) {
333 opline_num = &new_opcodes[*opline_num].result.u.opline_num;
334 }
335 *opline_num = opline - new_opcodes;
336 opline->result.op_type = IS_UNUSED;
337 opline->result.u.opline_num = -1;
338 opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
339 ZEND_VM_SET_OPCODE_HANDLER(opline);
340 }
341 break;
342 }
343 }
344
345 #else /* if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO */
346
347 if (ZEND_DONE_PASS_TWO(op_array)) {
348 /* fix jumps to point to new array */
349 switch (opline->opcode) {
350 case ZEND_JMP:
351 case ZEND_GOTO:
352 #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
353 case ZEND_FAST_CALL:
354 #endif
355 ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes];
356 break;
357 case ZEND_JMPZ:
358 case ZEND_JMPNZ:
359 case ZEND_JMPZ_EX:
360 case ZEND_JMPNZ_EX:
361 case ZEND_JMP_SET:
362 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
363 case ZEND_JMP_SET_VAR:
364 #endif
365 ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes];
366 break;
367 }
368 }
369 #endif /* if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO */
370 }
371
372 efree(op_array->opcodes);
373 op_array->opcodes = new_opcodes;
374
375 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
376 if (op_array->run_time_cache) {
377 efree(op_array->run_time_cache);
378 op_array->run_time_cache = NULL;
379 }
380 #endif
381 }
382
383 if (op_array->function_name) {
384 char *new_name;
385 if ((new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name))) {
386 op_array->function_name = new_name;
387 } else {
388 zend_accel_store(op_array->function_name, strlen(op_array->function_name) + 1);
389 }
390 }
391
392 if (op_array->arg_info) {
393 zend_arg_info *new_ptr;
394 if ((new_ptr = zend_shared_alloc_get_xlat_entry(op_array->arg_info))) {
395 op_array->arg_info = new_ptr;
396 } else {
397 zend_uint i;
398
399 zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
400 for (i = 0; i < op_array->num_args; i++) {
401 if (op_array->arg_info[i].name) {
402 zend_accel_store_interned_string(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
403 }
404 if (op_array->arg_info[i].class_name) {
405 zend_accel_store_interned_string(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
406 }
407 }
408 }
409 }
410
411 if (op_array->brk_cont_array) {
412 zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont);
413 }
414
415 if (op_array->static_variables) {
416 zend_hash_persist(op_array->static_variables, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
417 zend_accel_store(op_array->static_variables, sizeof(HashTable));
418 }
419
420 if (op_array->scope) {
421 op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
422 }
423
424 if (op_array->doc_comment) {
425 if (ZCG(accel_directives).save_comments) {
426 zend_accel_store(op_array->doc_comment, op_array->doc_comment_len + 1);
427 } else {
428 if (!zend_shared_alloc_get_xlat_entry(op_array->doc_comment)) {
429 zend_shared_alloc_register_xlat_entry(op_array->doc_comment, op_array->doc_comment);
430 efree((char*)op_array->doc_comment);
431 }
432 op_array->doc_comment = NULL;
433 op_array->doc_comment_len = 0;
434 }
435 }
436
437 if (op_array->try_catch_array) {
438 zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
439 }
440
441 if (op_array->vars) {
442 if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars))) {
443 op_array->vars = (zend_compiled_variable*)persist_ptr;
444 } else {
445 int i;
446 zend_accel_store(op_array->vars, sizeof(zend_compiled_variable) * op_array->last_var);
447 for (i = 0; i < op_array->last_var; i++) {
448 zend_accel_store_interned_string(op_array->vars[i].name, op_array->vars[i].name_len + 1);
449 }
450 }
451 }
452
453 /* "prototype" may be undefined if "scope" isn't set */
454 if (op_array->scope && op_array->prototype) {
455 if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
456 op_array->prototype = (union _zend_function*)persist_ptr;
457 /* we use refcount to show that op_array is referenced from several places */
458 op_array->prototype->op_array.refcount++;
459 }
460 } else {
461 op_array->prototype = NULL;
462 }
463 }
464
465 static void zend_persist_op_array(zend_op_array *op_array TSRMLS_DC)
466 {
467 zend_persist_op_array_ex(op_array, NULL TSRMLS_CC);
468 }
469
470 static void zend_persist_property_info(zend_property_info *prop TSRMLS_DC)
471 {
472 zend_accel_store_interned_string(prop->name, prop->name_length + 1);
473 if (prop->doc_comment) {
474 if (ZCG(accel_directives).save_comments) {
475 zend_accel_store(prop->doc_comment, prop->doc_comment_len + 1);
476 } else {
477 if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
478 zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
479 efree((char*)prop->doc_comment);
480 }
481 prop->doc_comment = NULL;
482 prop->doc_comment_len = 0;
483 }
484 }
485 }
486
487 static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC)
488 {
489 zend_class_entry *ce = *pce;
490
491 if (ce->type == ZEND_USER_CLASS) {
492 *pce = zend_accel_store(ce, sizeof(zend_class_entry));
493 zend_accel_store_interned_string(ce->name, ce->name_length + 1);
494 zend_hash_persist(&ce->function_table, (zend_persist_func_t) zend_persist_op_array, sizeof(zend_op_array) TSRMLS_CC);
495 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
496 if (ce->default_properties_table) {
497 int i;
498
499 zend_accel_store(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count);
500 for (i = 0; i < ce->default_properties_count; i++) {
501 if (ce->default_properties_table[i]) {
502 zend_persist_zval_ptr(&ce->default_properties_table[i] TSRMLS_CC);
503 }
504 }
505 }
506 if (ce->default_static_members_table) {
507 int i;
508
509 zend_accel_store(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count);
510 for (i = 0; i < ce->default_static_members_count; i++) {
511 if (ce->default_static_members_table[i]) {
512 zend_persist_zval_ptr(&ce->default_static_members_table[i] TSRMLS_CC);
513 }
514 }
515 }
516 ce->static_members_table = NULL;
517 #else
518 zend_hash_persist(&ce->default_properties, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
519 zend_hash_persist(&ce->default_static_members, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
520 ce->static_members = NULL;
521 #endif
522 zend_hash_persist(&ce->constants_table, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
523
524 if (ZEND_CE_FILENAME(ce)) {
525 /* do not free! PHP has centralized filename storage, compiler will free it */
526 ZEND_CE_FILENAME(ce) = zend_accel_memdup(ZEND_CE_FILENAME(ce), strlen(ZEND_CE_FILENAME(ce)) + 1);
527 }
528 if (ZEND_CE_DOC_COMMENT(ce)) {
529 if (ZCG(accel_directives).save_comments) {
530 zend_accel_store(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce) + 1);
531 } else {
532 if (!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) {
533 zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce));
534 efree((char*)ZEND_CE_DOC_COMMENT(ce));
535 }
536 ZEND_CE_DOC_COMMENT(ce) = NULL;
537 ZEND_CE_DOC_COMMENT_LEN(ce) = 0;
538 }
539 }
540 zend_hash_persist(&ce->properties_info, (zend_persist_func_t) zend_persist_property_info, sizeof(zend_property_info) TSRMLS_CC);
541 if (ce->num_interfaces && ce->interfaces) {
542 efree(ce->interfaces);
543 }
544 ce->interfaces = NULL; /* will be filled in on fetch */
545
546 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
547 if (ce->num_traits && ce->traits) {
548 efree(ce->traits);
549 }
550 ce->traits = NULL;
551
552 if (ce->trait_aliases) {
553 int i = 0;
554 while (ce->trait_aliases[i]) {
555 if (ce->trait_aliases[i]->trait_method) {
556 if (ce->trait_aliases[i]->trait_method->method_name) {
557 zend_accel_store(ce->trait_aliases[i]->trait_method->method_name,
558 ce->trait_aliases[i]->trait_method->mname_len + 1);
559 }
560 if (ce->trait_aliases[i]->trait_method->class_name) {
561 zend_accel_store(ce->trait_aliases[i]->trait_method->class_name,
562 ce->trait_aliases[i]->trait_method->cname_len + 1);
563 }
564 ce->trait_aliases[i]->trait_method->ce = NULL;
565 zend_accel_store(ce->trait_aliases[i]->trait_method,
566 sizeof(zend_trait_method_reference));
567 }
568
569 if (ce->trait_aliases[i]->alias) {
570 zend_accel_store(ce->trait_aliases[i]->alias,
571 ce->trait_aliases[i]->alias_len + 1);
572 }
573
574 #if ZEND_EXTENSION_API_NO <= PHP_5_4_X_API_NO
575 ce->trait_aliases[i]->function = NULL;
576 #endif
577 zend_accel_store(ce->trait_aliases[i], sizeof(zend_trait_alias));
578 i++;
579 }
580
581 zend_accel_store(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1));
582 }
583
584 if (ce->trait_precedences) {
585 int i = 0;
586
587 while (ce->trait_precedences[i]) {
588 zend_accel_store(ce->trait_precedences[i]->trait_method->method_name,
589 ce->trait_precedences[i]->trait_method->mname_len + 1);
590 zend_accel_store(ce->trait_precedences[i]->trait_method->class_name,
591 ce->trait_precedences[i]->trait_method->cname_len + 1);
592 ce->trait_precedences[i]->trait_method->ce = NULL;
593 zend_accel_store(ce->trait_precedences[i]->trait_method,
594 sizeof(zend_trait_method_reference));
595
596 if (ce->trait_precedences[i]->exclude_from_classes) {
597 int j = 0;
598
599 while (ce->trait_precedences[i]->exclude_from_classes[j]) {
600 zend_accel_store(ce->trait_precedences[i]->exclude_from_classes[j],
601 strlen((char*)ce->trait_precedences[i]->exclude_from_classes[j]) + 1);
602 j++;
603 }
604 zend_accel_store(ce->trait_precedences[i]->exclude_from_classes,
605 sizeof(zend_class_entry*) * (j + 1));
606 }
607
608 #if ZEND_EXTENSION_API_NO <= PHP_5_4_X_API_NO
609 ce->trait_precedences[i]->function = NULL;
610 #endif
611 zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence));
612 i++;
613 }
614 zend_accel_store(
615 ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
616 }
617 #endif
618 }
619 }
620
621 static int zend_update_property_info_ce(zend_property_info *prop TSRMLS_DC)
622 {
623 prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
624 return 0;
625 }
626
627 static int zend_update_parent_ce(zend_class_entry **pce TSRMLS_DC)
628 {
629 zend_class_entry *ce = *pce;
630
631 if (ce->parent) {
632 ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
633 /* We use refcount to show if the class is used as a parent */
634 ce->parent->refcount++;
635 }
636
637 /* update methods */
638 if (ce->constructor) {
639 ce->constructor = zend_shared_alloc_get_xlat_entry(ce->constructor);
640 /* we use refcount to show that op_array is referenced from several places */
641 ce->constructor->op_array.refcount++;
642 }
643 if (ce->destructor) {
644 ce->destructor = zend_shared_alloc_get_xlat_entry(ce->destructor);
645 ce->destructor->op_array.refcount++;
646 }
647 if (ce->clone) {
648 ce->clone = zend_shared_alloc_get_xlat_entry(ce->clone);
649 ce->clone->op_array.refcount++;
650 }
651 if (ce->__get) {
652 ce->__get = zend_shared_alloc_get_xlat_entry(ce->__get);
653 ce->__get->op_array.refcount++;
654 }
655 if (ce->__set) {
656 ce->__set = zend_shared_alloc_get_xlat_entry(ce->__set);
657 ce->__set->op_array.refcount++;
658 }
659 if (ce->__call) {
660 ce->__call = zend_shared_alloc_get_xlat_entry(ce->__call);
661 ce->__call->op_array.refcount++;
662 }
663 if (ce->serialize_func) {
664 ce->serialize_func = zend_shared_alloc_get_xlat_entry(ce->serialize_func);
665 ce->serialize_func->op_array.refcount++;
666 }
667 if (ce->unserialize_func) {
668 ce->unserialize_func = zend_shared_alloc_get_xlat_entry(ce->unserialize_func);
669 ce->unserialize_func->op_array.refcount++;
670 }
671 if (ce->__isset) {
672 ce->__isset = zend_shared_alloc_get_xlat_entry(ce->__isset);
673 ce->__isset->op_array.refcount++;
674 }
675 if (ce->__unset) {
676 ce->__unset = zend_shared_alloc_get_xlat_entry(ce->__unset);
677 ce->__unset->op_array.refcount++;
678 }
679 if (ce->__tostring) {
680 ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring);
681 ce->__tostring->op_array.refcount++;
682 }
683 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
684 if (ce->__callstatic) {
685 ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
686 ce->__callstatic->op_array.refcount++;
687 }
688 #endif
689 #if ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
690 if (ce->__debugInfo) {
691 ce->__debugInfo = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
692 ce->__debugInfo->op_array.refcount++;
693 }
694 #endif
695 zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce TSRMLS_CC);
696 return 0;
697 }
698
699 static void zend_accel_persist_class_table(HashTable *class_table TSRMLS_DC)
700 {
701 zend_hash_persist(class_table, (zend_persist_func_t) zend_persist_class_entry, sizeof(zend_class_entry*) TSRMLS_CC);
702 zend_hash_apply(class_table, (apply_func_t) zend_update_parent_ce TSRMLS_CC);
703 }
704
705 zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length TSRMLS_DC)
706 {
707 zend_shared_alloc_clear_xlat_table();
708 zend_hash_persist(&script->function_table, (zend_persist_func_t) zend_persist_op_array, sizeof(zend_op_array) TSRMLS_CC);
709 zend_accel_persist_class_table(&script->class_table TSRMLS_CC);
710 zend_persist_op_array_ex(&script->main_op_array, script TSRMLS_CC);
711 *key = zend_accel_memdup(*key, key_length + 1);
712 zend_accel_store(script->full_path, script->full_path_len + 1);
713 zend_accel_store(script, sizeof(zend_persistent_script));
714
715 return script;
716 }
717
718 int zend_accel_script_persistable(zend_persistent_script *script)
719 {
720 return 1;
721 }
722