Immutable clases and op_arrays

This commit is contained in:
Dmitry Stogov 2018-10-15 23:34:01 +03:00
parent 4f1274c59b
commit 94099586ec
36 changed files with 983 additions and 425 deletions

View File

@ -7,6 +7,7 @@ PHP 7.4 INTERNALS UPGRADE NOTES
d. Removed zend_check_private()
e. php_win32_error_to_msg() memory management
f. get_properties_for() handler / Z_OBJDEBUG_P
g. Immutable classes and op_arrays
2. Build system changes
a. Abstract
@ -98,6 +99,20 @@ PHP 7.4 INTERNALS UPGRADE NOTES
// ...
zend_release_properties(ht);
g. Opcache may make classes and op_arrays immutable. Such classes are marked
by ZEND_ACC_IMMUTABLE flag, they are not going to be copied from opcache
shard memory to process memory and must not be modified at all.
Few related data structures were changed to allow addressing mutable data
structures from immutable ones. This access is implemented through
ZEND_MAP_PTR... abstraction macros and, basically, uses additional level of
indirection. op_array->run_time_cache, op_array->static_variables_ptr,
class_entry->static_members_table and class_entry->iterator_funcs_ptr now
have to be access through ZEND_MAP_PTR... macros.
It's also not allowed to change op_array->reserved[] handles of immutable
op_arrays. Instead, now you have to reserve op_array handle using
zend_get_op_array_extension_handle() during MINIT and access its value
using ZEND_OP_ARRAY_EXTENSION(op_array, handle).
========================
2. Build system changes
========================

View File

