static void *zend_file_cache_serialize_interned(zend_string *str, zend_file_cache_metainfo *info) { size_t len; void *ret; /* check if the same interned string was already stored */ ret = zend_shared_alloc_get_xlat_entry(str); if (ret) { return ret; } len = ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); ret = (void*)(info->str_size | Z_UL(1)); zend_shared_alloc_register_xlat_entry(str, ret); if (info->str_size + len > ZSTR_LEN((zend_string*)ZCG(mem))) { size_t new_len = info->str_size + len; ZCG(mem) = (void*)zend_string_realloc( (zend_string*)ZCG(mem), ((_ZSTR_HEADER_SIZE + 1 + new_len + 4095) & ~0xfff) - (_ZSTR_HEADER_SIZE + 1), 0); } memcpy(ZSTR_VAL((zend_string*)ZCG(mem)) + info->str_size, str, len); info->str_size += len; return ret; }
static void zend_persist_op_array(zval *zv) { memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_op_array)); zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem)); Z_PTR_P(zv) = ZCG(arena_mem); ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_op_array))); zend_persist_op_array_ex(Z_PTR_P(zv), NULL); }
int zend_shared_memdup_size(void *source, size_t size) { void *old_p; if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), (zend_ulong)source)) != NULL) { /* we already duplicated this pointer */ return 0; } zend_shared_alloc_register_xlat_entry(source, source); return ZEND_ALIGNED_SIZE(size); }
int zend_shared_memdup_size(void *source, size_t size) { void **old_p; if (zend_hash_index_find(&xlat_table, (ulong)source, (void **)&old_p) == SUCCESS) { /* we already duplicated this pointer */ return 0; } zend_shared_alloc_register_xlat_entry(source, source); return ZEND_ALIGNED_SIZE(size); }
static void zend_persist_property_info(zval *zv) { zend_property_info *prop; memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_property_info)); zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem)); prop = Z_PTR_P(zv) = ZCG(arena_mem); ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_property_info))); zend_accel_store_interned_string(prop->name); if (prop->doc_comment) { if (ZCG(accel_directives).save_comments) { zend_accel_store_string(prop->doc_comment); } else { if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) { zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment); } zend_string_release(prop->doc_comment); prop->doc_comment = NULL; } } }
static void zend_persist_property_info_calc(zval *zv) { zend_property_info *prop = Z_PTR_P(zv); if (!zend_shared_alloc_get_xlat_entry(prop)) { zend_shared_alloc_register_xlat_entry(prop, prop); ADD_ARENA_SIZE(sizeof(zend_property_info)); ADD_INTERNED_STRING(prop->name, 0); if (ZCG(accel_directives).save_comments && prop->doc_comment) { ADD_STRING(prop->doc_comment); } } }
void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source) { void *old_p, *retval; if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), (zend_ulong)source)) != NULL) { /* we already duplicated this pointer */ return old_p; } retval = ZCG(mem); ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size)); memcpy(retval, source, size); zend_shared_alloc_register_xlat_entry(source, retval); if (free_source) { efree(source); } return retval; }
void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source TSRMLS_DC) { void **old_p, *retval; if (zend_hash_index_find(&xlat_table, (ulong)source, (void **)&old_p) == SUCCESS) { /* we already duplicated this pointer */ return *old_p; } retval = ZCG(mem);; ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size)); memcpy(retval, source, size); if (free_source) { interned_efree((char*)source); } zend_shared_alloc_register_xlat_entry(source, retval); return retval; }
static void zend_persist_op_array_calc(zval *zv) { zend_op_array *op_array = Z_PTR_P(zv); if (op_array->type == ZEND_USER_FUNCTION/* && (!op_array->refcount || *(op_array->refcount) > 1)*/) { zend_op_array *old_op_array = zend_shared_alloc_get_xlat_entry(op_array); if (old_op_array) { Z_PTR_P(zv) = old_op_array; } else { ADD_ARENA_SIZE(sizeof(zend_op_array)); zend_persist_op_array_calc_ex(Z_PTR_P(zv)); zend_shared_alloc_register_xlat_entry(op_array, Z_PTR_P(zv)); } } else { ADD_ARENA_SIZE(sizeof(zend_op_array)); zend_persist_op_array_calc_ex(Z_PTR_P(zv)); } }
static void zend_persist_class_entry(zval *zv) { zend_class_entry *ce = Z_PTR_P(zv); if (ce->type == ZEND_USER_CLASS) { memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_entry)); zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem)); ce = Z_PTR_P(zv) = ZCG(arena_mem); ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_entry))); zend_accel_store_interned_string(ce->name); zend_hash_persist(&ce->function_table, zend_persist_op_array); if (ce->default_properties_table) { int i; zend_accel_store(ce->default_properties_table, sizeof(zval) * ce->default_properties_count); for (i = 0; i < ce->default_properties_count; i++) { zend_persist_zval(&ce->default_properties_table[i]); } } if (ce->default_static_members_table) { int i; zend_accel_store(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count); for (i = 0; i < ce->default_static_members_count; i++) { zend_persist_zval(&ce->default_static_members_table[i]); } } ce->static_members_table = NULL; zend_hash_persist(&ce->constants_table, zend_persist_zval); if (ZEND_CE_FILENAME(ce)) { /* do not free! PHP has centralized filename storage, compiler will free it */ zend_accel_memdup_string(ZEND_CE_FILENAME(ce)); } if (ZEND_CE_DOC_COMMENT(ce)) { if (ZCG(accel_directives).save_comments) { zend_accel_store_string(ZEND_CE_DOC_COMMENT(ce)); } else { if (!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) { zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce)); zend_string_release(ZEND_CE_DOC_COMMENT(ce)); } ZEND_CE_DOC_COMMENT(ce) = NULL; } } zend_hash_persist(&ce->properties_info, zend_persist_property_info); if (ce->num_interfaces && ce->interfaces) { efree(ce->interfaces); } ce->interfaces = NULL; /* will be filled in on fetch */ if (ce->num_traits && ce->traits) { efree(ce->traits); } ce->traits = NULL; if (ce->trait_aliases) { int i = 0; while (ce->trait_aliases[i]) { if (ce->trait_aliases[i]->trait_method) { if (ce->trait_aliases[i]->trait_method->method_name) { zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->method_name); } if (ce->trait_aliases[i]->trait_method->class_name) { zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->class_name); } ce->trait_aliases[i]->trait_method->ce = NULL; zend_accel_store(ce->trait_aliases[i]->trait_method, sizeof(zend_trait_method_reference)); } if (ce->trait_aliases[i]->alias) { zend_accel_store_interned_string(ce->trait_aliases[i]->alias); } zend_accel_store(ce->trait_aliases[i], sizeof(zend_trait_alias)); i++; } zend_accel_store(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1)); } if (ce->trait_precedences) { int i = 0; while (ce->trait_precedences[i]) { zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->method_name); zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->class_name); ce->trait_precedences[i]->trait_method->ce = NULL; zend_accel_store(ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference)); if (ce->trait_precedences[i]->exclude_from_classes) { int j = 0; while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) { zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_from_classes[j].class_name); j++; } zend_accel_store(ce->trait_precedences[i]->exclude_from_classes, sizeof(zend_class_entry*) * (j + 1)); } zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence)); i++; } zend_accel_store( ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1)); } } }
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); } }
static void zend_persist_op_array_calc_ex(zend_op_array *op_array) { if (op_array->type != ZEND_USER_FUNCTION) { return; } if (op_array->static_variables) { if (!zend_shared_alloc_get_xlat_entry(op_array->static_variables)) { HashTable *old = op_array->static_variables; ADD_DUP_SIZE(op_array->static_variables, sizeof(HashTable)); zend_hash_persist_calc(op_array->static_variables, zend_persist_zval_calc); zend_shared_alloc_register_xlat_entry(old, op_array->static_variables); } } if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) { /* already stored */ if (op_array->function_name) { zend_string *new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name); if (IS_ACCEL_INTERNED(new_name)) { op_array->function_name = new_name; } } return; } if (op_array->literals) { zval *p = op_array->literals; zval *end = p + op_array->last_literal; ADD_DUP_SIZE(op_array->literals, sizeof(zval) * op_array->last_literal); while (p < end) { zend_persist_zval_calc(p); p++; } } ADD_DUP_SIZE(op_array->opcodes, sizeof(zend_op) * op_array->last); if (op_array->function_name) { zend_string *old_name = op_array->function_name; zend_string *new_name = zend_shared_alloc_get_xlat_entry(old_name); if (new_name) { op_array->function_name = new_name; } else { ADD_INTERNED_STRING(op_array->function_name, 0); zend_shared_alloc_register_xlat_entry(old_name, op_array->function_name); } } if (op_array->filename) { ADD_STRING(op_array->filename); } if (op_array->arg_info) { zend_arg_info *arg_info = op_array->arg_info; uint32_t num_args = op_array->num_args; uint32_t i; num_args = op_array->num_args; if (op_array->fn_flags & ZEND_ACC_VARIADIC) { num_args++; } if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { arg_info--; num_args++; } ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * num_args); ADD_DUP_SIZE(arg_info, sizeof(zend_arg_info) * num_args); for (i = 0; i < num_args; i++) { if (arg_info[i].name) { ADD_INTERNED_STRING(arg_info[i].name, 1); } if (arg_info[i].class_name) { ADD_INTERNED_STRING(arg_info[i].class_name, 1); } } } if (op_array->brk_cont_array) { ADD_DUP_SIZE(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont); } if (ZCG(accel_directives).save_comments && op_array->doc_comment) { ADD_STRING(op_array->doc_comment); } if (op_array->try_catch_array) { ADD_DUP_SIZE(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch); } if (op_array->vars) { int i; ADD_DUP_SIZE(op_array->vars, sizeof(zend_string*) * op_array->last_var); for (i = 0; i < op_array->last_var; i++) { ADD_INTERNED_STRING(op_array->vars[i], 0); } } }