示例#1
0
static zend_ast *zend_file_cache_unserialize_ast(zend_ast                *ast,
                                                 zend_persistent_script  *script,
                                                 void                    *buf)
{
	uint32_t i;

	UNSERIALIZE_PTR(ast);

	if (ast->kind == ZEND_AST_ZVAL) {
		zend_file_cache_unserialize_zval(&((zend_ast_zval*)ast)->val, script, buf);
	} else if (zend_ast_is_list(ast)) {
		zend_ast_list *list = zend_ast_get_list(ast);
		for (i = 0; i < list->children; i++) {
			if (list->child[i]) {
				list->child[i] = zend_file_cache_unserialize_ast(list->child[i], script, buf);
			}
		}
	} else {
		uint32_t children = zend_ast_get_num_children(ast);
		for (i = 0; i < children; i++) {
			if (ast->child[i]) {
				ast->child[i] = zend_file_cache_unserialize_ast(ast->child[i], script, buf);
			}
		}
	}
	return ast;
}
示例#2
0
static void zend_file_cache_serialize_hash(HashTable                *ht,
                                           zend_persistent_script   *script,
                                           zend_file_cache_metainfo *info,
                                           void                     *buf,
                                           serialize_callback_t      func)
{
	Bucket *p, *end;

	if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
		ht->arData = NULL;
		return;
	}
	if (IS_SERIALIZED(ht->arData)) {
		return;
	}
	SERIALIZE_PTR(ht->arData);
	p = ht->arData;
	UNSERIALIZE_PTR(p);
	end = p + ht->nNumUsed;
	while (p < end) {
		if (Z_TYPE(p->val) != IS_UNDEF) {
			SERIALIZE_STR(p->key);
			func(&p->val, script, info, buf);
		}
		p++;
	}
}
示例#3
0
static void zend_file_cache_unserialize_hash(HashTable               *ht,
                                             zend_persistent_script  *script,
                                             void                    *buf,
                                             unserialize_callback_t   func,
                                             dtor_func_t              dtor)
{
	Bucket *p, *end;

	ht->pDestructor = dtor;
	if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
		HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
		return;
	}
	if (IS_UNSERIALIZED(ht->arData)) {
		return;
	}
	UNSERIALIZE_PTR(ht->arData);
	p = ht->arData;
	end = p + ht->nNumUsed;
	while (p < end) {
		if (Z_TYPE(p->val) != IS_UNDEF) {
			UNSERIALIZE_STR(p->key);
			func(&p->val, script, buf);
		}
		p++;
	}
}
示例#4
0
static void zend_file_cache_serialize_zval(zval                     *zv,
                                           zend_persistent_script   *script,
                                           zend_file_cache_metainfo *info,
                                           void                     *buf)
{
	switch (Z_TYPE_P(zv)) {
		case IS_STRING:
		case IS_CONSTANT:
			if (!IS_SERIALIZED(Z_STR_P(zv))) {
				SERIALIZE_STR(Z_STR_P(zv));
			}
			break;
		case IS_ARRAY:
			if (!IS_SERIALIZED(Z_ARR_P(zv))) {
				HashTable *ht;

				SERIALIZE_PTR(Z_ARR_P(zv));
				ht = Z_ARR_P(zv);
				UNSERIALIZE_PTR(ht);
				zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
			}
			break;
		case IS_REFERENCE:
			if (!IS_SERIALIZED(Z_REF_P(zv))) {
				zend_reference *ref;

				SERIALIZE_PTR(Z_REF_P(zv));
				ref = Z_REF_P(zv);
				UNSERIALIZE_PTR(ref);
				zend_file_cache_serialize_zval(&ref->val, script, info, buf);
			}
			break;
		case IS_CONSTANT_AST:
			if (!IS_SERIALIZED(Z_AST_P(zv))) {
				zend_ast_ref *ast;

				SERIALIZE_PTR(Z_AST_P(zv));
				ast = Z_AST_P(zv);
				UNSERIALIZE_PTR(ast);
				if (!IS_SERIALIZED(ast->ast)) {
					ast->ast = zend_file_cache_serialize_ast(ast->ast, script, info, buf);
				}
			}
			break;
	}
}
示例#5
0
static void zend_file_cache_unserialize_class_constant(zval                    *zv,
                                                       zend_persistent_script  *script,
                                                       void                    *buf)
{
	if (!IS_UNSERIALIZED(Z_PTR_P(zv))) {
		zend_class_constant *c;

		UNSERIALIZE_PTR(Z_PTR_P(zv));
		c = Z_PTR_P(zv);

		zend_file_cache_unserialize_zval(&c->value, script, buf);
		if (c->ce && !IS_UNSERIALIZED(c->ce)) {
			UNSERIALIZE_PTR(c->ce);
		}
		if (c->doc_comment && !IS_UNSERIALIZED(c->doc_comment)) {
			UNSERIALIZE_STR(c->doc_comment);
		}
	}
}
示例#6
0
static void zend_file_cache_unserialize_func(zval                    *zv,
                                             zend_persistent_script  *script,
                                             void                    *buf)
{
	zend_op_array *op_array;

	UNSERIALIZE_PTR(Z_PTR_P(zv));
	op_array = Z_PTR_P(zv);
	zend_file_cache_unserialize_op_array(op_array, script, buf);
}
示例#7
0
static void zend_file_cache_unserialize_prop_info(zval                    *zv,
                                                  zend_persistent_script  *script,
                                                  void                    *buf)
{
	if (!IS_UNSERIALIZED(Z_PTR_P(zv))) {
		zend_property_info *prop;

		UNSERIALIZE_PTR(Z_PTR_P(zv));
		prop = Z_PTR_P(zv);

		if (prop->ce && !IS_UNSERIALIZED(prop->ce)) {
			UNSERIALIZE_PTR(prop->ce);
		}
		if (prop->name && !IS_UNSERIALIZED(prop->name)) {
			UNSERIALIZE_STR(prop->name);
		}
		if (prop->doc_comment && !IS_UNSERIALIZED(prop->doc_comment)) {
			UNSERIALIZE_STR(prop->doc_comment);
		}
	}
}
示例#8
0
static void zend_file_cache_unserialize(zend_persistent_script  *script,
                                        void                    *buf)
{
	script->mem = buf;

	UNSERIALIZE_STR(script->script.filename);

	zend_file_cache_unserialize_hash(&script->script.class_table,
			script, buf, zend_file_cache_unserialize_class, ZEND_CLASS_DTOR);
	zend_file_cache_unserialize_hash(&script->script.function_table,
			script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
	zend_file_cache_unserialize_op_array(&script->script.main_op_array, script, buf);

	UNSERIALIZE_PTR(script->arena_mem);
}
示例#9
0
static void zend_file_cache_unserialize_op_array(zend_op_array           *op_array,
                                                 zend_persistent_script  *script,
                                                 void                    *buf)
{
	if (op_array->static_variables && !IS_UNSERIALIZED(op_array->static_variables)) {
		HashTable *ht;

		UNSERIALIZE_PTR(op_array->static_variables);
		ht = op_array->static_variables;
		zend_file_cache_unserialize_hash(ht,
				script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
	}

	if (op_array->literals && !IS_UNSERIALIZED(op_array->literals)) {
		zval *p, *end;

		UNSERIALIZE_PTR(op_array->literals);
		p = op_array->literals;
		end = p + op_array->last_literal;
		while (p < end) {
			zend_file_cache_unserialize_zval(p, script, buf);
			p++;
		}
	}

	if (!IS_UNSERIALIZED(op_array->opcodes)) {
		zend_op *opline, *end;

		UNSERIALIZE_PTR(op_array->opcodes);
		opline = op_array->opcodes;
		end = opline + op_array->last;
		while (opline < end) {
# if ZEND_USE_ABS_CONST_ADDR
			if (opline->op1_type == IS_CONST) {
				UNSERIALIZE_PTR(opline->op1.zv);
			}
			if (opline->op2_type == IS_CONST) {
				UNSERIALIZE_PTR(opline->op2.zv);
			}
# endif
# if ZEND_USE_ABS_JMP_ADDR
			switch (opline->opcode) {
				case ZEND_JMP:
				case ZEND_FAST_CALL:
					UNSERIALIZE_PTR(opline->op1.jmp_addr);
					break;
				case ZEND_JMPZNZ:
					/* relative extended_value don't have to be changed */
					/* break omitted intentionally */
				case ZEND_JMPZ:
				case ZEND_JMPNZ:
				case ZEND_JMPZ_EX:
				case ZEND_JMPNZ_EX:
				case ZEND_JMP_SET:
				case ZEND_COALESCE:
				case ZEND_FE_RESET_R:
				case ZEND_FE_RESET_RW:
				case ZEND_ASSERT_CHECK:
					UNSERIALIZE_PTR(opline->op2.jmp_addr);
					break;
				case ZEND_DECLARE_ANON_CLASS:
				case ZEND_DECLARE_ANON_INHERITED_CLASS:
				case ZEND_FE_FETCH_R:
				case ZEND_FE_FETCH_RW:
					/* relative extended_value don't have to be changed */
					break;
			}
# endif
			zend_deserialize_opcode_handler(opline);
			opline++;
		}

		if (op_array->arg_info) {
			zend_arg_info *p, *end;
			UNSERIALIZE_PTR(op_array->arg_info);
			p = op_array->arg_info;
			end = p + op_array->num_args;
			if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
				p--;
			}
			if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
				end++;
			}
			while (p < end) {
				if (!IS_UNSERIALIZED(p->name)) {
					UNSERIALIZE_STR(p->name);
				}
				if (!IS_UNSERIALIZED(p->class_name)) {
					UNSERIALIZE_STR(p->class_name);
				}
				p++;
			}
		}

		if (op_array->vars) {
			zend_string **p, **end;

			UNSERIALIZE_PTR(op_array->vars);
			p = op_array->vars;
			end = p + op_array->last_var;
			while (p < end) {
				if (!IS_UNSERIALIZED(*p)) {
					UNSERIALIZE_STR(*p);
				}
				p++;
			}
		}

		UNSERIALIZE_STR(op_array->function_name);
		UNSERIALIZE_STR(op_array->filename);
		UNSERIALIZE_PTR(op_array->live_range);
		UNSERIALIZE_PTR(op_array->scope);
		UNSERIALIZE_STR(op_array->doc_comment);
		UNSERIALIZE_PTR(op_array->try_catch_array);
		UNSERIALIZE_PTR(op_array->prototype);
	}
}
示例#10
0
static void zend_file_cache_serialize_class(zval                     *zv,
                                            zend_persistent_script   *script,
                                            zend_file_cache_metainfo *info,
                                            void                     *buf)
{
	zend_class_entry *ce;

	SERIALIZE_PTR(Z_PTR_P(zv));
	ce = Z_PTR_P(zv);
	UNSERIALIZE_PTR(ce);

	SERIALIZE_STR(ce->name);
	zend_file_cache_serialize_hash(&ce->function_table, script, info, buf, zend_file_cache_serialize_func);
	if (ce->default_properties_table) {
		zval *p, *end;

		SERIALIZE_PTR(ce->default_properties_table);
		p = ce->default_properties_table;
		UNSERIALIZE_PTR(p);
		end = p + ce->default_properties_count;
		while (p < end) {
			zend_file_cache_serialize_zval(p, script, info, buf);
			p++;
		}
	}
	if (ce->default_static_members_table) {
		zval *p, *end;

		SERIALIZE_PTR(ce->default_static_members_table);
		p = ce->default_static_members_table;
		UNSERIALIZE_PTR(p);
		end = p + ce->default_static_members_count;
		while (p < end) {
			zend_file_cache_serialize_zval(p, script, info, buf);
			p++;
		}
	}
	zend_file_cache_serialize_hash(&ce->constants_table, script, info, buf, zend_file_cache_serialize_class_constant);
	SERIALIZE_STR(ce->info.user.filename);
	SERIALIZE_STR(ce->info.user.doc_comment);
	zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info);

	if (ce->trait_aliases) {
		zend_trait_alias **p, *q;

		SERIALIZE_PTR(ce->trait_aliases);
		p = ce->trait_aliases;
		UNSERIALIZE_PTR(p);

		while (*p) {
			SERIALIZE_PTR(*p);
			q = *p;
			UNSERIALIZE_PTR(q);

			if (q->trait_method) {
				zend_trait_method_reference *m;

				SERIALIZE_PTR(q->trait_method);
				m = q->trait_method;
				UNSERIALIZE_PTR(m);

				if (m->method_name) {
					SERIALIZE_STR(m->method_name);
				}
				if (m->class_name) {
					SERIALIZE_STR(m->class_name);
				}
			}

			if (q->alias) {
				SERIALIZE_STR(q->alias);
			}
			p++;
		}
	}

	if (ce->trait_precedences) {
		zend_trait_precedence **p, *q;

		SERIALIZE_PTR(ce->trait_precedences);
		p = ce->trait_precedences;
		UNSERIALIZE_PTR(p);

		while (*p) {
			SERIALIZE_PTR(*p);
			q = *p;
			UNSERIALIZE_PTR(q);

			if (q->trait_method) {
				zend_trait_method_reference *m;

				SERIALIZE_PTR(q->trait_method);
				m = q->trait_method;
				UNSERIALIZE_PTR(m);

				if (m->method_name) {
					SERIALIZE_STR(m->method_name);
				}
				if (m->class_name) {
					SERIALIZE_STR(m->class_name);
				}
			}

			if (q->exclude_from_classes) {
				zend_string **s;

				SERIALIZE_PTR(q->exclude_from_classes);
				s = (zend_string**)q->exclude_from_classes;
				UNSERIALIZE_PTR(s);

				while (*s) {
					SERIALIZE_STR(*s);
					s++;
				}
			}
			p++;
		}
	}

	SERIALIZE_PTR(ce->parent);
	SERIALIZE_PTR(ce->constructor);
	SERIALIZE_PTR(ce->destructor);
	SERIALIZE_PTR(ce->clone);
	SERIALIZE_PTR(ce->__get);
	SERIALIZE_PTR(ce->__set);
	SERIALIZE_PTR(ce->__call);
	SERIALIZE_PTR(ce->serialize_func);
	SERIALIZE_PTR(ce->unserialize_func);
	SERIALIZE_PTR(ce->__isset);
	SERIALIZE_PTR(ce->__unset);
	SERIALIZE_PTR(ce->__tostring);
	SERIALIZE_PTR(ce->__callstatic);
	SERIALIZE_PTR(ce->__debugInfo);
}
示例#11
0
static void zend_file_cache_unserialize_class(zval                    *zv,
                                              zend_persistent_script  *script,
                                              void                    *buf)
{
	zend_class_entry *ce;

	UNSERIALIZE_PTR(Z_PTR_P(zv));
	ce = Z_PTR_P(zv);

	UNSERIALIZE_STR(ce->name);
	zend_file_cache_unserialize_hash(&ce->function_table,
			script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
	if (ce->default_properties_table) {
		zval *p, *end;

		UNSERIALIZE_PTR(ce->default_properties_table);
		p = ce->default_properties_table;
		end = p + ce->default_properties_count;
		while (p < end) {
			zend_file_cache_unserialize_zval(p, script, buf);
			p++;
		}
	}
	if (ce->default_static_members_table) {
		zval *p, *end;

		UNSERIALIZE_PTR(ce->default_static_members_table);
		p = ce->default_static_members_table;
		end = p + ce->default_static_members_count;
		while (p < end) {
			zend_file_cache_unserialize_zval(p, script, buf);
			p++;
		}
	}
	zend_file_cache_unserialize_hash(&ce->constants_table,
			script, buf, zend_file_cache_unserialize_class_constant, NULL);
	UNSERIALIZE_STR(ce->info.user.filename);
	UNSERIALIZE_STR(ce->info.user.doc_comment);
	zend_file_cache_unserialize_hash(&ce->properties_info,
			script, buf, zend_file_cache_unserialize_prop_info, ZVAL_PTR_DTOR);

	if (ce->trait_aliases) {
		zend_trait_alias **p, *q;

		UNSERIALIZE_PTR(ce->trait_aliases);
		p = ce->trait_aliases;

		while (*p) {
			UNSERIALIZE_PTR(*p);
			q = *p;

			if (q->trait_method) {
				zend_trait_method_reference *m;

				UNSERIALIZE_PTR(q->trait_method);
				m = q->trait_method;

				if (m->method_name) {
					UNSERIALIZE_STR(m->method_name);
				}
				if (m->class_name) {
					UNSERIALIZE_STR(m->class_name);
				}
			}

			if (q->alias) {
				UNSERIALIZE_STR(q->alias);
			}
			p++;
		}
	}

	if (ce->trait_precedences) {
		zend_trait_precedence **p, *q;

		UNSERIALIZE_PTR(ce->trait_precedences);
		p = ce->trait_precedences;

		while (*p) {
			UNSERIALIZE_PTR(*p);
			q = *p;

			if (q->trait_method) {
				zend_trait_method_reference *m;

				UNSERIALIZE_PTR(q->trait_method);
				m = q->trait_method;

				if (m->method_name) {
					UNSERIALIZE_STR(m->method_name);
				}
				if (m->class_name) {
					UNSERIALIZE_STR(m->class_name);
				}
			}

			if (q->exclude_from_classes) {
				zend_string **s;

				UNSERIALIZE_PTR(q->exclude_from_classes);
				s = (zend_string**)q->exclude_from_classes;

				while (*s) {
					UNSERIALIZE_STR(*s);
					s++;
				}
			}
			p++;
		}
	}

	UNSERIALIZE_PTR(ce->parent);
	UNSERIALIZE_PTR(ce->constructor);
	UNSERIALIZE_PTR(ce->destructor);
	UNSERIALIZE_PTR(ce->clone);
	UNSERIALIZE_PTR(ce->__get);
	UNSERIALIZE_PTR(ce->__set);
	UNSERIALIZE_PTR(ce->__call);
	UNSERIALIZE_PTR(ce->serialize_func);
	UNSERIALIZE_PTR(ce->unserialize_func);
	UNSERIALIZE_PTR(ce->__isset);
	UNSERIALIZE_PTR(ce->__unset);
	UNSERIALIZE_PTR(ce->__tostring);
	UNSERIALIZE_PTR(ce->__callstatic);
	UNSERIALIZE_PTR(ce->__debugInfo);

	if (UNEXPECTED((ce->ce_flags & ZEND_ACC_ANON_CLASS))) {
		ce->serialize = zend_class_serialize_deny;
		ce->unserialize = zend_class_unserialize_deny;
	}
}
示例#12
0
static void zend_file_cache_unserialize_op_array(zend_op_array           *op_array,
                                                 zend_persistent_script  *script,
                                                 void                    *buf)
{
	if (op_array->static_variables && !IS_UNSERIALIZED(op_array->static_variables)) {
		HashTable *ht;

		UNSERIALIZE_PTR(op_array->static_variables);
		ht = op_array->static_variables;
		zend_file_cache_unserialize_hash(ht,
				script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
	}

	if (op_array->refcount) {
		op_array->refcount = NULL;
		UNSERIALIZE_PTR(op_array->literals);
		UNSERIALIZE_PTR(op_array->opcodes);
		UNSERIALIZE_PTR(op_array->arg_info);
		UNSERIALIZE_PTR(op_array->vars);
		UNSERIALIZE_STR(op_array->function_name);
		UNSERIALIZE_STR(op_array->filename);
		UNSERIALIZE_PTR(op_array->live_range);
		UNSERIALIZE_PTR(op_array->scope);
		UNSERIALIZE_STR(op_array->doc_comment);
		UNSERIALIZE_PTR(op_array->try_catch_array);
		UNSERIALIZE_PTR(op_array->prototype);
		return;
	}

	if (op_array->literals && !IS_UNSERIALIZED(op_array->literals)) {
		zval *p, *end;

		UNSERIALIZE_PTR(op_array->literals);
		p = op_array->literals;
		end = p + op_array->last_literal;
		while (p < end) {
			zend_file_cache_unserialize_zval(p, script, buf);
			p++;
		}
	}

	if (!IS_UNSERIALIZED(op_array->opcodes)) {
		zend_op *opline, *end;

		UNSERIALIZE_PTR(op_array->opcodes);
		opline = op_array->opcodes;
		end = opline + op_array->last;
		while (opline < end) {
#if ZEND_USE_ABS_CONST_ADDR
			if (opline->op1_type == IS_CONST) {
				UNSERIALIZE_PTR(opline->op1.zv);
			}
			if (opline->op2_type == IS_CONST) {
				UNSERIALIZE_PTR(opline->op2.zv);
			}
#else
			if (opline->op1_type == IS_CONST) {
				ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op1);
			}
			if (opline->op2_type == IS_CONST) {
				ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op2);
			}
#endif
#if ZEND_USE_ABS_JMP_ADDR
			switch (opline->opcode) {
				case ZEND_JMP:
				case ZEND_FAST_CALL:
					UNSERIALIZE_PTR(opline->op1.jmp_addr);
					break;
				case ZEND_JMPZNZ:
					/* relative extended_value don't have to be changed */
					/* break omitted intentionally */
				case ZEND_JMPZ:
				case ZEND_JMPNZ:
				case ZEND_JMPZ_EX:
				case ZEND_JMPNZ_EX:
				case ZEND_JMP_SET:
				case ZEND_COALESCE:
				case ZEND_FE_RESET_R:
				case ZEND_FE_RESET_RW:
				case ZEND_ASSERT_CHECK:
					UNSERIALIZE_PTR(opline->op2.jmp_addr);
					break;
				case ZEND_DECLARE_ANON_CLASS:
				case ZEND_DECLARE_ANON_INHERITED_CLASS:
				case ZEND_FE_FETCH_R:
				case ZEND_FE_FETCH_RW:
				case ZEND_SWITCH_LONG:
				case ZEND_SWITCH_STRING:
					/* relative extended_value don't have to be changed */
					break;
			}
#endif
			zend_deserialize_opcode_handler(opline);
			opline++;
		}

		if (op_array->arg_info) {
			zend_arg_info *p, *end;
			UNSERIALIZE_PTR(op_array->arg_info);
			p = op_array->arg_info;
			end = p + op_array->num_args;
			if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
				p--;
			}
			if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
				end++;
			}
			while (p < end) {
				if (!IS_UNSERIALIZED(p->name)) {
					UNSERIALIZE_STR(p->name);
				}
				if (p->type & (Z_UL(1) << (sizeof(zend_type)*8-1))) { /* type is class */
					zend_bool allow_null = (p->type & (Z_UL(1) << (sizeof(zend_type)*8-2))) != 0; /* type allow null */
					zend_string *type_name = (zend_string*)(p->type & ~(((Z_UL(1) << (sizeof(zend_type)*8-1))) | ((Z_UL(1) << (sizeof(zend_type)*8-2)))));

					UNSERIALIZE_STR(type_name);
					p->type = ZEND_TYPE_ENCODE_CLASS(type_name, allow_null);
				}
				p++;
			}
		}

		if (op_array->vars) {
			zend_string **p, **end;

			UNSERIALIZE_PTR(op_array->vars);
			p = op_array->vars;
			end = p + op_array->last_var;
			while (p < end) {
				if (!IS_UNSERIALIZED(*p)) {
					UNSERIALIZE_STR(*p);
				}
				p++;
			}
		}

		UNSERIALIZE_STR(op_array->function_name);
		UNSERIALIZE_STR(op_array->filename);
		UNSERIALIZE_PTR(op_array->live_range);
		UNSERIALIZE_PTR(op_array->scope);
		UNSERIALIZE_STR(op_array->doc_comment);
		UNSERIALIZE_PTR(op_array->try_catch_array);
		UNSERIALIZE_PTR(op_array->prototype);
	}
}
示例#13
0
static void zend_file_cache_serialize_op_array(zend_op_array            *op_array,
                                               zend_persistent_script   *script,
                                               zend_file_cache_metainfo *info,
                                               void                     *buf)
{
	if (op_array->static_variables && !IS_SERIALIZED(op_array->static_variables)) {
		HashTable *ht;

		SERIALIZE_PTR(op_array->static_variables);
		ht = op_array->static_variables;
		UNSERIALIZE_PTR(ht);
		zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
	}

	if (op_array->scope && !IS_SERIALIZED(op_array->opcodes)) {
		if (UNEXPECTED(zend_shared_alloc_get_xlat_entry(op_array->opcodes))) {
			op_array->refcount = (uint32_t*)(intptr_t)-1;
			SERIALIZE_PTR(op_array->literals);
			SERIALIZE_PTR(op_array->opcodes);
			SERIALIZE_PTR(op_array->arg_info);
			SERIALIZE_PTR(op_array->vars);
			SERIALIZE_STR(op_array->function_name);
			SERIALIZE_STR(op_array->filename);
			SERIALIZE_PTR(op_array->live_range);
			SERIALIZE_PTR(op_array->scope);
			SERIALIZE_STR(op_array->doc_comment);
			SERIALIZE_PTR(op_array->try_catch_array);
			SERIALIZE_PTR(op_array->prototype);
			return;
		}
		zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array->opcodes);
	}

	if (op_array->literals && !IS_SERIALIZED(op_array->literals)) {
		zval *p, *end;

		SERIALIZE_PTR(op_array->literals);
		p = op_array->literals;
		UNSERIALIZE_PTR(p);
		end = p + op_array->last_literal;
		while (p < end) {
			zend_file_cache_serialize_zval(p, script, info, buf);
			p++;
		}
	}

	if (!IS_SERIALIZED(op_array->opcodes)) {
		zend_op *opline, *end;

		SERIALIZE_PTR(op_array->opcodes);
		opline = op_array->opcodes;
		UNSERIALIZE_PTR(opline);
		end = opline + op_array->last;
		while (opline < end) {
#if ZEND_USE_ABS_CONST_ADDR
			if (opline->op1_type == IS_CONST) {
				SERIALIZE_PTR(opline->op1.zv);
			}
			if (opline->op2_type == IS_CONST) {
				SERIALIZE_PTR(opline->op2.zv);
			}
#else
			if (opline->op1_type == IS_CONST) {
				ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline, opline->op1);
			}
			if (opline->op2_type == IS_CONST) {
				ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline, opline->op2);
			}