@ -33,6 +33,8 @@
#include "zend_smart_string.h"
#include "zend_cpuinfo.h"
static size_t global_map_ptr_last = 0;
#ifdef ZTS
ZEND_API int compiler_globals_id;
ZEND_API int executor_globals_id;
@ -41,7 +43,6 @@ static HashTable *global_class_table = NULL;
static HashTable *global_constants_table = NULL;
static HashTable *global_auto_globals_table = NULL;
static HashTable *global_persistent_list = NULL;
static zend_uintptr_t global_last_static_member = 0;
ZEND_TSRMLS_CACHE_DEFINE()
# define GLOBAL_FUNCTION_TABLE global_function_table
# define GLOBAL_CLASS_TABLE global_class_table
@ -626,13 +627,22 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{
zend_hash_init_ex(compiler_globals->auto_globals, 8, NULL, auto_global_dtor, 1, 0);
zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, auto_global_copy_ctor);
compiler_globals->last_static_member = global_last_static_member;
if (compiler_globals->last_static_member) {
compiler_globals->static_members_table = calloc(compiler_globals->last_static_member + 1, sizeof(zval*));
} else {
compiler_globals->static_members_table = NULL;
}
compiler_globals->script_encoding_list = NULL;
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
/* Map region is going to be created and resized at run-time. */
compiler_globals->map_ptr_base = NULL;
compiler_globals->map_ptr_size = 0;
compiler_globals->map_ptr_last = global_map_ptr_last;
if (compiler_globals->map_ptr_last) {
/* Allocate map_ptr table */
compiler_globals->map_ptr_size = ZEND_MM_ALIGNED_SIZE_EX(compiler_globals->map_ptr_last, 4096);
compiler_globals->map_ptr_base = pemalloc(compiler_globals->map_ptr_size * sizeof(void*), 1);
memset(compiler_globals->map_ptr_base, 0, compiler_globals->map_ptr_last * sizeof(void*));
}
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
}
/* }}} */
@ -650,13 +660,14 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{
zend_hash_destroy(compiler_globals->auto_globals);
free(compiler_globals->auto_globals);
}
if (compiler_globals->static_members_table) {
free(compiler_globals->static_members_table);
}
if (compiler_globals->script_encoding_list) {
pefree((char*)compiler_globals->script_encoding_list, 1);
}
compiler_globals->last_static_member = 0;
if (compiler_globals->map_ptr_base) {
free(compiler_globals->map_ptr_base);
compiler_globals->map_ptr_base = NULL;
compiler_globals->map_ptr_size = 0;
}
}
/* }}} */
@ -879,6 +890,22 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
#ifdef ZEND_WIN32
zend_get_windows_version_info(&EG(windows_version_info));
#endif
# if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
/* Create a map region, used for indirect pointers from shared to
* process memory. It's allocatred once and never resized.
* All processes must map it into the same address space.
*/
CG(map_ptr_size) = 1024 * 1024; // TODO: initial size ???
CG(map_ptr_last) = 0;
CG(map_ptr_base) = pemalloc(CG(map_ptr_size) * sizeof(void*), 1);
# elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
/* Map region is going to be created and resized at run-time. */
CG(map_ptr_base) = NULL;
CG(map_ptr_size) = 0;
CG(map_ptr_last) = 0;
# else
# error "Unknown ZEND_MAP_PTR_KIND"
# endif
#endif
EG(error_reporting) = E_ALL & ~E_NOTICE;
@ -931,7 +958,7 @@ int zend_post_startup(void) /* {{{ */
*GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table;
*GLOBAL_CLASS_TABLE = *compiler_globals->class_table;
*GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants;
global_last_static_member = compiler_globals->last_static_member;
global_map_ptr_last = compiler_globals->map_ptr_last;
short_tags_default = CG(short_tags);
compiler_options_default = CG(compiler_options);
@ -950,6 +977,8 @@ int zend_post_startup(void) /* {{{ */
executor_globals_ctor(executor_globals);
global_persistent_list = &EG(persistent_list);
zend_copy_ini_directives();
#else
global_map_ptr_last = CG(map_ptr_last);
#endif
if (zend_post_startup_cb) {
@ -996,6 +1025,12 @@ void zend_shutdown(void) /* {{{ */
GLOBAL_CLASS_TABLE = NULL;
GLOBAL_AUTO_GLOBALS_TABLE = NULL;
GLOBAL_CONSTANTS_TABLE = NULL;
#else
if (CG(map_ptr_base)) {
free(CG(map_ptr_base));
CG(map_ptr_base) = NULL;
CG(map_ptr_size) = 0;
}
#endif
zend_destroy_rsrc_list_dtors();
}
@ -1077,17 +1112,12 @@ ZEND_API void zend_activate(void) /* {{{ */
init_compiler();
init_executor();
startup_scanner();
if (CG(map_ptr_last)) {
memset(CG(map_ptr_base), 0, CG(map_ptr_last) * sizeof(void*));
}
}
/* }}} */
#ifdef ZTS
void zend_reset_internal_classes(void) /* {{{ */
{
CG(last_static_member) = global_last_static_member;
}
/* }}} */
#endif
void zend_call_destructors(void) /* {{{ */
{
zend_try {
@ -1619,6 +1649,62 @@ void free_estring(char **str_p) /* {{{ */
}
/* }}} */
ZEND_API void zend_map_ptr_reset(void)
{
CG(map_ptr_last) = global_map_ptr_last;
}
ZEND_API void *zend_map_ptr_new(void)
{
void **ptr;
if (CG(map_ptr_last) >= CG(map_ptr_size)) {
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
// TODO: error ???
ZEND_ASSERT(0);
#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
/* Grow map_ptr table */
CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(CG(map_ptr_last) + 1, 4096);
CG(map_ptr_base) = perealloc(CG(map_ptr_base), CG(map_ptr_size) * sizeof(void*), 1);
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
}
ptr = (void**)CG(map_ptr_base) + CG(map_ptr_last);
*ptr = NULL;
CG(map_ptr_last)++;
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
return ptr;
#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
return (void*)((CG(map_ptr_last) * sizeof(void*)) - (sizeof(void*) - 1));
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
}
ZEND_API void zend_map_ptr_extend(size_t last)
{
if (last > CG(map_ptr_last)) {
void **ptr;
if (last >= CG(map_ptr_size)) {
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
/* This may never happen */
ZEND_ASSERT(0);
#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
/* Grow map_ptr table */
CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(last, 4096);
CG(map_ptr_base) = perealloc(CG(map_ptr_base), CG(map_ptr_size) * sizeof(void*), 1);
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
}
ptr = (void**)CG(map_ptr_base) + CG(map_ptr_last);
memset(ptr, 0, (last - CG(map_ptr_last)) * sizeof(void*));
CG(map_ptr_last) = last;
}
}
/*
* Local variables:
* tab-width: 4

View File

@ -25,6 +25,7 @@
#define ZEND_ENGINE_3
#include "zend_types.h"
#include "zend_map_ptr.h"
#include "zend_errors.h"
#include "zend_alloc.h"
#include "zend_llist.h"
@ -127,10 +128,7 @@ struct _zend_class_entry {
int default_static_members_count;
zval *default_properties_table;
zval *default_static_members_table;
union {
zval *static_members_table;
zend_uintptr_t static_members_table_idx;
};
ZEND_MAP_PTR_DEF(zval *, static_members_table);
HashTable function_table;
HashTable properties_info;
HashTable constants_table;
@ -150,7 +148,7 @@ struct _zend_class_entry {
zend_function *unserialize_func;
/* allocated only if class implements Iterator or IteratorAggregate interface */
zend_class_iterator_funcs *iterator_funcs_ptr;
ZEND_MAP_PTR_DEF(zend_class_iterator_funcs *, iterator_funcs_ptr);
/* handlers */
union {
@ -271,9 +269,8 @@ ZEND_API void zend_activate_modules(void);
ZEND_API void zend_deactivate_modules(void);
ZEND_API void zend_post_deactivate_modules(void);
void zend_reset_internal_classes(void);
ZEND_API void free_estring(char **str_p);
END_EXTERN_C()
/* output support */

View File

@ -2795,7 +2795,9 @@ ZEND_API int zend_register_class_alias_ex(const char *name, size_t name_len, zen
ce = zend_hash_add_ptr(CG(class_table), lcname, ce);
zend_string_release_ex(lcname, 0);
if (ce) {
ce->refcount++;
if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
ce->refcount++;
}
return SUCCESS;
}
return FAILURE;
@ -3696,18 +3698,14 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
}
ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property);
if (ce->type == ZEND_USER_CLASS) {
ce->static_members_table = ce->default_static_members_table;
#ifdef ZTS
} else if (!ce->static_members_table_idx) {
CG(last_static_member)++;
ce->static_members_table_idx = CG(last_static_member);
if (CG(static_members_table)) {
/* Support for run-time declaration: dl() */
CG(static_members_table) = realloc(CG(static_members_table), (CG(last_static_member) + 1) * sizeof(zval*));
CG(static_members_table)[ce->static_members_table_idx] = NULL;
if (!ZEND_MAP_PTR(ce->static_members_table)) {
ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS);
if (!EG(current_execute_data)) {
ZEND_MAP_PTR_NEW(ce->static_members_table);
} else {
/* internal class loaded by dl() */
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
}
#endif
}
} else {
if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&

View File

@ -219,7 +219,7 @@ typedef struct _zend_fcall_info_cache {
class_container.trait_precedences = NULL; \
class_container.interfaces = NULL; \
class_container.get_iterator = NULL; \
class_container.iterator_funcs_ptr = NULL; \
ZEND_MAP_PTR_INIT(class_container.iterator_funcs_ptr, NULL); \
class_container.info.internal.module = NULL; \
class_container.info.internal.builtin_functions = functions; \
}
@ -228,11 +228,8 @@ typedef struct _zend_fcall_info_cache {
#define INIT_NS_CLASS_ENTRY(class_container, ns, class_name, functions) \
INIT_CLASS_ENTRY(class_container, ZEND_NS_NAME(ns, class_name), functions)
#ifdef ZTS
# define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members_table:CG(static_members_table)[(ce)->static_members_table_idx])
#else
# define CE_STATIC_MEMBERS(ce) ((ce)->static_members_table)
#endif
#define CE_STATIC_MEMBERS(ce) \
((zval*)ZEND_MAP_PTR_GET((ce)->static_members_table))
#define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0)

View File

@ -1770,7 +1770,7 @@ static int copy_class_or_interface_name(zval *el, int num_args, va_list args, ze
if ((hash_key->key && ZSTR_VAL(hash_key->key)[0] != 0)
&& (comply_mask == (ce->ce_flags & mask))) {
if (ce->refcount > 1 &&
if ((ce->refcount > 1 || (ce->ce_flags & ZEND_ACC_IMMUTABLE)) &&
!same_name(hash_key->key, ce->name)) {
add_next_index_str(array, zend_string_copy(hash_key->key));
} else {

View File

@ -151,9 +151,14 @@ ZEND_METHOD(Closure, call)
if (ZEND_USER_CODE(my_function.type)
&& (closure->func.common.scope != Z_OBJCE_P(newthis)
|| (closure->func.common.fn_flags & ZEND_ACC_HEAP_RT_CACHE))) {
my_function.op_array.run_time_cache = emalloc(my_function.op_array.cache_size);
void *ptr;
my_function.op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE;
memset(my_function.op_array.run_time_cache, 0, my_function.op_array.cache_size);
ptr = emalloc(sizeof(void*) + my_function.op_array.cache_size);
ZEND_MAP_PTR_INIT(my_function.op_array.run_time_cache, ptr);
ptr = (char*)ptr + sizeof(void*);
ZEND_MAP_PTR_SET(my_function.op_array.run_time_cache, ptr);
memset(ptr, 0, my_function.op_array.cache_size);
}
}
@ -176,7 +181,7 @@ ZEND_METHOD(Closure, call)
/* copied upon generator creation */
GC_DELREF(&closure->std);
} else if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_HEAP_RT_CACHE) {
efree(my_function.op_array.run_time_cache);
efree(ZEND_MAP_PTR(my_function.op_array.run_time_cache));
}
}
/* }}} */
@ -501,7 +506,8 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{
debug_info = zend_new_array(8);
if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) {
HashTable *static_variables = closure->func.op_array.static_variables;
HashTable *static_variables =
ZEND_MAP_PTR_GET(closure->func.op_array.static_variables_ptr);
ZVAL_ARR(&val, zend_array_dup(static_variables));
zend_hash_update(debug_info, ZSTR_KNOWN(ZEND_STR_STATIC), &val);
}
@ -559,7 +565,7 @@ static HashTable *zend_closure_get_gc(zval *obj, zval **table, int *n) /* {{{ */
*table = Z_TYPE(closure->this_ptr) != IS_NULL ? &closure->this_ptr : NULL;
*n = Z_TYPE(closure->this_ptr) != IS_NULL ? 1 : 0;
return (closure->func.type == ZEND_USER_FUNCTION) ?
closure->func.op_array.static_variables : NULL;
ZEND_MAP_PTR_GET(closure->func.op_array.static_variables_ptr) : NULL;
}
/* }}} */
@ -654,28 +660,44 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
if (func->type == ZEND_USER_FUNCTION) {
memcpy(&closure->func, func, sizeof(zend_op_array));
closure->func.common.fn_flags |= ZEND_ACC_CLOSURE;
closure->func.common.fn_flags &= ~ZEND_ACC_IMMUTABLE;
if (closure->func.op_array.static_variables) {
closure->func.op_array.static_variables =
zend_array_dup(closure->func.op_array.static_variables);
}
ZEND_MAP_PTR_INIT(closure->func.op_array.static_variables_ptr,
&closure->func.op_array.static_variables);
/* Runtime cache is scope-dependent, so we cannot reuse it if the scope changed */
if (!closure->func.op_array.run_time_cache
if (!ZEND_MAP_PTR_GET(closure->func.op_array.run_time_cache)
|| func->common.scope != scope
|| (func->common.fn_flags & ZEND_ACC_HEAP_RT_CACHE)
) {
if (!func->op_array.run_time_cache && (func->common.fn_flags & ZEND_ACC_CLOSURE)) {
void *ptr;
if (!ZEND_MAP_PTR_GET(func->op_array.run_time_cache)
&& (func->common.fn_flags & ZEND_ACC_CLOSURE)
&& (func->common.scope == scope ||
!(func->common.fn_flags & ZEND_ACC_IMMUTABLE))) {
/* If a real closure is used for the first time, we create a shared runtime cache
* and remember which scope it is for. */
func->common.scope = scope;
func->op_array.run_time_cache = zend_arena_alloc(&CG(arena), func->op_array.cache_size);
closure->func.op_array.run_time_cache = func->op_array.run_time_cache;
if (func->common.scope != scope) {
func->common.scope = scope;
}
closure->func.op_array.fn_flags &= ~ZEND_ACC_HEAP_RT_CACHE;
ptr = zend_arena_alloc(&CG(arena), func->op_array.cache_size);
ZEND_MAP_PTR_SET(func->op_array.run_time_cache, ptr);
ZEND_MAP_PTR_SET(closure->func.op_array.run_time_cache, ptr);
} else {
/* Otherwise, we use a non-shared runtime cache */
closure->func.op_array.run_time_cache = emalloc(func->op_array.cache_size);
closure->func.op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE;
ptr = emalloc(sizeof(void*) + func->op_array.cache_size);
ZEND_MAP_PTR_INIT(closure->func.op_array.run_time_cache, ptr);
ptr = (char*)ptr + sizeof(void*);
ZEND_MAP_PTR_SET(closure->func.op_array.run_time_cache, ptr);
}
memset(closure->func.op_array.run_time_cache, 0, func->op_array.cache_size);
memset(ptr, 0, func->op_array.cache_size);
}
if (closure->func.op_array.refcount) {
(*closure->func.op_array.refcount)++;
@ -728,7 +750,7 @@ ZEND_API void zend_create_fake_closure(zval *res, zend_function *func, zend_clas
void zend_closure_bind_var(zval *closure_zv, zend_string *var_name, zval *var) /* {{{ */
{
zend_closure *closure = (zend_closure *) Z_OBJ_P(closure_zv);
HashTable *static_variables = closure->func.op_array.static_variables;
HashTable *static_variables = ZEND_MAP_PTR_GET(closure->func.op_array.static_variables_ptr);
zend_hash_update(static_variables, var_name, var);
}
/* }}} */
@ -736,7 +758,7 @@ void zend_closure_bind_var(zval *closure_zv, zend_string *var_name, zval *var) /
void zend_closure_bind_var_ex(zval *closure_zv, uint32_t offset, zval *val) /* {{{ */
{
zend_closure *closure = (zend_closure *) Z_OBJ_P(closure_zv);
HashTable *static_variables = closure->func.op_array.static_variables;
HashTable *static_variables = ZEND_MAP_PTR_GET(closure->func.op_array.static_variables_ptr);
zval *var = (zval*)((char*)static_variables->arData + offset);
zval_ptr_dtor(var);
ZVAL_COPY_VALUE(var, val);

View File

@ -1021,7 +1021,9 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
GC_ADDREF(op_array->static_variables);
}
}
op_array->run_time_cache = NULL;
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
} else if (function->type == ZEND_INTERNAL_FUNCTION) {
if (function->common.function_name) {
zend_string_addref(function->common.function_name);
@ -1614,9 +1616,9 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
if (ce->type == ZEND_INTERNAL_CLASS) {
ce->static_members_table = NULL;
ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
} else {
ce->static_members_table = ce->default_static_members_table;
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
ce->info.user.doc_comment = NULL;
}
@ -1636,7 +1638,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
ce->__tostring = NULL;
ce->create_object = NULL;
ce->get_iterator = NULL;
ce->iterator_funcs_ptr = NULL;
ZEND_MAP_PTR_INIT(ce->iterator_funcs_ptr, NULL);
ce->get_static_method = NULL;
ce->parent = NULL;
ce->parent_name = NULL;
@ -5867,6 +5869,9 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
op_array->fn_flags |= (orig_op_array->fn_flags & ZEND_ACC_STRICT_TYPES);
op_array->fn_flags |= decl->flags;
op_array->line_start = decl->start_lineno;

View File

@ -389,7 +389,8 @@ struct _zend_op_array {
uint32_t last; /* number of opcodes */
zend_op *opcodes;
void **run_time_cache;
ZEND_MAP_PTR_DEF(void **, run_time_cache);
ZEND_MAP_PTR_DEF(HashTable *, static_variables_ptr);
HashTable *static_variables;
zend_string **vars; /* names of CV variables */
@ -660,19 +661,25 @@ struct _zend_execute_data {
(node).constant = RT_CONSTANT(opline, node) - (op_array)->literals; \
} while (0)
#define RUN_TIME_CACHE(op_array) \
ZEND_MAP_PTR_GET((op_array)->run_time_cache)
#define ZEND_OP_ARRAY_EXTENSION(op_array, handle) \
RUN_TIME_CACHE(op_array)[handle]
#if ZEND_EX_USE_RUN_TIME_CACHE
# define EX_RUN_TIME_CACHE() \
EX(run_time_cache)
# define EX_LOAD_RUN_TIME_CACHE(op_array) do { \
EX(run_time_cache) = (op_array)->run_time_cache; \
EX(run_time_cache) = RUN_TIME_CACHE(op_array); \
} while (0)
#else
# define EX_RUN_TIME_CACHE() \
EX(func)->op_array.run_time_cache
RUN_TIME_CACHE(&EX(func)->op_array)
# define EX_LOAD_RUN_TIME_CACHE(op_array) do { \
} while (0)

View File

@ -2504,39 +2504,20 @@ static zend_always_inline void i_init_func_execute_data(zend_op_array *op_array,
}
/* }}} */
static zend_always_inline void init_func_run_time_cache_i(zend_op_array *op_array) /* {{{ */
{
void **run_time_cache;
ZEND_ASSERT(RUN_TIME_CACHE(op_array) == NULL);
run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
memset(run_time_cache, 0, op_array->cache_size);
ZEND_MAP_PTR_SET(op_array->run_time_cache, run_time_cache);
}
/* }}} */
static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_array *op_array) /* {{{ */
{
ZEND_ASSERT(op_array->run_time_cache == NULL);
op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
memset(op_array->run_time_cache, 0, op_array->cache_size);
}
/* }}} */
static zend_always_inline zend_function* ZEND_FASTCALL init_func_run_time_cache_i(zval *zv) /* {{{ */
{
zend_op_array *op_array = Z_PTR_P(zv);
ZEND_ASSERT(op_array->run_time_cache == NULL);
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
zend_op_array *new_op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array) + op_array->cache_size);
Z_PTR_P(zv) = new_op_array;
memcpy(new_op_array, op_array, sizeof(zend_op_array));
new_op_array->fn_flags &= ~ZEND_ACC_IMMUTABLE;
new_op_array->run_time_cache = (void**)(new_op_array + 1);
memset(new_op_array->run_time_cache, 0, new_op_array->cache_size);
return (zend_function*)new_op_array;
} else {
op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
memset(op_array->run_time_cache, 0, op_array->cache_size);
return (zend_function*)op_array;
}
}
/* }}} */
static zend_never_inline zend_function* init_func_run_time_cache_ex(zval *zv) /* {{{ */
{
return init_func_run_time_cache_i(zv);
init_func_run_time_cache_i(op_array);
}
/* }}} */
@ -2547,8 +2528,8 @@ ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /*
if (EXPECTED(zv != NULL)) {
zend_function *fbc = Z_FUNC_P(zv);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
fbc = (zend_function*)init_func_run_time_cache_i(zv);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache_i(&fbc->op_array);
}
return fbc;
}
@ -2562,8 +2543,8 @@ ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name,
if (EXPECTED(zv != NULL)) {
zend_function *fbc = Z_FUNC_P(zv);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
fbc = (zend_function*)init_func_run_time_cache_i(zv);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache_i(&fbc->op_array);
}
return fbc;
}
@ -2580,10 +2561,15 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
zend_attach_symbol_table(execute_data);
if (!op_array->run_time_cache) {
if (!ZEND_MAP_PTR(op_array->run_time_cache)) {
void *ptr;
ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE);
op_array->run_time_cache = emalloc(op_array->cache_size);
memset(op_array->run_time_cache, 0, op_array->cache_size);
ptr = emalloc(op_array->cache_size + sizeof(void*));
ZEND_MAP_PTR_INIT(op_array->run_time_cache, ptr);
ptr = (char*)ptr + sizeof(void*);
ZEND_MAP_PTR_SET(op_array->run_time_cache, ptr);
memset(ptr, 0, op_array->cache_size);
}
EX_LOAD_RUN_TIME_CACHE(op_array);
@ -2602,7 +2588,7 @@ ZEND_API void zend_init_func_execute_data(zend_execute_data *ex, zend_op_array *
#endif
EX(prev_execute_data) = EG(current_execute_data);
if (!op_array->run_time_cache) {
if (!RUN_TIME_CACHE(op_array)) {
init_func_run_time_cache(op_array);
}
i_init_func_execute_data(op_array, return_value, 1 EXECUTE_DATA_CC);
@ -2618,10 +2604,15 @@ ZEND_API void zend_init_func_execute_data(zend_execute_data *ex, zend_op_array *
ZEND_API void zend_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
{
EX(prev_execute_data) = EG(current_execute_data);
if (!op_array->run_time_cache) {
if (!ZEND_MAP_PTR(op_array->run_time_cache)) {
void *ptr;
ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE);
op_array->run_time_cache = emalloc(op_array->cache_size);
memset(op_array->run_time_cache, 0, op_array->cache_size);
ptr = emalloc(op_array->cache_size + sizeof(void*));
ZEND_MAP_PTR_INIT(op_array->run_time_cache, ptr);
ptr = (char*)ptr + sizeof(void*);
ZEND_MAP_PTR_SET(op_array->run_time_cache, ptr);
memset(ptr, 0, op_array->cache_size);
}
i_init_code_execute_data(execute_data, op_array, return_value);
}
@ -2964,7 +2955,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s
return NULL;
}
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
} else {
@ -2982,8 +2973,8 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s
zend_string_release_ex(lcname, 0);
fbc = Z_FUNC_P(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
fbc = init_func_run_time_cache_ex(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
called_scope = NULL;
}
@ -3019,7 +3010,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval *
return NULL;
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
@ -3106,7 +3097,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar
return NULL;
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}

View File

@ -318,9 +318,6 @@ void shutdown_executor(void) /* {{{ */
zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant_full);
zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function_full);
zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class_full);
#ifdef ZTS
zend_reset_internal_classes();
#endif
} else {
ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) {
zend_constant *c = Z_PTR_P(zv);
@ -334,6 +331,7 @@ void shutdown_executor(void) /* {{{ */
efree(c);
zend_string_release_ex(key, 0);
} ZEND_HASH_FOREACH_END_DEL();
ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(function_table), key, zv) {
zend_function *func = Z_PTR_P(zv);
if (_idx == EG(persistent_functions_count)) {

View File

@ -21,6 +21,7 @@
ZEND_API zend_llist zend_extensions;
ZEND_API uint32_t zend_extension_flags = 0;
ZEND_API int zend_op_array_extension_handles = 0;
static int last_resource_number;
int zend_load_extension(const char *path)
@ -198,6 +199,7 @@ int zend_startup_extensions_mechanism()
{
/* Startup extensions mechanism */
zend_llist_init(&zend_extensions, sizeof(zend_extension), (void (*)(void *)) zend_extension_dtor, 1);
zend_op_array_extension_handles = 0;
last_resource_number = 0;
return SUCCESS;
}
@ -257,6 +259,10 @@ ZEND_API int zend_get_resource_handle(zend_extension *extension)
}
}
ZEND_API int zend_get_op_array_extension_handle(void)
{
return zend_op_array_extension_handles++;
}
ZEND_API zend_extension *zend_get_extension(const char *extension_name)
{

View File

@ -111,7 +111,10 @@ struct _zend_extension {
};
BEGIN_EXTERN_C()
extern ZEND_API int zend_op_array_extension_handles;
ZEND_API int zend_get_resource_handle(zend_extension *extension);
ZEND_API int zend_get_op_array_extension_handle(void);
ZEND_API void zend_extension_dispatch_message(int message, void *arg);
END_EXTERN_C()

View File

@ -117,10 +117,9 @@ struct _zend_compiler_globals {
zend_stack delayed_oplines_stack;
#ifdef ZTS
zval **static_members_table;
zend_uintptr_t last_static_member;
#endif
void *map_ptr_base;
size_t map_ptr_size;
size_t map_ptr_last;
};

View File

@ -64,11 +64,16 @@ static zend_function *zend_duplicate_function(zend_function *func, zend_class_en
/* reuse the same op_array structure */
return func;
}
if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
GC_ADDREF(func->op_array.static_variables);
}
new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
memcpy(new_function, func, sizeof(zend_op_array));
if (ZEND_MAP_PTR_GET(func->op_array.static_variables_ptr)) {
/* See: Zend/tests/method_static_var.phpt */
new_function->op_array.static_variables = ZEND_MAP_PTR_GET(func->op_array.static_variables_ptr);
}
if (!(GC_FLAGS(new_function->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
GC_ADDREF(new_function->op_array.static_variables);
}
ZEND_MAP_PTR_INIT(new_function->op_array.static_variables_ptr, &new_function->op_array.static_variables);
}
return new_function;
}
@ -87,23 +92,9 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
if (EXPECTED(!ce->get_iterator)) {
ce->get_iterator = parent->get_iterator;
}
if (EXPECTED(!ce->iterator_funcs_ptr) && UNEXPECTED(parent->iterator_funcs_ptr)) {
if (ce->type == ZEND_INTERNAL_CLASS) {
ce->iterator_funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs));
if (parent->iterator_funcs_ptr->zf_new_iterator) {
ce->iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&ce->function_table, "getiterator", sizeof("getiterator") - 1);
}
if (parent->iterator_funcs_ptr->zf_current) {
ce->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&ce->function_table, "rewind", sizeof("rewind") - 1);
ce->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&ce->function_table, "valid", sizeof("valid") - 1);
ce->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&ce->function_table, "key", sizeof("key") - 1);
ce->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&ce->function_table, "current", sizeof("current") - 1);
ce->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&ce->function_table, "next", sizeof("next") - 1);
}
} else {
ce->iterator_funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs));
memset(ce->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
}
if (ZEND_MAP_PTR(parent->iterator_funcs_ptr)) {
/* Must be initialized through iface->interface_gets_implemented() */
ZEND_ASSERT(ZEND_MAP_PTR(ce->iterator_funcs_ptr) && ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr));
}
if (EXPECTED(!ce->__get)) {
ce->__get = parent->__get;
@ -910,7 +901,11 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
}
} while (dst != end);
} else if (ce->type == ZEND_USER_CLASS) {
src = parent_ce->default_static_members_table + parent_ce->default_static_members_count;
if (UNEXPECTED(CE_STATIC_MEMBERS(parent_ce) == NULL)) {
ZEND_ASSERT(parent_ce->type == ZEND_INTERNAL_CLASS || (parent_ce->ce_flags & ZEND_ACC_IMMUTABLE));
zend_class_init_statics(parent_ce);
}
src = CE_STATIC_MEMBERS(parent_ce) + parent_ce->default_static_members_count;
do {
dst--;
src--;
@ -936,18 +931,14 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
} while (dst != end);
}
ce->default_static_members_count += parent_ce->default_static_members_count;
if (ce->type == ZEND_USER_CLASS) {
ce->static_members_table = ce->default_static_members_table;
#ifdef ZTS
} else if (!ce->static_members_table_idx) {
CG(last_static_member)++;
ce->static_members_table_idx = CG(last_static_member);
if (CG(static_members_table)) {
/* Support for run-time declaration: dl() */
CG(static_members_table) = realloc(CG(static_members_table), (CG(last_static_member) + 1) * sizeof(zval*));
CG(static_members_table)[ce->static_members_table_idx] = NULL;
if (!ZEND_MAP_PTR(ce->static_members_table)) {
ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS);
if (!EG(current_execute_data)) {
ZEND_MAP_PTR_NEW(ce->static_members_table);
} else {
/* internal class loaded by dl() */
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
}
#endif
}
}
@ -1315,6 +1306,10 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s
} else {
new_fn = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
memcpy(new_fn, fn, sizeof(zend_op_array));
new_fn->op_array.fn_flags &= ~ZEND_ACC_IMMUTABLE;
ZEND_MAP_PTR_INIT(new_fn->op_array.run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
ZEND_MAP_PTR_SET(new_fn->op_array.run_time_cache, NULL);
ZEND_MAP_PTR_INIT(new_fn->op_array.static_variables_ptr, &new_fn->op_array.static_variables);
}
fn = zend_hash_update_ptr(&ce->function_table, key, new_fn);
zend_add_magic_methods(ce, key, fn);

View File

@ -119,12 +119,36 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun
}
/* }}} */
typedef struct _zend_class_iterator_funcs_ptr {
zend_class_iterator_funcs *ptr;
zend_class_iterator_funcs data;
} zend_class_iterator_funcs_ptr;
/* iterator interface, c-level functions used by engine */
static zend_never_inline zend_class_iterator_funcs* zend_alloc_iterator_funcs_ptr(zend_class_entry *ce) /* {{{ */
{
zend_class_iterator_funcs *ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs));
memset(ptr, 0, sizeof(zend_class_iterator_funcs));
ZEND_MAP_PTR_SET(ce->iterator_funcs_ptr, ptr);
return ptr;
}
/* }}} */
static zend_always_inline zend_class_iterator_funcs* zend_get_iterator_funcs_ptr(zend_class_entry *ce) /* {{{ */
{
if (ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr)) {
return ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr);
} else {
return zend_alloc_iterator_funcs_ptr(ce);
}
}
/* }}} */
/* {{{ zend_user_it_new_iterator */
ZEND_API void zend_user_it_new_iterator(zend_class_entry *ce, zval *object, zval *retval)
{
zend_call_method_with_0_params(object, ce, &ce->iterator_funcs_ptr->zf_new_iterator, "getiterator", retval);
zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce);
zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_new_iterator, "getiterator", retval);
}
/* }}} */
@ -159,8 +183,10 @@ ZEND_API int zend_user_it_valid(zend_object_iterator *_iter)
zval *object = &iter->it.data;
zval more;
int result;
zend_class_entry *ce = iter->ce;
zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce);
zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_valid, "valid", &more);
zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_valid, "valid", &more);
result = i_zend_is_true(&more);
zval_ptr_dtor(&more);
return result ? SUCCESS : FAILURE;
@ -176,7 +202,10 @@ ZEND_API zval *zend_user_it_get_current_data(zend_object_iterator *_iter)
zval *object = &iter->it.data;
if (Z_ISUNDEF(iter->value)) {
zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_current, "current", &iter->value);
zend_class_entry *ce = iter->ce;
zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce);
zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_current, "current", &iter->value);
}
return &iter->value;
}
@ -188,8 +217,10 @@ ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *ke
zend_user_iterator *iter = (zend_user_iterator*)_iter;
zval *object = &iter->it.data;
zval retval;
zend_class_entry *ce = iter->ce;
zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce);
zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_key, "key", &retval);
zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_key, "key", &retval);
if (Z_TYPE(retval) != IS_UNDEF) {
ZVAL_ZVAL(key, &retval, 1, 1);
@ -208,9 +239,11 @@ ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter)
{
zend_user_iterator *iter = (zend_user_iterator*)_iter;
zval *object = &iter->it.data;
zend_class_entry *ce = iter->ce;
zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce);
zend_user_it_invalidate_current(_iter);
zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_next, "next", NULL);
zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_next, "next", NULL);
}
/* }}} */
@ -219,9 +252,11 @@ ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter)
{
zend_user_iterator *iter = (zend_user_iterator*)_iter;
zval *object = &iter->it.data;
zend_class_entry *ce = iter->ce;
zend_class_iterator_funcs *iterator_funcs_ptr = zend_get_iterator_funcs_ptr(ce);
zend_user_it_invalidate_current(_iter);
zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_rewind, "rewind", NULL);
zend_call_method_with_0_params(object, ce, &iterator_funcs_ptr->zf_rewind, "rewind", NULL);
}
/* }}} */
@ -312,6 +347,7 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr
{
uint32_t i;
int t = -1;
zend_class_iterator_funcs *iterator_funcs_ptr;
if (class_type->get_iterator) {
if (class_type->type == ZEND_INTERNAL_CLASS) {
@ -340,17 +376,31 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr
}
}
class_type->get_iterator = zend_user_it_get_new_iterator;
if (class_type->iterator_funcs_ptr != NULL) {
class_type->iterator_funcs_ptr->zf_new_iterator = NULL;
if (ZEND_MAP_PTR(class_type->iterator_funcs_ptr)) {
iterator_funcs_ptr = ZEND_MAP_PTR_GET(class_type->iterator_funcs_ptr);
ZEND_ASSERT(iterator_funcs_ptr);
if (class_type->type == ZEND_USER_CLASS) {
iterator_funcs_ptr->zf_new_iterator = NULL;
return SUCCESS;
}
} else if (class_type->type == ZEND_INTERNAL_CLASS) {
class_type->iterator_funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs));
/* We can use pointer even in ZTS mode, because this structure is read-only */
zend_class_iterator_funcs_ptr *iterator_funcs_ptr_ptr =
calloc(1, sizeof(zend_class_iterator_funcs_ptr));
ZEND_MAP_PTR_INIT(class_type->iterator_funcs_ptr, &iterator_funcs_ptr_ptr->ptr);
iterator_funcs_ptr = &iterator_funcs_ptr_ptr->data;
iterator_funcs_ptr_ptr->ptr = iterator_funcs_ptr;
} else {
class_type->iterator_funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs));
memset(class_type->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
}
if (class_type->type == ZEND_INTERNAL_CLASS) {
class_type->iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&class_type->function_table, "getiterator", sizeof("getiterator") - 1);
zend_class_iterator_funcs_ptr *iterator_funcs_ptr_ptr =
zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs_ptr));
iterator_funcs_ptr_ptr->ptr = &iterator_funcs_ptr_ptr->data;
ZEND_MAP_PTR_INIT(class_type->iterator_funcs_ptr, &iterator_funcs_ptr_ptr->ptr);
iterator_funcs_ptr = &iterator_funcs_ptr_ptr->data;
iterator_funcs_ptr_ptr->ptr = iterator_funcs_ptr;
memset(iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
return SUCCESS;
}
iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&class_type->function_table, "getiterator", sizeof("getiterator") - 1);
return SUCCESS;
}
/* }}} */
@ -358,6 +408,8 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr
/* {{{ zend_implement_iterator */
static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type)
{
zend_class_iterator_funcs *iterator_funcs_ptr;
if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) {
if (class_type->type == ZEND_INTERNAL_CLASS) {
/* inheritance ensures the class has the necessary userland methods */
@ -374,25 +426,39 @@ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry
}
}
class_type->get_iterator = zend_user_it_get_iterator;
if (class_type->iterator_funcs_ptr != NULL) {
class_type->iterator_funcs_ptr->zf_valid = NULL;
class_type->iterator_funcs_ptr->zf_current = NULL;
class_type->iterator_funcs_ptr->zf_key = NULL;
class_type->iterator_funcs_ptr->zf_next = NULL;
class_type->iterator_funcs_ptr->zf_rewind = NULL;
if (ZEND_MAP_PTR(class_type->iterator_funcs_ptr)) {
iterator_funcs_ptr = ZEND_MAP_PTR_GET(class_type->iterator_funcs_ptr);
ZEND_ASSERT(iterator_funcs_ptr);
if (class_type->type == ZEND_USER_CLASS) {
iterator_funcs_ptr->zf_valid = NULL;
iterator_funcs_ptr->zf_current = NULL;
iterator_funcs_ptr->zf_key = NULL;
iterator_funcs_ptr->zf_next = NULL;
iterator_funcs_ptr->zf_rewind = NULL;
return SUCCESS;
}
} else if (class_type->type == ZEND_INTERNAL_CLASS) {
class_type->iterator_funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs));
/* We can use pointer even in ZTS mode, because this structure is read-only */
zend_class_iterator_funcs_ptr *iterator_funcs_ptr_ptr =
calloc(1, sizeof(zend_class_iterator_funcs_ptr));
ZEND_MAP_PTR_INIT(class_type->iterator_funcs_ptr, &iterator_funcs_ptr_ptr->ptr);
iterator_funcs_ptr = &iterator_funcs_ptr_ptr->data;
iterator_funcs_ptr_ptr->ptr = iterator_funcs_ptr;
} else {
class_type->iterator_funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs));
memset(class_type->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
}
if (class_type->type == ZEND_INTERNAL_CLASS) {
class_type->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1);
class_type->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1);
class_type->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1);
class_type->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1);
class_type->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1);
zend_class_iterator_funcs_ptr *iterator_funcs_ptr_ptr =
zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs_ptr));
iterator_funcs_ptr_ptr->ptr = &iterator_funcs_ptr_ptr->data;
ZEND_MAP_PTR_INIT(class_type->iterator_funcs_ptr, &iterator_funcs_ptr_ptr->ptr);
iterator_funcs_ptr = &iterator_funcs_ptr_ptr->data;
iterator_funcs_ptr_ptr->ptr = iterator_funcs_ptr;
memset(iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
return SUCCESS;
}
iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1);
iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1);
iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1);
iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1);
iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1);
return SUCCESS;
}
/* }}} */

