1 /*
2    +----------------------------------------------------------------------+
3    | Zend OPcache                                                         |
4    +----------------------------------------------------------------------+
5    | Copyright (c) The PHP Group                                          |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | 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@php.net>                                 |
16    |          Zeev Suraski <zeev@php.net>                                 |
17    |          Stanislav Malyshev <stas@zend.com>                          |
18    |          Dmitry Stogov <dmitry@php.net>                              |
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_operators.h"
28 
29 #define ADD_DUP_SIZE(m,s)  ZCG(current_persistent_script)->size += zend_shared_memdup_size((void*)m, s)
30 #define ADD_SIZE(m)        ZCG(current_persistent_script)->size += ZEND_ALIGNED_SIZE(m)
31 #define ADD_ARENA_SIZE(m)  ZCG(current_persistent_script)->arena_size += ZEND_ALIGNED_SIZE(m)
32 
33 #define ADD_SIZE_EX(m) do { \
34 		if (ZCG(is_immutable_class)) { \
35 			ADD_SIZE(m); \
36 		} else { \
37 			ADD_ARENA_SIZE(m); \
38 		} \
39 	} while (0)
40 
41 # define ADD_STRING(str) ADD_DUP_SIZE((str), _ZSTR_STRUCT_SIZE(ZSTR_LEN(str)))
42 
43 # define ADD_INTERNED_STRING(str) do { \
44 		if (ZCG(current_persistent_script)->corrupted) { \
45 			ADD_STRING(str); \
46 		} else if (!IS_ACCEL_INTERNED(str)) { \
47 			zend_string *tmp = accel_new_interned_string(str); \
48 			if (tmp != (str)) { \
49 				(str) = tmp; \
50 			} else { \
51 				ADD_STRING(str); \
52 			} \
53 		} \
54 	} while (0)
55 
56 static void zend_persist_zval_calc(zval *z);
57 
zend_hash_persist_calc(HashTable *ht)58 static void zend_hash_persist_calc(HashTable *ht)
59 {
60 	if ((HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) || ht->nNumUsed == 0) {
61 		return;
62 	}
63 
64 	if (!(HT_FLAGS(ht) & HASH_FLAG_PACKED) && ht->nNumUsed > HT_MIN_SIZE && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) {
65 		/* compact table */
66 		uint32_t hash_size;
67 
68 		hash_size = (uint32_t)(-(int32_t)ht->nTableMask);
69 		while (hash_size >> 2 > ht->nNumUsed) {
70 			hash_size >>= 1;
71 		}
72 		ADD_SIZE(hash_size * sizeof(uint32_t) + ht->nNumUsed * sizeof(Bucket));
73 	} else {
74 		ADD_SIZE(HT_USED_SIZE(ht));
75 	}
76 }
77 
zend_persist_ast_calc(zend_ast *ast)78 static void zend_persist_ast_calc(zend_ast *ast)
79 {
80 	uint32_t i;
81 
82 	if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
83 		ADD_SIZE(sizeof(zend_ast_zval));
84 		zend_persist_zval_calc(&((zend_ast_zval*)(ast))->val);
85 	} else if (zend_ast_is_list(ast)) {
86 		zend_ast_list *list = zend_ast_get_list(ast);
87 		ADD_SIZE(sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
88 		for (i = 0; i < list->children; i++) {
89 			if (list->child[i]) {
90 				zend_persist_ast_calc(list->child[i]);
91 			}
92 		}
93 	} else {
94 		uint32_t children = zend_ast_get_num_children(ast);
95 		ADD_SIZE(sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
96 		for (i = 0; i < children; i++) {
97 			if (ast->child[i]) {
98 				zend_persist_ast_calc(ast->child[i]);
99 			}
100 		}
101 	}
102 }
103 
zend_persist_zval_calc(zval *z)104 static void zend_persist_zval_calc(zval *z)
105 {
106 	uint32_t size;
107 
108 	switch (Z_TYPE_P(z)) {
109 		case IS_STRING:
110 			ADD_INTERNED_STRING(Z_STR_P(z));
111 			if (ZSTR_IS_INTERNED(Z_STR_P(z))) {
112 				Z_TYPE_FLAGS_P(z) = 0;
113 			}
114 			break;
115 		case IS_ARRAY:
116 			size = zend_shared_memdup_size(Z_ARR_P(z), sizeof(zend_array));
117 			if (size) {
118 				Bucket *p;
119 
120 				ADD_SIZE(size);
121 				zend_hash_persist_calc(Z_ARRVAL_P(z));
122 				ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(z), p) {
123 					if (p->key) {
124 						ADD_INTERNED_STRING(p->key);
125 					}
126 					zend_persist_zval_calc(&p->val);
127 				} ZEND_HASH_FOREACH_END();
128 			}
129 			break;
130 		case IS_REFERENCE:
131 			size = zend_shared_memdup_size(Z_REF_P(z), sizeof(zend_reference));
132 			if (size) {
133 				ADD_SIZE(size);
134 				zend_persist_zval_calc(Z_REFVAL_P(z));
135 			}
136 			break;
137 		case IS_CONSTANT_AST:
138 			size = zend_shared_memdup_size(Z_AST_P(z), sizeof(zend_ast_ref));
139 			if (size) {
140 				ADD_SIZE(size);
141 				zend_persist_ast_calc(Z_ASTVAL_P(z));
142 			}
143 			break;
144 		default:
145 			ZEND_ASSERT(Z_TYPE_P(z) != IS_OBJECT);
146 			ZEND_ASSERT(Z_TYPE_P(z) != IS_RESOURCE);
147 			break;
148 	}
149 }
150 
zend_persist_op_array_calc_ex(zend_op_array *op_array)151 static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
152 {
153 	if (op_array->scope && zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
154 		/* already stored */
155 		if (op_array->function_name) {
156 			zend_string *new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
157 			if (new_name) {
158 				op_array->function_name = new_name;
159 			}
160 		}
161 		ADD_SIZE(ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist_calc(op_array)));
162 		return;
163 	}
164 
165 	if (op_array->static_variables) {
166 		if (!zend_shared_alloc_get_xlat_entry(op_array->static_variables)) {
167 			Bucket *p;
168 
169 			zend_shared_alloc_register_xlat_entry(op_array->static_variables, op_array->static_variables);
170 			ADD_SIZE(sizeof(HashTable));
171 			zend_hash_persist_calc(op_array->static_variables);
172 			ZEND_HASH_FOREACH_BUCKET(op_array->static_variables, p) {
173 				ZEND_ASSERT(p->key != NULL);
174 				ADD_INTERNED_STRING(p->key);
175 				zend_persist_zval_calc(&p->val);
176 			} ZEND_HASH_FOREACH_END();
177 		}
178 	}
179 
180 	if (op_array->literals) {
181 		zval *p = op_array->literals;
182 		zval *end = p + op_array->last_literal;
183 		ADD_SIZE(sizeof(zval) * op_array->last_literal);
184 		while (p < end) {
185 			zend_persist_zval_calc(p);
186 			p++;
187 		}
188 	}
189 
190 	zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array->opcodes);
191 	ADD_SIZE(sizeof(zend_op) * op_array->last);
192 
193 	if (op_array->function_name) {
194 		zend_string *old_name = op_array->function_name;
195 		if (!zend_shared_alloc_get_xlat_entry(old_name)) {
196 			ADD_INTERNED_STRING(op_array->function_name);
197 			if (!zend_shared_alloc_get_xlat_entry(op_array->function_name)) {
198 				zend_shared_alloc_register_xlat_entry(old_name, op_array->function_name);
199 			}
200 		}
201     }
202 
203 	if (op_array->filename) {
204 		ADD_STRING(op_array->filename);
205 	}
206 
207 	if (op_array->arg_info) {
208 		zend_arg_info *arg_info = op_array->arg_info;
209 		uint32_t num_args = op_array->num_args;
210 		uint32_t i;
211 
212 		num_args = op_array->num_args;
213 		if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
214 			num_args++;
215 		}
216 		if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
217 			arg_info--;
218 			num_args++;
219 		}
220 		ADD_SIZE(sizeof(zend_arg_info) * num_args);
221 		for (i = 0; i < num_args; i++) {
222 			if (arg_info[i].name) {
223 				ADD_INTERNED_STRING(arg_info[i].name);
224 			}
225 			if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
226 				zend_string *type_name = ZEND_TYPE_NAME(arg_info[i].type);
227 				zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(arg_info[i].type);
228 
229 				ADD_INTERNED_STRING(type_name);
230 				arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(type_name, allow_null);
231 			}
232 		}
233 	}
234 
235 	if (op_array->live_range) {
236 		ADD_SIZE(sizeof(zend_live_range) * op_array->last_live_range);
237 	}
238 
239 	if (ZCG(accel_directives).save_comments && op_array->doc_comment) {
240 		ADD_STRING(op_array->doc_comment);
241 	}
242 
243 	if (op_array->try_catch_array) {
244 		ADD_SIZE(sizeof(zend_try_catch_element) * op_array->last_try_catch);
245 	}
246 
247 	if (op_array->vars) {
248 		int i;
249 
250 		ADD_SIZE(sizeof(zend_string*) * op_array->last_var);
251 		for (i = 0; i < op_array->last_var; i++) {
252 			ADD_INTERNED_STRING(op_array->vars[i]);
253 		}
254 	}
255 
256 	ADD_SIZE(ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist_calc(op_array)));
257 }
258 
zend_persist_op_array_calc(zval *zv)259 static void zend_persist_op_array_calc(zval *zv)
260 {
261 	zend_op_array *op_array = Z_PTR_P(zv);
262 
263 	ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
264 	ADD_SIZE(sizeof(zend_op_array));
265 	zend_persist_op_array_calc_ex(Z_PTR_P(zv));
266 	if (ZCG(current_persistent_script)->corrupted) {
267 		ADD_ARENA_SIZE(sizeof(void*));
268 	}
269 }
270 
zend_persist_class_method_calc(zval *zv)271 static void zend_persist_class_method_calc(zval *zv)
272 {
273 	zend_op_array *op_array = Z_PTR_P(zv);
274 	zend_op_array *old_op_array;
275 
276 	if (op_array->type != ZEND_USER_FUNCTION) {
277 		ZEND_ASSERT(op_array->type == ZEND_INTERNAL_FUNCTION);
278 		if (op_array->fn_flags & ZEND_ACC_ARENA_ALLOCATED) {
279 			old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
280 			if (!old_op_array) {
281 				ADD_SIZE_EX(sizeof(zend_internal_function));
282 				zend_shared_alloc_register_xlat_entry(op_array, Z_PTR_P(zv));
283 			}
284 		}
285 		return;
286 	}
287 
288 	old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
289 	if (!old_op_array) {
290 		ADD_SIZE_EX(sizeof(zend_op_array));
291 		zend_persist_op_array_calc_ex(Z_PTR_P(zv));
292 		zend_shared_alloc_register_xlat_entry(op_array, Z_PTR_P(zv));
293 		if (!ZCG(is_immutable_class)) {
294 			ADD_ARENA_SIZE(sizeof(void*));
295 		}
296 	}
297 }
298 
zend_persist_property_info_calc(zval *zv)299 static void zend_persist_property_info_calc(zval *zv)
300 {
301 	zend_property_info *prop = Z_PTR_P(zv);
302 
303 	if (!zend_shared_alloc_get_xlat_entry(prop)) {
304 		zend_shared_alloc_register_xlat_entry(prop, prop);
305 		ADD_SIZE_EX(sizeof(zend_property_info));
306 		ADD_INTERNED_STRING(prop->name);
307 		if (ZEND_TYPE_IS_NAME(prop->type)) {
308 			zend_string *class_name = ZEND_TYPE_NAME(prop->type);
309 			ADD_INTERNED_STRING(class_name);
310 			prop->type = ZEND_TYPE_ENCODE_CLASS(class_name, ZEND_TYPE_ALLOW_NULL(prop->type));
311 		}
312 		if (ZCG(accel_directives).save_comments && prop->doc_comment) {
313 			ADD_STRING(prop->doc_comment);
314 		}
315 	}
316 }
317 
zend_persist_class_constant_calc(zval *zv)318 static void zend_persist_class_constant_calc(zval *zv)
319 {
320 	zend_class_constant *c = Z_PTR_P(zv);
321 
322 	if (!zend_shared_alloc_get_xlat_entry(c)) {
323 		zend_shared_alloc_register_xlat_entry(c, c);
324 		ADD_SIZE_EX(sizeof(zend_class_constant));
325 		zend_persist_zval_calc(&c->value);
326 		if (ZCG(accel_directives).save_comments && c->doc_comment) {
327 			ADD_STRING(c->doc_comment);
328 		}
329 	}
330 }
331 
check_property_type_resolution(zend_class_entry *ce)332 static void check_property_type_resolution(zend_class_entry *ce) {
333 	zend_property_info *prop;
334 	if (ce->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED) {
335 		/* Preloading might have computed this already. */
336 		return;
337 	}
338 
339 	if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) {
340 		ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
341 			if (ZEND_TYPE_IS_NAME(prop->type)) {
342 				return;
343 			}
344 		} ZEND_HASH_FOREACH_END();
345 	}
346 	ce->ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED;
347 }
348 
zend_persist_class_entry_calc(zval *zv)349 static void zend_persist_class_entry_calc(zval *zv)
350 {
351 	zend_class_entry *ce = Z_PTR_P(zv);
352 	Bucket *p;
353 
354 	if (ce->type == ZEND_USER_CLASS) {
355 		/* The same zend_class_entry may be reused by class_alias */
356 		if (zend_shared_alloc_get_xlat_entry(ce)) {
357 			return;
358 		}
359 		zend_shared_alloc_register_xlat_entry(ce, ce);
360 
361 		check_property_type_resolution(ce);
362 
363 		ZCG(is_immutable_class) =
364 			(ce->ce_flags & ZEND_ACC_LINKED) &&
365 			(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) &&
366 			(ce->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED) &&
367 			!ZCG(current_persistent_script)->corrupted;
368 
369 		ADD_SIZE_EX(sizeof(zend_class_entry));
370 		ADD_INTERNED_STRING(ce->name);
371 		if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_LINKED)) {
372 			ADD_INTERNED_STRING(ce->parent_name);
373 		}
374 		zend_hash_persist_calc(&ce->function_table);
375 		ZEND_HASH_FOREACH_BUCKET(&ce->function_table, p) {
376 			ZEND_ASSERT(p->key != NULL);
377 			ADD_INTERNED_STRING(p->key);
378 			zend_persist_class_method_calc(&p->val);
379 		} ZEND_HASH_FOREACH_END();
380 		if (ce->default_properties_table) {
381 		    int i;
382 
383 			ADD_SIZE(sizeof(zval) * ce->default_properties_count);
384 			for (i = 0; i < ce->default_properties_count; i++) {
385 				zend_persist_zval_calc(&ce->default_properties_table[i]);
386 			}
387 		}
388 		if (ce->default_static_members_table) {
389 		    int i;
390 
391 			ADD_SIZE(sizeof(zval) * ce->default_static_members_count);
392 			for (i = 0; i < ce->default_static_members_count; i++) {
393 				if (Z_TYPE(ce->default_static_members_table[i]) != IS_INDIRECT) {
394 					zend_persist_zval_calc(&ce->default_static_members_table[i]);
395 				}
396 			}
397 		}
398 		zend_hash_persist_calc(&ce->constants_table);
399 		ZEND_HASH_FOREACH_BUCKET(&ce->constants_table, p) {
400 			ZEND_ASSERT(p->key != NULL);
401 			ADD_INTERNED_STRING(p->key);
402 			zend_persist_class_constant_calc(&p->val);
403 		} ZEND_HASH_FOREACH_END();
404 
405 		if (ce->info.user.filename) {
406 			ADD_STRING(ce->info.user.filename);
407 		}
408 		if (ZCG(accel_directives).save_comments && ce->info.user.doc_comment) {
409 			ADD_STRING(ce->info.user.doc_comment);
410 		}
411 
412 		zend_hash_persist_calc(&ce->properties_info);
413 		ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) {
414 			ZEND_ASSERT(p->key != NULL);
415 			ADD_INTERNED_STRING(p->key);
416 			zend_persist_property_info_calc(&p->val);
417 		} ZEND_HASH_FOREACH_END();
418 
419 		if (ce->properties_info_table) {
420 			ADD_SIZE_EX(sizeof(zend_property_info *) * ce->default_properties_count);
421 		}
422 
423 		if (ce->num_interfaces) {
424 			uint32_t i;
425 
426 			if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
427 				for (i = 0; i < ce->num_interfaces; i++) {
428 					ADD_INTERNED_STRING(ce->interface_names[i].name);
429 					ADD_INTERNED_STRING(ce->interface_names[i].lc_name);
430 				}
431 				ADD_SIZE(sizeof(zend_class_name) * ce->num_interfaces);
432 			} else {
433 				ADD_SIZE(sizeof(zend_class_entry*) * ce->num_interfaces);
434 			}
435 		}
436 
437 		if (ce->num_traits) {
438 			uint32_t i;
439 
440 			for (i = 0; i < ce->num_traits; i++) {
441 				ADD_INTERNED_STRING(ce->trait_names[i].name);
442 				ADD_INTERNED_STRING(ce->trait_names[i].lc_name);
443 			}
444 			ADD_SIZE(sizeof(zend_class_name) * ce->num_traits);
445 
446 			if (ce->trait_aliases) {
447 				i = 0;
448 				while (ce->trait_aliases[i]) {
449 					if (ce->trait_aliases[i]->trait_method.method_name) {
450 						ADD_INTERNED_STRING(ce->trait_aliases[i]->trait_method.method_name);
451 					}
452 					if (ce->trait_aliases[i]->trait_method.class_name) {
453 						ADD_INTERNED_STRING(ce->trait_aliases[i]->trait_method.class_name);
454 					}
455 
456 					if (ce->trait_aliases[i]->alias) {
457 						ADD_INTERNED_STRING(ce->trait_aliases[i]->alias);
458 					}
459 					ADD_SIZE(sizeof(zend_trait_alias));
460 					i++;
461 				}
462 				ADD_SIZE(sizeof(zend_trait_alias*) * (i + 1));
463 			}
464 
465 			if (ce->trait_precedences) {
466 				int j;
467 
468 				i = 0;
469 				while (ce->trait_precedences[i]) {
470 					ADD_INTERNED_STRING(ce->trait_precedences[i]->trait_method.method_name);
471 					ADD_INTERNED_STRING(ce->trait_precedences[i]->trait_method.class_name);
472 
473 					for (j = 0; j < ce->trait_precedences[i]->num_excludes; j++) {
474 						ADD_INTERNED_STRING(ce->trait_precedences[i]->exclude_class_names[j]);
475 					}
476 					ADD_SIZE(sizeof(zend_trait_precedence) + (ce->trait_precedences[i]->num_excludes - 1) * sizeof(zend_string*));
477 					i++;
478 				}
479 				ADD_SIZE(sizeof(zend_trait_precedence*) * (i + 1));
480 			}
481 		}
482 
483 		if (ce->iterator_funcs_ptr) {
484 			ADD_SIZE(sizeof(zend_class_iterator_funcs));
485 		}
486 	}
487 }
488 
zend_accel_persist_class_table_calc(HashTable *class_table)489 static void zend_accel_persist_class_table_calc(HashTable *class_table)
490 {
491 	Bucket *p;
492 
493 	zend_hash_persist_calc(class_table);
494 	ZEND_HASH_FOREACH_BUCKET(class_table, p) {
495 		ZEND_ASSERT(p->key != NULL);
496 		ADD_INTERNED_STRING(p->key);
497 		zend_persist_class_entry_calc(&p->val);
498 	} ZEND_HASH_FOREACH_END();
499 }
500 
zend_accel_script_persist_calc(zend_persistent_script *new_persistent_script, const char *key, unsigned int key_length, int for_shm)501 uint32_t zend_accel_script_persist_calc(zend_persistent_script *new_persistent_script, const char *key, unsigned int key_length, int for_shm)
502 {
503 	Bucket *p;
504 
505 	new_persistent_script->mem = NULL;
506 	new_persistent_script->size = 0;
507 	new_persistent_script->arena_mem = NULL;
508 	new_persistent_script->arena_size = 0;
509 	new_persistent_script->corrupted = 0;
510 	ZCG(current_persistent_script) = new_persistent_script;
511 
512 	if (!for_shm) {
513 		/* script is not going to be saved in SHM */
514 		new_persistent_script->corrupted = 1;
515 	}
516 
517 	ADD_SIZE(sizeof(zend_persistent_script));
518 	if (key) {
519 		ADD_SIZE(key_length + 1);
520 		zend_shared_alloc_register_xlat_entry(key, key);
521 	}
522 	ADD_STRING(new_persistent_script->script.filename);
523 
524 #if defined(__AVX__) || defined(__SSE2__)
525 	/* Align size to 64-byte boundary */
526 	new_persistent_script->size = (new_persistent_script->size + 63) & ~63;
527 #endif
528 
529 	if (new_persistent_script->script.class_table.nNumUsed != new_persistent_script->script.class_table.nNumOfElements) {
530 		zend_hash_rehash(&new_persistent_script->script.class_table);
531 	}
532 	zend_accel_persist_class_table_calc(&new_persistent_script->script.class_table);
533 	if (new_persistent_script->script.function_table.nNumUsed != new_persistent_script->script.function_table.nNumOfElements) {
534 		zend_hash_rehash(&new_persistent_script->script.function_table);
535 	}
536 	zend_hash_persist_calc(&new_persistent_script->script.function_table);
537 	ZEND_HASH_FOREACH_BUCKET(&new_persistent_script->script.function_table, p) {
538 		ZEND_ASSERT(p->key != NULL);
539 		ADD_INTERNED_STRING(p->key);
540 		zend_persist_op_array_calc(&p->val);
541 	} ZEND_HASH_FOREACH_END();
542 	zend_persist_op_array_calc_ex(&new_persistent_script->script.main_op_array);
543 
544 #if defined(__AVX__) || defined(__SSE2__)
545 	/* Align size to 64-byte boundary */
546 	new_persistent_script->arena_size = (new_persistent_script->arena_size + 63) & ~63;
547 #endif
548 
549 	new_persistent_script->size += new_persistent_script->arena_size;
550 	new_persistent_script->corrupted = 0;
551 
552 	ZCG(current_persistent_script) = NULL;
553 
554 	return new_persistent_script->size;
555 }
556