#endif
#if ZEND_USE_ABS_JMP_ADDR
			switch (opline->opcode) {
				case ZEND_JMP:
				case ZEND_FAST_CALL:
					SERIALIZE_PTR(opline->op1.jmp_addr);
					break;
				case ZEND_JMPZNZ:
					/* relative extended_value don't have to be changed */
					/* break omitted intentionally */
				case ZEND_JMPZ:
				case ZEND_JMPNZ:
				case ZEND_JMPZ_EX:
				case ZEND_JMPNZ_EX:
				case ZEND_JMP_SET:
				case ZEND_COALESCE:
				case ZEND_FE_RESET_R:
				case ZEND_FE_RESET_RW:
				case ZEND_ASSERT_CHECK:
					SERIALIZE_PTR(opline->op2.jmp_addr);
					break;
				case ZEND_DECLARE_ANON_CLASS:
				case ZEND_DECLARE_ANON_INHERITED_CLASS:
				case ZEND_FE_FETCH_R:
				case ZEND_FE_FETCH_RW:
				case ZEND_SWITCH_LONG:
				case ZEND_SWITCH_STRING:
					/* relative extended_value don't have to be changed */
					break;
			}
#endif
			zend_serialize_opcode_handler(opline);
			opline++;
		}

		if (op_array->arg_info) {
			zend_arg_info *p, *end;
			SERIALIZE_PTR(op_array->arg_info);
			p = op_array->arg_info;
			UNSERIALIZE_PTR(p);
			end = p + op_array->num_args;
			if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
				p--;
			}
			if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
				end++;
			}
			while (p < end) {
				if (!IS_SERIALIZED(p->name)) {
					SERIALIZE_STR(p->name);
				}
				if (ZEND_TYPE_IS_CLASS(p->type)) {
					zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(p->type);
					zend_string *type_name = ZEND_TYPE_NAME(p->type);

					SERIALIZE_STR(type_name);
					p->type =
						(Z_UL(1) << (sizeof(zend_type)*8-1)) | /* type is class */
						(allow_null ? (Z_UL(1) << (sizeof(zend_type)*8-2)) : Z_UL(0)) | /* type allow null */
						(zend_type)type_name;
				}
				p++;
			}
		}

		if (op_array->vars) {
			zend_string **p, **end;

			SERIALIZE_PTR(op_array->vars);
			p = op_array->vars;
			UNSERIALIZE_PTR(p);
			end = p + op_array->last_var;
			while (p < end) {
				if (!IS_SERIALIZED(*p)) {
					SERIALIZE_STR(*p);
				}
				p++;
			}
		}

		SERIALIZE_STR(op_array->function_name);
		SERIALIZE_STR(op_array->filename);
		SERIALIZE_PTR(op_array->live_range);
		SERIALIZE_PTR(op_array->scope);
		SERIALIZE_STR(op_array->doc_comment);
		SERIALIZE_PTR(op_array->try_catch_array);
		SERIALIZE_PTR(op_array->prototype);
	}
}