89
Zend/zend_map_ptr.h Normal file
View File

@ -0,0 +1,89 @@
/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
#ifndef ZEND_MAP_PTR_H
#define ZEND_MAP_PTR_H
#include "zend_portability.h"
#define ZEND_MAP_PTR_KIND_PTR 0
#define ZEND_MAP_PTR_KIND_PTR_OR_OFFSET 1
//#if defined(ZTS) || defined(TSRM_WIN32)
# define ZEND_MAP_PTR_KIND ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
//#else
//# define ZEND_MAP_PTR_KIND ZEND_MAP_PTR_KIND_PTR
//#endif
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
# define ZEND_MAP_PTR(ptr) \
ptr ## __ptr
# define ZEND_MAP_PTR_DEF(type, name) \
type * ZEND_MAP_PTR(name)
# define ZEND_MAP_PTR_GET(ptr) \
(*(ZEND_MAP_PTR(ptr)))
# define ZEND_MAP_PTR_SET(ptr, val) do { \
(*(ZEND_MAP_PTR(ptr))) = (val); \
} while (0)
# define ZEND_MAP_PTR_INIT(ptr, val) do { \
ZEND_MAP_PTR(ptr) = (val); \
} while (0)
# define ZEND_MAP_PTR_NEW(ptr) do { \
ZEND_MAP_PTR(ptr) = zend_map_ptr_new(); \
} while (0)
#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
# define ZEND_MAP_PTR(ptr) \
ptr ## __ptr
# define ZEND_MAP_PTR_DEF(type, name) \
type * ZEND_MAP_PTR(name)
# define ZEND_MAP_PTR_GET(ptr) \
((((uintptr_t)ZEND_MAP_PTR(ptr)) & 1L) ? \
*(void**)((char*)CG(map_ptr_base) + (uintptr_t)ZEND_MAP_PTR(ptr) - 1) : \
(void*)(*(ZEND_MAP_PTR(ptr))))
# define ZEND_MAP_PTR_SET(ptr, val) do { \
if (((uintptr_t)ZEND_MAP_PTR(ptr)) & 1L) { \
*(void**)((char*)CG(map_ptr_base) + (uintptr_t)ZEND_MAP_PTR(ptr) - 1) = (val); \
} else { \
*(ZEND_MAP_PTR(ptr)) = (val); \
} \
} while (0)
# define ZEND_MAP_PTR_INIT(ptr, val) do { \
ZEND_MAP_PTR(ptr) = (val); \
} while (0)
# define ZEND_MAP_PTR_NEW(ptr) do { \
ZEND_MAP_PTR(ptr) = zend_map_ptr_new(); \
} while (0)
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
ZEND_API void zend_map_ptr_reset(void);
ZEND_API void *zend_map_ptr_new(void);
ZEND_API void zend_map_ptr_extend(size_t last);
#endif /* ZEND_MAP_PTR_H */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* indent-tabs-mode: t
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

