Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #5
0
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;
		}
	}
}
Beispiel #6
0
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;
}
Beispiel #9
0
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));
	}
}
Beispiel #10
0
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));
		}
	}
}
Beispiel #11
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);
	}
}
Beispiel #12
0
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);
		}
	}
}