static void zend_file_cache_serialize(zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf) { zend_persistent_script *new_script; memcpy(info->magic, "OPCACHE", 8); memcpy(info->system_id, ZCG(system_id), 32); info->mem_size = script->size; info->str_size = 0; info->script_offset = (char*)script - (char*)script->mem; info->timestamp = script->timestamp; memcpy(buf, script->mem, script->size); new_script = (zend_persistent_script*)((char*)buf + info->script_offset); SERIALIZE_STR(new_script->script.filename); zend_file_cache_serialize_hash(&new_script->script.class_table, script, info, buf, zend_file_cache_serialize_class); zend_file_cache_serialize_hash(&new_script->script.function_table, script, info, buf, zend_file_cache_serialize_func); zend_file_cache_serialize_op_array(&new_script->script.main_op_array, script, info, buf); SERIALIZE_PTR(new_script->arena_mem); new_script->mem = NULL; }
static zend_ast *zend_file_cache_serialize_ast(zend_ast *ast, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf) { uint32_t i; zend_ast *ret; SERIALIZE_PTR(ast); ret = ast; UNSERIALIZE_PTR(ast); if (ast->kind == ZEND_AST_ZVAL) { zend_file_cache_serialize_zval(&((zend_ast_zval*)ast)->val, script, info, 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_serialize_ast(list->child[i], script, info, 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_serialize_ast(ast->child[i], script, info, buf); } } } return ret; }
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++; } }
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; } }
static void zend_file_cache_serialize_class_constant(zval *zv, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf) { if (!IS_SERIALIZED(Z_PTR_P(zv))) { zend_class_constant *c; SERIALIZE_PTR(Z_PTR_P(zv)); c = Z_PTR_P(zv); UNSERIALIZE_PTR(c); zend_file_cache_serialize_zval(&c->value, script, info, buf); if (c->ce && !IS_SERIALIZED(c->ce)) { SERIALIZE_PTR(c->ce); } if (c->doc_comment && !IS_SERIALIZED(c->doc_comment)) { SERIALIZE_STR(c->doc_comment); } } }
static void zend_file_cache_serialize_func(zval *zv, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf) { zend_op_array *op_array; SERIALIZE_PTR(Z_PTR_P(zv)); op_array = Z_PTR_P(zv); UNSERIALIZE_PTR(op_array); zend_file_cache_serialize_op_array(op_array, script, info, buf); }
static void zend_file_cache_serialize_prop_info(zval *zv, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf) { if (!IS_SERIALIZED(Z_PTR_P(zv))) { zend_property_info *prop; SERIALIZE_PTR(Z_PTR_P(zv)); prop = Z_PTR_P(zv); UNSERIALIZE_PTR(prop); if (prop->ce && !IS_SERIALIZED(prop->ce)) { SERIALIZE_PTR(prop->ce); } if (prop->name && !IS_SERIALIZED(prop->name)) { SERIALIZE_STR(prop->name); } if (prop->doc_comment && !IS_SERIALIZED(prop->doc_comment)) { SERIALIZE_STR(prop->doc_comment); } } }
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); }
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->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); } #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: /* 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 (!IS_SERIALIZED(p->class_name)) { SERIALIZE_STR(p->class_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); } }
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); } }