View File

@ -1139,6 +1139,7 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend
size_t mname_len;
zend_op_array *func;
zend_function *fbc = is_static ? ce->__callstatic : ce->__call;
static const void *dummy = (void*)(intptr_t)2;
ZEND_ASSERT(fbc);
@ -1157,7 +1158,7 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend
func->fn_flags |= ZEND_ACC_STATIC;
}
func->opcodes = &EG(call_trampoline_op);
func->run_time_cache = (void*)(intptr_t)-1;
ZEND_MAP_PTR_INIT(func->run_time_cache, (void***)&dummy);
func->scope = fbc->common.scope;
/* reserve space for arguments, local and temorary variables */
func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, 2) : 2;
@ -1352,11 +1353,7 @@ static void zend_intenal_class_init_statics(zend_class_entry *class_type) /* {{{
zend_intenal_class_init_statics(class_type->parent);
}
#if ZTS
CG(static_members_table)[class_type->static_members_table_idx] = emalloc(sizeof(zval) * class_type->default_static_members_count);
#else
class_type->static_members_table = emalloc(sizeof(zval) * class_type->default_static_members_count);
#endif
ZEND_MAP_PTR_SET(class_type->static_members_table, emalloc(sizeof(zval) * class_type->default_static_members_count));
for (i = 0; i < class_type->default_static_members_count; i++) {
p = &class_type->default_static_members_table[i];
if (Z_TYPE_P(p) == IS_INDIRECT) {
@ -1370,6 +1367,11 @@ static void zend_intenal_class_init_statics(zend_class_entry *class_type) /* {{{
}
} /* }}} */
ZEND_API void zend_class_init_statics(zend_class_entry *class_type) /* {{{ */
{
zend_intenal_class_init_statics(class_type);
} /* }}} */
ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent) /* {{{ */
{
zend_property_info *property_info = zend_hash_find_ptr(&ce->properties_info, property_name);
@ -1409,7 +1411,7 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p
/* check if static properties were destroyed */
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
if (ce->type == ZEND_INTERNAL_CLASS) {
if (ce->type == ZEND_INTERNAL_CLASS || (ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
zend_intenal_class_init_statics(ce);
} else {
undeclared_property:

View File

@ -198,6 +198,7 @@ extern const ZEND_API zend_object_handlers std_object_handlers;
#define ZEND_PROPERTY_NOT_EMPTY ZEND_ISEMPTY /* Property is not empty */
#define ZEND_PROPERTY_EXISTS 0x2 /* Property exists */
ZEND_API void zend_class_init_statics(zend_class_entry *ce);
ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name_strval, const zval *key);
ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent);
ZEND_API ZEND_COLD zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name);

View File

@ -76,6 +76,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->last_live_range = 0;
op_array->static_variables = NULL;
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
op_array->last_try_catch = 0;
op_array->fn_flags = 0;
@ -83,8 +84,8 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->last_literal = 0;
op_array->literals = NULL;
op_array->run_time_cache = NULL;
op_array->cache_size = 0;
ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
op_array->cache_size = zend_op_array_extension_handles * sizeof(void*);
memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
@ -145,11 +146,7 @@ ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce)
zval *p = static_members;
zval *end = p + ce->default_static_members_count;
#ifdef ZTS
CG(static_members_table)[ce->static_members_table_idx] = NULL;
#else
ce->static_members_table = NULL;
#endif
ZEND_MAP_PTR_SET(ce->static_members_table, NULL);
while (p != end) {
i_zval_ptr_dtor(p);
p++;
@ -213,7 +210,21 @@ ZEND_API void destroy_zend_class(zval *zv)
zend_class_entry *ce = Z_PTR_P(zv);
zend_function *fn;
if (--ce->refcount > 0) {
if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
zend_op_array *op_array;
if (ce->default_static_members_count) {
zend_cleanup_internal_class_data(ce);
}
if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
if (op_array->type == ZEND_USER_FUNCTION) {
destroy_op_array(op_array);
}
} ZEND_HASH_FOREACH_END();
}
return;
} else if (--ce->refcount > 0) {
return;
}
switch (ce->type) {
@ -305,6 +316,9 @@ ZEND_API void destroy_zend_class(zval *zv)
p++;
}
free(ce->default_static_members_table);
if (ZEND_MAP_PTR(ce->static_members_table) != &ce->default_static_members_table) {
zend_cleanup_internal_class_data(ce);
}
}
zend_hash_destroy(&ce->properties_info);
zend_string_release_ex(ce->name, 1);
@ -333,8 +347,8 @@ ZEND_API void destroy_zend_class(zval *zv)
} ZEND_HASH_FOREACH_END();
zend_hash_destroy(&ce->constants_table);
}
if (ce->iterator_funcs_ptr) {
free(ce->iterator_funcs_ptr);
if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) {
free(ZEND_MAP_PTR(ce->iterator_funcs_ptr));
}
if (ce->num_interfaces > 0) {
free(ce->interfaces);
@ -355,17 +369,18 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
{
uint32_t i;
if (op_array->static_variables &&
!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
if (GC_DELREF(op_array->static_variables) == 0) {
zend_array_destroy(op_array->static_variables);
if (op_array->static_variables) {
HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
if (ht && !(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
if (GC_DELREF(ht) == 0) {
zend_array_destroy(ht);
}
}
}
if (op_array->run_time_cache
&& (op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE)) {
efree(op_array->run_time_cache);
op_array->run_time_cache = NULL;
if ((op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE)
&& ZEND_MAP_PTR(op_array->run_time_cache)) {
efree(ZEND_MAP_PTR(op_array->run_time_cache));
}
if (!op_array->refcount || --(*op_array->refcount) > 0) {

View File

@ -3099,7 +3099,7 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -3220,7 +3220,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (OP2_TYPE != IS_CONST) {
@ -3236,7 +3236,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -3289,8 +3289,8 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper, function_name, function_name);
}
fbc = Z_FUNC_P(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
fbc = init_func_run_time_cache_ex(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
CACHE_PTR(opline->result.num, fbc);
}
@ -3410,7 +3410,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
HANDLE_EXCEPTION();
}
if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!func->op_array.run_time_cache)) {
if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&func->op_array))) {
init_func_run_time_cache(&func->op_array);
}
} else {
@ -3453,8 +3453,8 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
}
}
fbc = Z_FUNC_P(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
fbc = init_func_run_time_cache_ex(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
CACHE_PTR(opline->result.num, fbc);
}
@ -3484,8 +3484,8 @@ ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper, function_name, fname);
}
fbc = Z_FUNC_P(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
fbc = init_func_run_time_cache_ex(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
CACHE_PTR(opline->result.num, fbc);
}
@ -4963,7 +4963,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
opline->extended_value, NULL, NULL);
} else {
if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!constructor->op_array.run_time_cache)) {
if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
init_func_run_time_cache(&constructor->op_array);
}
/* We are not handling overloaded classes right now */
@ -6993,20 +6993,10 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
zval *zfunc;
zval *object;
zend_class_entry *called_scope;
zend_function *fbc;
zfunc = zend_hash_find_ex(EG(function_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION);
fbc = Z_PTR_P(zfunc);
if (fbc->common.fn_flags & ZEND_ACC_IMMUTABLE) {
zend_function *new_func = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
memcpy(new_func, fbc, sizeof(zend_op_array));
new_func->common.fn_flags &= ~ZEND_ACC_IMMUTABLE;
Z_PTR_P(zfunc) = fbc = new_func;
}
if (Z_TYPE(EX(This)) == IS_OBJECT) {
called_scope = Z_OBJCE(EX(This));
if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) ||
@ -7655,7 +7645,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
fbc = call->func;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
if (UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
execute_data = call;
@ -7781,13 +7771,17 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF)
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
zval_ptr_dtor(variable_ptr);
ht = EX(func)->op_array.static_variables;
ZEND_ASSERT(ht != NULL);
if (GC_REFCOUNT(ht) > 1) {
ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
if (!ht) {
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
ht = zend_array_dup(EX(func)->op_array.static_variables);
ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht);
} else if (GC_REFCOUNT(ht) > 1) {
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
GC_DELREF(ht);
}
EX(func)->op_array.static_variables = ht = zend_array_dup(ht);
ht = zend_array_dup(ht);
ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht);
}
value = (zval*)((char*)ht->arData + (opline->extended_value & ~ZEND_BIND_REF));

