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