View File

@ -1908,7 +1908,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
fbc = call->func;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
if (UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
execute_data = call;
@ -2026,8 +2026,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME
ZEND_VM_TAIL_CALL(zend_undefined_function_helper_SPEC(function_name ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
fbc = Z_FUNC_P(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
fbc = init_func_run_time_cache_ex(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
CACHE_PTR(opline->result.num, fbc);
}
@ -2115,8 +2115,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_N
}
}
fbc = Z_FUNC_P(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
fbc = init_func_run_time_cache_ex(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
CACHE_PTR(opline->result.num, fbc);
}
@ -2146,8 +2146,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CO
ZEND_VM_TAIL_CALL(zend_undefined_function_helper_SPEC(fname ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
fbc = Z_FUNC_P(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
fbc = init_func_run_time_cache_ex(func);
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
CACHE_PTR(opline->result.num, fbc);
}
@ -5066,7 +5066,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -5186,7 +5186,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (IS_CONST != IS_CONST) {
@ -5202,7 +5202,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -5290,7 +5290,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
HANDLE_EXCEPTION();
}
if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!func->op_array.run_time_cache)) {
if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&func->op_array))) {
init_func_run_time_cache(&func->op_array);
}
} else {
@ -7242,7 +7242,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -7362,7 +7362,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
@ -7378,7 +7378,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -7467,7 +7467,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
HANDLE_EXCEPTION();
}
if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!func->op_array.run_time_cache)) {
if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&func->op_array))) {
init_func_run_time_cache(&func->op_array);
}
} else {
@ -8595,7 +8595,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (IS_UNUSED != IS_CONST) {
@ -8611,7 +8611,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -8753,7 +8753,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER(
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
opline->extended_value, NULL, NULL);
} else {
if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!constructor->op_array.run_time_cache)) {
if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
init_func_run_time_cache(&constructor->op_array);
}
/* We are not handling overloaded classes right now */
@ -9102,20 +9102,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_C
zval *zfunc;
zval *object;
zend_class_entry *called_scope;
zend_function *fbc;
zfunc = zend_hash_find_ex(EG(function_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION);
fbc = Z_PTR_P(zfunc);
if (fbc->common.fn_flags & ZEND_ACC_IMMUTABLE) {
zend_function *new_func = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
memcpy(new_func, fbc, sizeof(zend_op_array));
new_func->common.fn_flags &= ~ZEND_ACC_IMMUTABLE;
Z_PTR_P(zfunc) = fbc = new_func;
}
if (Z_TYPE(EX(This)) == IS_OBJECT) {
called_scope = Z_OBJCE(EX(This));
if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) ||
@ -10338,7 +10328,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -10458,7 +10448,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (IS_CV != IS_CONST) {
@ -10474,7 +10464,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -10562,7 +10552,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
HANDLE_EXCEPTION();
}
if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!func->op_array.run_time_cache)) {
if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&func->op_array))) {
init_func_run_time_cache(&func->op_array);
}
} else {
@ -14056,7 +14046,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -15666,7 +15656,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -17543,7 +17533,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -23691,7 +23681,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (IS_CONST != IS_CONST) {
@ -23707,7 +23697,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -26005,7 +25995,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
@ -26021,7 +26011,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -27564,7 +27554,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (IS_UNUSED != IS_CONST) {
@ -27580,7 +27570,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -27722,7 +27712,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
opline->extended_value, NULL, NULL);
} else {
if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!constructor->op_array.run_time_cache)) {
if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
init_func_run_time_cache(&constructor->op_array);
}
/* We are not handling overloaded classes right now */
@ -30002,7 +29992,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (IS_CV != IS_CONST) {
@ -30018,7 +30008,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -31969,7 +31959,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -32089,7 +32079,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (IS_CONST != IS_CONST) {
@ -32105,7 +32095,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -33700,7 +33690,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -33820,7 +33810,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
@ -33836,7 +33826,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -34358,7 +34348,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (IS_UNUSED != IS_CONST) {
@ -34374,7 +34364,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -34516,7 +34506,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
opline->extended_value, NULL, NULL);
} else {
if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!constructor->op_array.run_time_cache)) {
if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
init_func_run_time_cache(&constructor->op_array);
}
/* We are not handling overloaded classes right now */
@ -36075,7 +36065,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -36195,7 +36185,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (IS_CV != IS_CONST) {
@ -36211,7 +36201,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -41082,7 +41072,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -44796,7 +44786,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@ -47556,13 +47546,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HAN
variable_ptr = EX_VAR(opline->op1.var);
zval_ptr_dtor(variable_ptr);
ht = EX(func)->op_array.static_variables;
ZEND_ASSERT(ht != NULL);
if (GC_REFCOUNT(ht) > 1) {
ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
if (!ht) {
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
ht = zend_array_dup(EX(func)->op_array.static_variables);
ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht);
} else if (GC_REFCOUNT(ht) > 1) {
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
GC_DELREF(ht);
}
EX(func)->op_array.static_variables = ht = zend_array_dup(ht);
ht = zend_array_dup(ht);
ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht);
}
value = (zval*)((char*)ht->arData + (opline->extended_value & ~ZEND_BIND_REF));
@ -50643,7 +50637,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
}
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}

View File

@ -28,6 +28,7 @@
#include "zend_constants.h"
#include "zend_execute.h"
#include "zend_vm.h"
#include "zend_extensions.h"
#define DEBUG_COMPACT_LITERALS 0
@ -505,7 +506,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
method_slot = property_slot + j;
/* Update opcodes to use new literals table */
cache_size = 0;
cache_size = zend_op_array_extension_handles * sizeof(void*);
opline = op_array->opcodes;
end = opline + op_array->last;
while (opline < end) {

View File

@ -1374,6 +1374,8 @@ static zend_persistent_script *store_script_in_file_cache(zend_persistent_script
ZCG(mem) = zend_arena_alloc(&CG(arena), memory_used);
#endif
zend_shared_alloc_clear_xlat_table();
/* Copy into memory block */
new_persistent_script = zend_accel_script_persist(new_persistent_script, NULL, 0, 0);
@ -1539,6 +1541,8 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
return new_persistent_script;
}
zend_shared_alloc_clear_xlat_table();
/* Copy into shared memory */
new_persistent_script = zend_accel_script_persist(new_persistent_script, &key, key_length, 1);
@ -2278,6 +2282,7 @@ static void zend_reset_cache_vars(void)
ZSMMG(wasted_shared_memory) = 0;
ZCSG(restart_pending) = 0;
ZCSG(force_restart_time) = 0;
ZCSG(map_ptr_last) = CG(map_ptr_last);
}
static void accel_reset_pcre_cache(void)
@ -2374,6 +2379,7 @@ int accel_activate(INIT_FUNC_ARGS)
}
accel_restart_enter();
zend_map_ptr_reset();
zend_reset_cache_vars();
zend_accel_hash_clean(&ZCSG(hash));
@ -2561,7 +2567,6 @@ static int zend_accel_init_shm(void)
ZCSG(last_restart_time) = 0;
ZCSG(restart_in_progress) = 0;
for (i = 0; i < -HT_MIN_MASK; i++) {
ZCSG(uninitialized_bucket)[i] = HT_INVALID_IDX;
}

View File

@ -240,6 +240,7 @@ typedef struct _zend_accel_globals {
void *mem;
void *arena_mem;
zend_persistent_script *current_persistent_script;
zend_bool is_immutable_class;
/* cache to save hash lookup on the same INCLUDE opcode */
const zend_op *cache_opline;
zend_persistent_script *cache_persistent_script;
@ -267,6 +268,8 @@ typedef struct _zend_accel_shared_globals {
zend_ulong manual_restarts; /* number of restarts scheduled by opcache_reset() */
zend_accel_hash hash; /* hash table for cached scripts */
size_t map_ptr_last;
/* Directives & Maintenance */
time_t start_time;
time_t last_restart_time;

View File

@ -126,11 +126,14 @@ static void zend_hash_clone_constants(HashTable *ht, HashTable *source)
end = p + ht->nNumUsed;
for (; p != end; p++) {
ZEND_ASSERT(Z_TYPE(p->val) != IS_UNDEF);
c = ARENA_REALLOC(Z_PTR(p->val));
Z_PTR(p->val) = c;
c = Z_PTR(p->val);
if (IN_ARENA(c)) {
c = ARENA_REALLOC(c);
Z_PTR(p->val) = c;
if (IN_ARENA(c->ce)) {
c->ce = ARENA_REALLOC(c->ce);
if (IN_ARENA(c->ce)) {
c->ce = ARENA_REALLOC(c->ce);
}
}
}
}
@ -162,16 +165,21 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class
end = p + ht->nNumUsed;
for (; p != end; p++) {
ZEND_ASSERT(Z_TYPE(p->val) != IS_UNDEF);
new_entry = ARENA_REALLOC(Z_PTR(p->val));
Z_PTR(p->val) = new_entry;
new_entry = Z_PTR(p->val);
if (IN_ARENA(new_entry)) {
new_entry = ARENA_REALLOC(new_entry);
Z_PTR(p->val) = new_entry;
if (IN_ARENA(new_entry->scope)) {
new_entry->scope = ARENA_REALLOC(new_entry->scope);
if (IN_ARENA(new_entry->scope)) {
new_entry->scope = ARENA_REALLOC(new_entry->scope);
/* update prototype */
if (new_entry->prototype) {
new_entry->prototype = ARENA_REALLOC(new_entry->prototype);
/* update prototype */
if (IN_ARENA(new_entry->prototype)) {
new_entry->prototype = ARENA_REALLOC(new_entry->prototype);
}
}
ZEND_MAP_PTR_INIT(new_entry->run_time_cache, ARENA_REALLOC(ZEND_MAP_PTR(new_entry->run_time_cache)));
ZEND_MAP_PTR_INIT(new_entry->static_variables_ptr, &new_entry->static_variables);
}
}
}
@ -203,11 +211,14 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla
end = p + ht->nNumUsed;
for (; p != end; p++) {
ZEND_ASSERT(Z_TYPE(p->val) != IS_UNDEF);
prop_info = ARENA_REALLOC(Z_PTR(p->val));
Z_PTR(p->val) = prop_info;
prop_info = Z_PTR(p->val);
if (IN_ARENA(prop_info)) {
prop_info = ARENA_REALLOC(prop_info);
Z_PTR(p->val) = prop_info;
if (IN_ARENA(prop_info->ce)) {
prop_info->ce = ARENA_REALLOC(prop_info->ce);
if (IN_ARENA(prop_info->ce)) {
prop_info->ce = ARENA_REALLOC(prop_info->ce);
}
}
}
}
@ -229,7 +240,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
*pce = ce = ARENA_REALLOC(old_ce);
ce->refcount = 1;
if (ce->parent && (ce->ce_flags & ZEND_ACC_LINKED)) {
if ((ce->ce_flags & ZEND_ACC_LINKED) && IN_ARENA(ce->parent)) {
ce->parent = ARENA_REALLOC(ce->parent);
}
@ -271,7 +282,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
parent = parent->parent;
}
}
ce->static_members_table = ce->default_static_members_table;
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
/* properties_info */
zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce);
@ -282,10 +293,23 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
if (ce->num_interfaces) {
zend_class_name *interface_names;
ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_LINKED));
interface_names = emalloc(sizeof(zend_class_name) * ce->num_interfaces);
memcpy(interface_names, ce->interface_names, sizeof(zend_class_name) * ce->num_interfaces);
ce->interface_names = interface_names;
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
interface_names = emalloc(sizeof(zend_class_name) * ce->num_interfaces);
memcpy(interface_names, ce->interface_names, sizeof(zend_class_name) * ce->num_interfaces);
ce->interface_names = interface_names;
} else {
zend_class_entry **interfaces = emalloc(sizeof(zend_class_entry*) * ce->num_interfaces);
uint32_t i;
for (i = 0; i < ce->num_interfaces; i++) {
if (IN_ARENA(ce->interfaces[i])) {
interfaces[i] = ARENA_REALLOC(ce->interfaces[i]);
} else {
interfaces[i] = ce->interfaces[i];
}
}
ce->interfaces = interfaces;
}
}
zend_update_inherited_handler(constructor);
@ -349,6 +373,11 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
ce->trait_precedences = trait_precedences;
}
}
if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) {
ZEND_MAP_PTR_INIT(ce->iterator_funcs_ptr, ARENA_REALLOC(ZEND_MAP_PTR(ce->iterator_funcs_ptr)));
ZEND_MAP_PTR_SET(ce->iterator_funcs_ptr, ARENA_REALLOC(ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr)));
}
}
static void zend_accel_function_hash_copy(HashTable *target, HashTable *source)
@ -507,7 +536,9 @@ static void zend_accel_class_hash_copy_from_shm(HashTable *target, HashTable *so
}
} else {
t = _zend_hash_append_ptr_ex(target, p->key, Z_PTR(p->val), 1);
zend_class_copy_ctor((zend_class_entry**)&Z_PTR_P(t));
if (!(((zend_class_entry*)Z_PTR_P(t))->ce_flags & ZEND_ACC_IMMUTABLE)) {
zend_class_copy_ctor((zend_class_entry**)&Z_PTR_P(t));
}
}
}
target->nInternalPointer = 0;
@ -668,6 +699,7 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
*op_array = persistent_script->script.main_op_array;
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
if (EXPECTED(from_shared_memory)) {
zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0);
@ -712,6 +744,7 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
zend_hash_destroy(&ZCG(bind_hash));
ZCG(current_persistent_script) = NULL;
zend_map_ptr_extend(ZCSG(map_ptr_last));
} else /* if (!from_shared_memory) */ {
if (zend_hash_num_elements(&persistent_script->script.function_table) > 0) {
zend_accel_function_hash_copy(CG(function_table), &persistent_script->script.function_table);

View File

@ -534,6 +534,13 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
SERIALIZE_STR(op_array->doc_comment);
SERIALIZE_PTR(op_array->try_catch_array);
SERIALIZE_PTR(op_array->prototype);
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
} else {
SERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
}
}
}
@ -749,6 +756,15 @@ static void zend_file_cache_serialize_class(zval *zv,
SERIALIZE_PTR(ce->__tostring);
SERIALIZE_PTR(ce->__callstatic);
SERIALIZE_PTR(ce->__debugInfo);
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) {
if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
ZEND_MAP_PTR_INIT(ce->iterator_funcs_ptr, (void*)(uintptr_t)1);
} else {
SERIALIZE_PTR(ZEND_MAP_PTR(ce->iterator_funcs_ptr));
}
}
}
static void zend_file_cache_serialize(zend_persistent_script *script,
@ -1183,6 +1199,18 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
UNSERIALIZE_STR(op_array->doc_comment);
UNSERIALIZE_PTR(op_array->try_catch_array);
UNSERIALIZE_PTR(op_array->prototype);
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
if (op_array->static_variables) {
ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
} else {
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
}
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
} else {
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
UNSERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
}
}
}
@ -1384,6 +1412,20 @@ static void zend_file_cache_unserialize_class(zval *zv,
ce->serialize = zend_class_serialize_deny;
ce->unserialize = zend_class_unserialize_deny;
}
if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
if (ce->default_static_members_table) {
ZEND_MAP_PTR_NEW(ce->static_members_table);
} else {
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
}
if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) {
ZEND_MAP_PTR_NEW(ce->iterator_funcs_ptr);
}
} else {
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
UNSERIALIZE_PTR(ZEND_MAP_PTR(ce->iterator_funcs_ptr));
}
}
static void zend_file_cache_unserialize(zend_persistent_script *script,
@ -1546,6 +1588,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
goto use_process_mem;
}
memcpy(buf, mem, info.mem_size);
zend_map_ptr_extend(ZCSG(map_ptr_last));
} else {
use_process_mem:
buf = mem;
@ -1576,6 +1619,7 @@ use_process_mem:
script->corrupted = 0;
if (cache_it) {
ZCSG(map_ptr_last) = CG(map_ptr_last);
script->dynamic_members.checksum = zend_accel_script_checksum(script);
script->dynamic_members.last_used = ZCG(request_time);

View File

@ -391,9 +391,14 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
GC_TYPE_INFO(op_array->static_variables) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << GC_FLAGS_SHIFT);
}
}
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
if (op_array->scope) {
op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
zend_class_entry *scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
if (scope) {
op_array->scope = scope;
}
if (op_array->prototype) {
zend_function *ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype);
@ -557,7 +562,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
efree(op_array->opcodes);
op_array->opcodes = new_opcodes;
op_array->run_time_cache = NULL;
ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
}
if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) {
@ -633,11 +638,19 @@ static void zend_persist_op_array(zval *zv)
zend_op_array *op_array = Z_PTR_P(zv);
ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
memcpy(ZCG(mem), Z_PTR_P(zv), sizeof(zend_op_array));
Z_PTR_P(zv) = ZCG(mem);
ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(sizeof(zend_op_array)));
zend_persist_op_array_ex(Z_PTR_P(zv), NULL);
((zend_op_array*)Z_PTR_P(zv))->fn_flags |= ZEND_ACC_IMMUTABLE;
op_array = Z_PTR_P(zv) = zend_shared_memdup(Z_PTR_P(zv), sizeof(zend_op_array));
zend_persist_op_array_ex(op_array, NULL);
if (!ZCG(current_persistent_script)->corrupted) {
op_array->fn_flags |= ZEND_ACC_IMMUTABLE;
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
if (op_array->static_variables) {
ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
}
} else {
ZEND_MAP_PTR_INIT(op_array->run_time_cache, ZCG(arena_mem));
ZCG(arena_mem) = (void*)(((char*)ZCG(arena_mem)) + ZEND_ALIGNED_SIZE(sizeof(void*)));
ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
}
}
static void zend_persist_class_method(zval *zv)
@ -645,7 +658,35 @@ static void zend_persist_class_method(zval *zv)
zend_op_array *op_array = Z_PTR_P(zv);
zend_op_array *old_op_array;
ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
if (op_array->type != ZEND_USER_FUNCTION) {
ZEND_ASSERT(op_array->type == ZEND_INTERNAL_FUNCTION);
if (op_array->fn_flags & ZEND_ACC_ARENA_ALLOCATED) {
old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
if (old_op_array) {
Z_PTR_P(zv) = old_op_array;
} else {
if (ZCG(is_immutable_class)) {
op_array = Z_PTR_P(zv) = zend_shared_memdup_put(op_array, sizeof(zend_internal_function));
} else {
op_array = Z_PTR_P(zv) = zend_shared_memdup_arena_put(op_array, sizeof(zend_internal_function));
}
if (op_array->scope) {
void *persist_ptr;
if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->scope))) {
op_array->scope = (zend_class_entry*)persist_ptr;
}
if (op_array->prototype) {
if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
op_array->prototype = (zend_function*)persist_ptr;
}
}
}
}
}
return;
}
old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
if (old_op_array) {
Z_PTR_P(zv) = old_op_array;
@ -654,11 +695,23 @@ static void zend_persist_class_method(zval *zv)
}
return;
}
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);
if (ZCG(is_immutable_class)) {
op_array = Z_PTR_P(zv) = zend_shared_memdup_put(op_array, sizeof(zend_op_array));
} else {
op_array = Z_PTR_P(zv) = zend_shared_memdup_arena_put(op_array, sizeof(zend_op_array));
}
zend_persist_op_array_ex(op_array, NULL);
if (ZCG(is_immutable_class)) {
op_array->fn_flags |= ZEND_ACC_IMMUTABLE;
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
if (op_array->static_variables) {
ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
}
} else {
ZEND_MAP_PTR_INIT(op_array->run_time_cache, ZCG(arena_mem));
ZCG(arena_mem) = (void*)(((char*)ZCG(arena_mem)) + ZEND_ALIGNED_SIZE(sizeof(void*)));
ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
}
}
static void zend_persist_property_info(zval *zv)
@ -669,10 +722,11 @@ static void zend_persist_property_info(zval *zv)
Z_PTR_P(zv) = prop;
return;
}
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)));
if (ZCG(is_immutable_class)) {
prop = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_property_info));
} else {
prop = Z_PTR_P(zv) = zend_shared_memdup_arena_put(Z_PTR_P(zv), sizeof(zend_property_info));
}
prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
zend_accel_store_interned_string(prop->name);
if (prop->doc_comment) {
@ -696,10 +750,11 @@ static void zend_persist_class_constant(zval *zv)
Z_PTR_P(zv) = c;
return;
}
memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_constant));
zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
c = Z_PTR_P(zv) = ZCG(arena_mem);
ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_constant)));
if (ZCG(is_immutable_class)) {
c = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_class_constant));
} else {
c = Z_PTR_P(zv) = zend_shared_memdup_arena_put(Z_PTR_P(zv), sizeof(zend_class_constant));
}
zend_persist_zval(&c->value);
c->ce = zend_shared_alloc_get_xlat_entry(c->ce);
if (c->doc_comment) {
@ -726,10 +781,16 @@ 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)));
if ((ce->ce_flags & ZEND_ACC_LINKED)
&& (ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)
&& !ZCG(current_persistent_script)->corrupted) {
ZCG(is_immutable_class) = 1;
ce = Z_PTR_P(zv) = zend_shared_memdup_put(ce, sizeof(zend_class_entry));
ce->ce_flags |= ZEND_ACC_IMMUTABLE;
} else {
ZCG(is_immutable_class) = 0;
ce = Z_PTR_P(zv) = zend_shared_memdup_arena_put(ce, sizeof(zend_class_entry));
}
zend_accel_store_interned_string(ce->name);
if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_LINKED)) {
zend_accel_store_interned_string(ce->parent_name);
@ -754,8 +815,14 @@ static void zend_persist_class_entry(zval *zv)
for (; i < ce->default_static_members_count; i++) {
zend_persist_zval(&ce->default_static_members_table[i]);
}
if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
ZEND_MAP_PTR_NEW(ce->static_members_table);
} else {
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
}
} else {
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
}
ce->static_members_table = NULL;
zend_hash_persist(&ce->constants_table, zend_persist_class_constant);
HT_FLAGS(&ce->constants_table) &= (HASH_FLAG_INITIALIZED | HASH_FLAG_STATIC_KEYS);
@ -778,10 +845,9 @@ static void zend_persist_class_entry(zval *zv)
zend_hash_persist(&ce->properties_info, zend_persist_property_info);
HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_INITIALIZED | HASH_FLAG_STATIC_KEYS);
if (ce->num_interfaces) {
if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_LINKED)) {
uint32_t i = 0;
ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_LINKED));
for (i = 0; i < ce->num_interfaces; i++) {
zend_accel_store_interned_string(ce->interface_names[i].name);
zend_accel_store_interned_string(ce->interface_names[i].lc_name);
@ -838,6 +904,16 @@ static void zend_persist_class_entry(zval *zv)
ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
}
}
if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) {
if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
ZEND_MAP_PTR_NEW(ce->iterator_funcs_ptr);
} else {
ZEND_MAP_PTR_INIT(ce->iterator_funcs_ptr, ZCG(arena_mem));
ZCG(arena_mem) = (void*)(((char*)ZCG(arena_mem)) + ZEND_ALIGNED_SIZE(sizeof(void*)));
ZEND_MAP_PTR_SET(ce->iterator_funcs_ptr, zend_shared_memdup_arena(ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr), sizeof(zend_class_iterator_funcs)));
}
}
}
}
@ -853,8 +929,45 @@ static int zend_update_parent_ce(zval *zv)
{
zend_class_entry *ce = Z_PTR_P(zv);
if (ce->parent && (ce->ce_flags & ZEND_ACC_LINKED)) {
ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
if (ce->ce_flags & ZEND_ACC_LINKED) {
if (ce->parent) {
int i, end;
zend_class_entry *parent = ce->parent;
if (parent->type == ZEND_USER_CLASS) {
zend_class_entry *p = zend_shared_alloc_get_xlat_entry(parent);
if (p) {
ce->parent = parent = p;
}
}
/* Create indirections to static properties from parent classes */
i = parent->default_static_members_count - 1;
while (parent && parent->default_static_members_table) {
end = parent->parent ? parent->parent->default_static_members_count : 0;
for (; i >= end; i--) {
zval *p = &ce->default_static_members_table[i];
ZVAL_INDIRECT(p, &parent->default_static_members_table[i]);
}
parent = parent->parent;
}
}
if (ce->num_interfaces) {
uint32_t i = 0;
ce->interfaces = zend_shared_memdup_free(ce->interfaces, sizeof(zend_class_entry*) * ce->num_interfaces);
for (i = 0; i < ce->num_interfaces; i++) {
if (ce->interfaces[i]->type == ZEND_USER_CLASS) {
zend_class_entry *tmp = zend_shared_alloc_get_xlat_entry(ce->interfaces[i]);
if (tmp != NULL) {
ce->interfaces[i] = tmp;
}
}
}
}
}
/* update methods */
@ -912,7 +1025,6 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
script->mem = ZCG(mem);
ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
zend_shared_alloc_clear_xlat_table();
script = zend_shared_memdup_free(script, sizeof(zend_persistent_script));
if (key && *key) {
@ -939,10 +1051,14 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
script->arena_mem = ZCG(arena_mem) = ZCG(mem);
ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size);
zend_map_ptr_extend(ZCSG(map_ptr_last));
zend_accel_persist_class_table(&script->script.class_table);
zend_hash_persist(&script->script.function_table, zend_persist_op_array);
zend_persist_op_array_ex(&script->script.main_op_array, script);
ZCSG(map_ptr_last) = CG(map_ptr_last);
script->corrupted = 0;
ZCG(current_persistent_script) = NULL;

View File

@ -28,8 +28,15 @@
#define ADD_DUP_SIZE(m,s) ZCG(current_persistent_script)->size += zend_shared_memdup_size((void*)m, s)
#define ADD_SIZE(m) ZCG(current_persistent_script)->size += ZEND_ALIGNED_SIZE(m)
#define ADD_ARENA_SIZE(m) ZCG(current_persistent_script)->arena_size += ZEND_ALIGNED_SIZE(m)
#define ADD_ARENA_SIZE(m) ZCG(current_persistent_script)->arena_size += ZEND_ALIGNED_SIZE(m)
#define ADD_SIZE_EX(m) do { \
if (ZCG(is_immutable_class)) { \
ADD_SIZE(m); \
} else { \
ADD_ARENA_SIZE(m); \
} \
} while (0)
# define ADD_STRING(str) ADD_DUP_SIZE((str), _ZSTR_STRUCT_SIZE(ZSTR_LEN(str)))
@ -258,6 +265,9 @@ static void zend_persist_op_array_calc(zval *zv)
ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
ADD_SIZE(sizeof(zend_op_array));
zend_persist_op_array_calc_ex(Z_PTR_P(zv));
if (ZCG(current_persistent_script)->corrupted) {
ADD_ARENA_SIZE(sizeof(void*));
}
}
static void zend_persist_class_method_calc(zval *zv)
@ -265,12 +275,26 @@ static void zend_persist_class_method_calc(zval *zv)
zend_op_array *op_array = Z_PTR_P(zv);
zend_op_array *old_op_array;
ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
if (op_array->type != ZEND_USER_FUNCTION) {
ZEND_ASSERT(op_array->type == ZEND_INTERNAL_FUNCTION);
if (op_array->fn_flags & ZEND_ACC_ARENA_ALLOCATED) {
old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
if (!old_op_array) {
ADD_SIZE_EX(sizeof(zend_internal_function));
zend_shared_alloc_register_xlat_entry(op_array, Z_PTR_P(zv));
}
}
return;
}
old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
if (!old_op_array) {
ADD_ARENA_SIZE(sizeof(zend_op_array));
ADD_SIZE_EX(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));
if (!ZCG(is_immutable_class)) {
ADD_ARENA_SIZE(sizeof(void*));
}
}
}
@ -280,7 +304,7 @@ static void zend_persist_property_info_calc(zval *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_SIZE_EX(sizeof(zend_property_info));
ADD_INTERNED_STRING(prop->name, 0);
if (ZCG(accel_directives).save_comments && prop->doc_comment) {
ADD_STRING(prop->doc_comment);
@ -294,7 +318,7 @@ static void zend_persist_class_constant_calc(zval *zv)
if (!zend_shared_alloc_get_xlat_entry(c)) {
zend_shared_alloc_register_xlat_entry(c, c);
ADD_ARENA_SIZE(sizeof(zend_class_constant));
ADD_SIZE_EX(sizeof(zend_class_constant));
zend_persist_zval_calc(&c->value);
if (ZCG(accel_directives).save_comments && c->doc_comment) {
ADD_STRING(c->doc_comment);
@ -302,13 +326,17 @@ static void zend_persist_class_constant_calc(zval *zv)
}
}
static void zend_persist_class_entry_calc(zval *zv)
{
zend_class_entry *ce = Z_PTR_P(zv);
if (ce->type == ZEND_USER_CLASS) {
ADD_ARENA_SIZE(sizeof(zend_class_entry));
ZCG(is_immutable_class) =
(ce->ce_flags & ZEND_ACC_LINKED) &&
(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) &&
!ZCG(current_persistent_script)->corrupted;
ADD_SIZE_EX(sizeof(zend_class_entry));
ADD_INTERNED_STRING(ce->name, 0);
if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_LINKED)) {
ADD_INTERNED_STRING(ce->parent_name, 0);
@ -346,12 +374,15 @@ static void zend_persist_class_entry_calc(zval *zv)
if (ce->num_interfaces) {
uint32_t i;
ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_LINKED));
for (i = 0; i < ce->num_interfaces; i++) {
ADD_INTERNED_STRING(ce->interface_names[i].name, 0);
ADD_INTERNED_STRING(ce->interface_names[i].lc_name, 0);
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
for (i = 0; i < ce->num_interfaces; i++) {
ADD_INTERNED_STRING(ce->interface_names[i].name, 0);
ADD_INTERNED_STRING(ce->interface_names[i].lc_name, 0);
}
ADD_SIZE(sizeof(zend_class_name) * ce->num_interfaces);
} else {
ADD_SIZE(sizeof(zend_class_entry*) * ce->num_interfaces);
}
ADD_SIZE(sizeof(zend_class_name) * ce->num_interfaces);
}
if (ce->num_traits) {
@ -399,6 +430,13 @@ static void zend_persist_class_entry_calc(zval *zv)
ADD_SIZE(sizeof(zend_trait_precedence*) * (i + 1));
}
}
if (ZEND_MAP_PTR(ce->iterator_funcs_ptr)) {
if (!ZCG(is_immutable_class)) {
ADD_ARENA_SIZE(sizeof(void*));
ADD_ARENA_SIZE(sizeof(zend_class_iterator_funcs));
}
}
}
}

View File

@ -347,7 +347,7 @@ int zend_shared_memdup_size(void *source, size_t size)
return ZEND_ALIGNED_SIZE(size);
}
static zend_always_inline void *_zend_shared_memdup(void *source, size_t size, zend_bool get_xlat, zend_bool set_xlat, zend_bool free_source)
static zend_always_inline void *_zend_shared_memdup(void *source, size_t size, zend_bool arena, zend_bool get_xlat, zend_bool set_xlat, zend_bool free_source)
{
void *old_p, *retval;
zend_ulong key;
@ -360,8 +360,13 @@ static zend_always_inline void *_zend_shared_memdup(void *source, size_t size, z
return old_p;
}
}
retval = ZCG(mem);
ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size));
if (arena) {
retval = ZCG(arena_mem);
ZCG(arena_mem) = (void*)(((char*)ZCG(arena_mem)) + ZEND_ALIGNED_SIZE(size));
} else {
retval = ZCG(mem);
ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size));
}
memcpy(retval, source, size);
if (set_xlat) {
if (!get_xlat) {
@ -378,32 +383,42 @@ static zend_always_inline void *_zend_shared_memdup(void *source, size_t size, z
void *zend_shared_memdup_get_put_free(void *source, size_t size)
{
return _zend_shared_memdup(source, size, 1, 1, 1);
return _zend_shared_memdup(source, size, 0, 1, 1, 1);
}
void *zend_shared_memdup_put_free(void *source, size_t size)
{
return _zend_shared_memdup(source, size, 0, 1, 1);
return _zend_shared_memdup(source, size, 0, 0, 1, 1);
}
void *zend_shared_memdup_free(void *source, size_t size)
{
return _zend_shared_memdup(source, size, 0, 0, 1);
return _zend_shared_memdup(source, size, 0, 0, 0, 1);
}
void *zend_shared_memdup_get_put(void *source, size_t size)
{
return _zend_shared_memdup(source, size, 1, 1, 0);
return _zend_shared_memdup(source, size, 0, 1, 1, 0);
}
void *zend_shared_memdup_put(void *source, size_t size)
{
return _zend_shared_memdup(source, size, 0, 1, 0);
return _zend_shared_memdup(source, size, 0, 0, 1, 0);
}
void *zend_shared_memdup(void *source, size_t size)
{
return _zend_shared_memdup(source, size, 0, 0, 0);
return _zend_shared_memdup(source, size, 0, 0, 0, 0);
}
void *zend_shared_memdup_arena_put(void *source, size_t size)
{
return _zend_shared_memdup(source, size, 1, 0, 1, 0);
}
void *zend_shared_memdup_arena(void *source, size_t size)
{
return _zend_shared_memdup(source, size, 1, 0, 0, 0);
}
void zend_shared_alloc_safe_unlock(void)
@ -483,6 +498,16 @@ void zend_shared_alloc_clear_xlat_table(void)
zend_hash_clean(&ZCG(xlat_table));
}
uint32_t zend_shared_alloc_checkpoint_xlat_table(void)
{
return ZCG(xlat_table).nNumUsed;
}
void zend_shared_alloc_restore_xlat_table(uint32_t checkpoint)
{
zend_hash_discard(&ZCG(xlat_table), checkpoint);
}
void zend_shared_alloc_register_xlat_entry(const void *old, const void *new)
{
zend_ulong key = (zend_ulong)old;

View File

@ -131,6 +131,8 @@ void *zend_shared_memdup_free(void *source, size_t size);
void *zend_shared_memdup_get_put(void *source, size_t size);
void *zend_shared_memdup_put(void *source, size_t size);
void *zend_shared_memdup(void *source, size_t size);
void *zend_shared_memdup_arena_put(void *source, size_t size);
void *zend_shared_memdup_arena(void *source, size_t size);
int zend_shared_memdup_size(void *p, size_t size);
@ -160,6 +162,8 @@ void zend_shared_alloc_safe_unlock(void);
void zend_shared_alloc_init_xlat_table(void);
void zend_shared_alloc_destroy_xlat_table(void);
void zend_shared_alloc_clear_xlat_table(void);
uint32_t zend_shared_alloc_checkpoint_xlat_table(void);
void zend_shared_alloc_restore_xlat_table(uint32_t checkpoint);
void zend_shared_alloc_register_xlat_entry(const void *old, const void *new);
void *zend_shared_alloc_get_xlat_entry(const void *old);

View File

@ -685,7 +685,7 @@ static void _function_closure_string(smart_str *str, zend_function *fptr, char*
return;
}
static_variables = fptr->op_array.static_variables;
static_variables = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
count = zend_hash_num_elements(static_variables);
if (!count) {
@ -1790,19 +1790,21 @@ ZEND_METHOD(reflection_function, getStaticVariables)
/* Return an empty array in case no static variables exist */
if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
HashTable *ht;
array_init(return_value);
if (GC_REFCOUNT(fptr->op_array.static_variables) > 1) {
if (!(GC_FLAGS(fptr->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
GC_DELREF(fptr->op_array.static_variables);
}
fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables);
ht = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
if (!ht) {
ZEND_ASSERT(fptr->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
ht = zend_array_dup(fptr->op_array.static_variables);
ZEND_MAP_PTR_SET(fptr->op_array.static_variables_ptr, ht);
}
ZEND_HASH_FOREACH_VAL(fptr->op_array.static_variables, val) {
ZEND_HASH_FOREACH_VAL(ht, val) {
if (UNEXPECTED(zval_update_constant_ex(val, fptr->common.scope) != SUCCESS)) {
return;
}
} ZEND_HASH_FOREACH_END();
zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, zval_add_ref);
zend_hash_copy(Z_ARRVAL_P(return_value), ht, zval_add_ref);
} else {
ZVAL_EMPTY_ARRAY(return_value);
}

View File

@ -243,19 +243,22 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zval *
/* Cache iterator functions if ArrayIterator or derived. Check current's */
/* cache since only current is always required */
if (intern->std.handlers == &spl_handler_ArrayIterator) {
if (!class_type->iterator_funcs_ptr->zf_current) {
class_type->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1);
class_type->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1);
class_type->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1);
class_type->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1);
class_type->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1);
zend_class_iterator_funcs *iterator_funcs_ptr =
ZEND_MAP_PTR_GET(class_type->iterator_funcs_ptr);
if (!iterator_funcs_ptr->zf_current) {
iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1);
iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1);
iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1);
iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1);
iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1);
}
if (inherited) {
if (class_type->iterator_funcs_ptr->zf_rewind->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_REWIND;
if (class_type->iterator_funcs_ptr->zf_valid->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_VALID;
if (class_type->iterator_funcs_ptr->zf_key->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_KEY;
if (class_type->iterator_funcs_ptr->zf_current->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_CURRENT;
if (class_type->iterator_funcs_ptr->zf_next->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_NEXT;
if (iterator_funcs_ptr->zf_rewind->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_REWIND;
if (iterator_funcs_ptr->zf_valid->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_VALID;
if (iterator_funcs_ptr->zf_key->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_KEY;
if (iterator_funcs_ptr->zf_current->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_CURRENT;
if (iterator_funcs_ptr->zf_next->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_NEXT;
}
}

View File

@ -207,6 +207,7 @@ static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, z
spl_fixedarray_object *intern;
zend_class_entry *parent = class_type;
int inherited = 0;
zend_class_iterator_funcs *iterator_funcs_ptr;
intern = zend_object_alloc(sizeof(spl_fixedarray_object), parent);
@ -238,27 +239,28 @@ static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, z
php_error_docref(NULL, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplFixedArray");
}
if (!class_type->iterator_funcs_ptr->zf_current) {
class_type->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1);
class_type->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1);
class_type->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1);
class_type->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1);
class_type->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1);
iterator_funcs_ptr = ZEND_MAP_PTR_GET(class_type->iterator_funcs_ptr);
if (!iterator_funcs_ptr->zf_current) {
iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1);
iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1);
iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1);
iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1);
iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1);
}
if (inherited) {
if (class_type->iterator_funcs_ptr->zf_rewind->common.scope != parent) {
if (iterator_funcs_ptr->zf_rewind->common.scope != parent) {
intern->flags |= SPL_FIXEDARRAY_OVERLOADED_REWIND;
}
if (class_type->iterator_funcs_ptr->zf_valid->common.scope != parent) {
if (iterator_funcs_ptr->zf_valid->common.scope != parent) {
intern->flags |= SPL_FIXEDARRAY_OVERLOADED_VALID;
}
if (class_type->iterator_funcs_ptr->zf_key->common.scope != parent) {
if (iterator_funcs_ptr->zf_key->common.scope != parent) {
intern->flags |= SPL_FIXEDARRAY_OVERLOADED_KEY;
}
if (class_type->iterator_funcs_ptr->zf_current->common.scope != parent) {
if (iterator_funcs_ptr->zf_current->common.scope != parent) {
intern->flags |= SPL_FIXEDARRAY_OVERLOADED_CURRENT;
}
if (class_type->iterator_funcs_ptr->zf_next->common.scope != parent) {
if (iterator_funcs_ptr->zf_next->common.scope != parent) {
intern->flags |= SPL_FIXEDARRAY_OVERLOADED_NEXT;
}

View File

@ -494,7 +494,8 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "o|lzl", &iterator, &flags, &user_caching_it_flags, &mode) == SUCCESS) {
if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate)) {
zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &Z_OBJCE_P(iterator)->iterator_funcs_ptr->zf_new_iterator, "getiterator", &aggregate_retval);
zend_class_iterator_funcs *iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(iterator)->iterator_funcs_ptr);
zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &iterator_funcs_ptr->zf_new_iterator, "getiterator", &aggregate_retval);
iterator = &aggregate_retval;
} else {
Z_ADDREF_P(iterator);
@ -522,7 +523,8 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "o|ll", &iterator, &mode, &flags) == SUCCESS) {
if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate)) {
zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &Z_OBJCE_P(iterator)->iterator_funcs_ptr->zf_new_iterator, "getiterator", &aggregate_retval);
zend_class_iterator_funcs *iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(iterator)->iterator_funcs_ptr);
zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &iterator_funcs_ptr->zf_new_iterator, "getiterator", &aggregate_retval);
iterator = &aggregate_retval;
} else {
Z_ADDREF_P(iterator);
@ -1348,19 +1350,6 @@ static const zend_function_entry spl_funcs_RecursiveTreeIterator[] = {
PHP_FE_END
};
#if MBO_0
static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_entry *class_type)
{
class_type->iterator_funcs_ptr->zf_valid = NULL;
class_type->iterator_funcs_ptr->zf_current = NULL;
class_type->iterator_funcs_ptr->zf_key = NULL;
class_type->iterator_funcs_ptr->zf_next = NULL;
class_type->iterator_funcs_ptr->zf_rewind = NULL;
return SUCCESS;
}
#endif
static zend_function *spl_dual_it_get_method(zend_object **object, zend_string *method, const zval *key)
{
zend_function *function_handler;
@ -1513,7 +1502,8 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
ce = ce_cast;
}
if (instanceof_function(ce, zend_ce_aggregate)) {
zend_call_method_with_0_params(zobject, ce, &ce->iterator_funcs_ptr->zf_new_iterator, "getiterator", &retval);
zend_class_iterator_funcs *iterator_funcs_ptr = ZEND_MAP_PTR_GET(ce->iterator_funcs_ptr);
zend_call_method_with_0_params(zobject, ce, &iterator_funcs_ptr->zf_new_iterator, "getiterator", &retval);
if (EG(exception)) {
zval_ptr_dtor(&retval);
return NULL;

View File

@ -1028,8 +1028,11 @@ SPL_METHOD(MultipleIterator, rewind)
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) {
zend_class_iterator_funcs *iterator_funcs_ptr;
it = &element->obj;
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_rewind, "rewind", NULL);
iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(it)->iterator_funcs_ptr);
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_rewind, "rewind", NULL);
zend_hash_move_forward_ex(&intern->storage, &intern->pos);
}
}
@ -1051,8 +1054,11 @@ SPL_METHOD(MultipleIterator, next)
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) {
zend_class_iterator_funcs *iterator_funcs_ptr;
it = &element->obj;
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_next, "next", NULL);
iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(it)->iterator_funcs_ptr);
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_next, "next", NULL);
zend_hash_move_forward_ex(&intern->storage, &intern->pos);
}
}
@ -1081,8 +1087,11 @@ SPL_METHOD(MultipleIterator, valid)
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) {
zend_class_iterator_funcs *iterator_funcs_ptr;
it = &element->obj;
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_valid, "valid", &retval);
iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(it)->iterator_funcs_ptr);
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_valid, "valid", &retval);
if (!Z_ISUNDEF(retval)) {
valid = (Z_TYPE(retval) == IS_TRUE);
@ -1117,8 +1126,11 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) {
zend_class_iterator_funcs *iterator_funcs_ptr;
it = &element->obj;
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_valid, "valid", &retval);
iterator_funcs_ptr = ZEND_MAP_PTR_GET(Z_OBJCE_P(it)->iterator_funcs_ptr);
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_valid, "valid", &retval);
if (!Z_ISUNDEF(retval)) {
valid = Z_TYPE(retval) == IS_TRUE;
@ -1129,9 +1141,9 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_
if (valid) {
if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) {
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_current, "current", &retval);
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_current, "current", &retval);
} else {
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_key, "key", &retval);
zend_call_method_with_0_params(it, Z_OBJCE_P(it), &iterator_funcs_ptr->zf_key, "key", &retval);
}
if (Z_ISUNDEF(retval)) {
zend_throw_exception(spl_ce_RuntimeException, "Failed to call sub iterator method", 0);