Skip to content

Avoid non-immutable map_ptr indirection #7394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 5 additions & 42 deletions Zend/zend.c
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,6 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{
compiler_globals->script_encoding_list = NULL;
compiler_globals->current_linking_class = 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_real_base = NULL;
compiler_globals->map_ptr_base = ZEND_MAP_PTR_BIASED_BASE(NULL);
Expand All @@ -716,9 +715,6 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{
compiler_globals->map_ptr_base = ZEND_MAP_PTR_BIASED_BASE(base);
memset(base, 0, compiler_globals->map_ptr_last * sizeof(void*));
}
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
}
/* }}} */

Expand Down Expand Up @@ -967,24 +963,11 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */
#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 allocated 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_real_base) = pemalloc(CG(map_ptr_size) * sizeof(void*), 1);
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
# 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_real_base) = NULL;
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(NULL);
CG(map_ptr_size) = 0;
CG(map_ptr_last) = 0;
# else
# error "Unknown ZEND_MAP_PTR_KIND"
# endif
/* Map region is going to be created and resized at run-time. */
CG(map_ptr_real_base) = NULL;
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(NULL);
CG(map_ptr_size) = 0;
CG(map_ptr_last) = 0;
#endif
EG(error_reporting) = E_ALL & ~E_NOTICE;

Expand Down Expand Up @@ -1821,28 +1804,15 @@ 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_UNREACHABLE();
#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_real_base) = perealloc(CG(map_ptr_real_base), CG(map_ptr_size) * sizeof(void*), 1);
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
}
ptr = (void**)CG(map_ptr_real_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 ZEND_MAP_PTR_PTR2OFFSET(ptr);
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
}

ZEND_API void zend_map_ptr_extend(size_t last)
Expand All @@ -1851,17 +1821,10 @@ ZEND_API void zend_map_ptr_extend(size_t last)
void **ptr;

if (last >= CG(map_ptr_size)) {
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
/* This may never happen */
ZEND_UNREACHABLE();
#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_real_base) = perealloc(CG(map_ptr_real_base), CG(map_ptr_size) * sizeof(void*), 1);
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
}
ptr = (void**)CG(map_ptr_real_base) + CG(map_ptr_last);
memset(ptr, 0, (last - CG(map_ptr_last)) * sizeof(void*));
Expand Down
4 changes: 0 additions & 4 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -4054,10 +4054,6 @@ ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, z
if (ce->type == ZEND_INTERNAL_CLASS &&
ce->info.internal.module->type == MODULE_PERSISTENT) {
ZEND_MAP_PTR_NEW(ce->static_members_table);
} else {
ZEND_MAP_PTR_INIT(ce->static_members_table,
zend_arena_alloc(&CG(arena), sizeof(zval **)));
ZEND_MAP_PTR_SET(ce->static_members_table, NULL);
}
}
} else {
Expand Down
19 changes: 12 additions & 7 deletions Zend/zend_closures.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,8 @@ ZEND_METHOD(Closure, call)
void *ptr;

my_function.op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE;
ptr = emalloc(sizeof(void*) + my_function.op_array.cache_size);
ptr = emalloc(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);
}
}
Expand Down Expand Up @@ -487,6 +485,7 @@ static void zend_closure_free_storage(zend_object *object) /* {{{ */
/* We don't own the static variables of fake closures. */
if (!(closure->func.op_array.fn_flags & ZEND_ACC_FAKE_CLOSURE)) {
zend_destroy_static_vars(&closure->func.op_array);
closure->func.op_array.static_variables = NULL;
}
destroy_op_array(&closure->func.op_array);
} else if (closure->func.type == ZEND_INTERNAL_FUNCTION) {
Expand Down Expand Up @@ -696,7 +695,15 @@ static void zend_create_closure_ex(zval *res, zend_function *func, zend_class_en
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);
closure->func.op_array.static_variables);
} else if (func->op_array.static_variables) {
HashTable *ht = ZEND_MAP_PTR_GET(func->op_array.static_variables_ptr);

if (!ht) {
ht = zend_array_dup(func->op_array.static_variables);
ZEND_MAP_PTR_SET(func->op_array.static_variables_ptr, ht);
}
ZEND_MAP_PTR_INIT(closure->func.op_array.static_variables_ptr, ht);
}

/* Runtime cache is scope-dependent, so we cannot reuse it if the scope changed */
Expand All @@ -722,10 +729,8 @@ static void zend_create_closure_ex(zval *res, zend_function *func, zend_class_en
} else {
/* Otherwise, we use a non-shared runtime cache */
closure->func.op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE;
ptr = emalloc(sizeof(void*) + func->op_array.cache_size);
ptr = emalloc(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(ptr, 0, func->op_array.cache_size);
}
Expand Down
19 changes: 2 additions & 17 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1037,15 +1037,6 @@ static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
}
/* }}} */

void zend_init_static_variables_map_ptr(zend_op_array *op_array)
{
if (op_array->static_variables) {
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr,
zend_arena_alloc(&CG(arena), sizeof(HashTable *)));
ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
}
}

ZEND_API void function_add_ref(zend_function *function) /* {{{ */
{
if (function->type == ZEND_USER_FUNCTION) {
Expand All @@ -1054,10 +1045,8 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
(*op_array->refcount)++;
}

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);

zend_init_static_variables_map_ptr(op_array);
ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL);
}

if (function->common.function_name) {
Expand Down Expand Up @@ -7093,9 +7082,6 @@ static void zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel)
op_array->fn_flags |= ZEND_ACC_PRELOADED;
}

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;
Expand Down Expand Up @@ -7181,7 +7167,6 @@ static void zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel)
zend_do_extended_stmt();
zend_emit_final_return(0);

zend_init_static_variables_map_ptr(op_array);
pass_two(CG(active_op_array));
zend_oparray_context_end(&orig_oparray_context);

Expand Down
1 change: 0 additions & 1 deletion Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,6 @@ ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name);
void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline);

ZEND_API void function_add_ref(zend_function *function);
void zend_init_static_variables_map_ptr(zend_op_array *op_array);
zend_string *zval_make_interned_string(zval *zv);

#define INITIAL_OP_ARRAY_SIZE 64
Expand Down
4 changes: 1 addition & 3 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -3779,10 +3779,8 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
void *ptr;

ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE);
ptr = emalloc(op_array->cache_size + sizeof(void*));
ptr = emalloc(op_array->cache_size);
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(run_time_cache) = RUN_TIME_CACHE(op_array);
Expand Down
25 changes: 4 additions & 21 deletions Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -1525,10 +1525,6 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par
if (ce->type == ZEND_INTERNAL_CLASS &&
ce->info.internal.module->type == MODULE_PERSISTENT) {
ZEND_MAP_PTR_NEW(ce->static_members_table);
} else {
ZEND_MAP_PTR_INIT(ce->static_members_table,
zend_arena_alloc(&CG(arena), sizeof(zval *)));
ZEND_MAP_PTR_SET(ce->static_members_table, NULL);
}
}
}
Expand Down Expand Up @@ -2615,30 +2611,18 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce)
end = p + ce->function_table.nNumUsed;
for (; p != end; p++) {
zend_op_array *op_array, *new_op_array;
void ***run_time_cache_ptr;
size_t alloc_size;

op_array = Z_PTR(p->val);
ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
ZEND_ASSERT(op_array->scope == pce);
ZEND_ASSERT(op_array->prototype == NULL);
alloc_size = sizeof(zend_op_array) + sizeof(void *);
if (op_array->static_variables) {
alloc_size += sizeof(HashTable *);
}
new_op_array = zend_arena_alloc(&CG(arena), alloc_size);
new_op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
Z_PTR(p->val) = new_op_array;
memcpy(new_op_array, op_array, sizeof(zend_op_array));
run_time_cache_ptr = (void***)(new_op_array + 1);
*run_time_cache_ptr = NULL;
new_op_array->fn_flags &= ~ZEND_ACC_IMMUTABLE;
new_op_array->scope = ce;
ZEND_MAP_PTR_INIT(new_op_array->run_time_cache, run_time_cache_ptr);
if (op_array->static_variables) {
HashTable **static_variables_ptr = (HashTable **) (run_time_cache_ptr + 1);
*static_variables_ptr = NULL;
ZEND_MAP_PTR_INIT(new_op_array->static_variables_ptr, static_variables_ptr);
}
ZEND_MAP_PTR_INIT(new_op_array->run_time_cache, NULL);
ZEND_MAP_PTR_INIT(new_op_array->static_variables_ptr, NULL);

zend_update_inherited_handler(constructor);
zend_update_inherited_handler(destructor);
Expand Down Expand Up @@ -2667,8 +2651,7 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce)
ZVAL_COPY_VALUE(dst, src);
}
}
ZEND_MAP_PTR_INIT(ce->static_members_table, zend_arena_alloc(&CG(arena), sizeof(zval *)));
ZEND_MAP_PTR_SET(ce->static_members_table, NULL);
ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);

/* properties_info */
if (!(HT_FLAGS(&ce->properties_info) & HASH_FLAG_UNINITIALIZED)) {
Expand Down
1 change: 0 additions & 1 deletion Zend/zend_language_scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,6 @@ static zend_op_array *zend_compile(int type)
zend_emit_final_return(type == ZEND_USER_FUNCTION);
op_array->line_start = 1;
op_array->line_end = last_lineno;
zend_init_static_variables_map_ptr(op_array);
pass_two(op_array);
zend_oparray_context_end(&original_oparray_context);
zend_file_context_end(&original_file_context);
Expand Down
36 changes: 9 additions & 27 deletions Zend/zend_map_ptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,12 @@
#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
#define 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)
type ZEND_MAP_PTR(name)
#define ZEND_MAP_PTR_OFFSET2PTR(offset) \
((void**)((char*)CG(map_ptr_base) + offset))
#define ZEND_MAP_PTR_PTR2OFFSET(ptr) \
Expand All @@ -45,37 +41,23 @@
ZEND_MAP_PTR(ptr) = zend_map_ptr_new(); \
} while (0)

#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
# define ZEND_MAP_PTR_NEW_OFFSET() \
((uint32_t)(uintptr_t)ZEND_MAP_PTR_PTR2OFFSET(zend_map_ptr_new()))
# define ZEND_MAP_PTR_GET(ptr) \
(*(ZEND_MAP_PTR(ptr)))
# define ZEND_MAP_PTR_GET_IMM(ptr) \
ZEND_MAP_PTR_GET(ptr)
# define ZEND_MAP_PTR_SET(ptr, val) do { \
(*(ZEND_MAP_PTR(ptr))) = (val); \
} while (0)
# define ZEND_MAP_PTR_SET_IMM(ptr, val) \
ZEND_MAP_PTR_SET(ptr, val)
# define ZEND_MAP_PTR_BIASED_BASE(real_base) \
(real_base)
#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
# define ZEND_MAP_PTR_NEW_OFFSET() \
((uint32_t)(uintptr_t)zend_map_ptr_new())
# define ZEND_MAP_PTR_IS_OFFSET(ptr) \
(((uintptr_t)ZEND_MAP_PTR(ptr)) & 1L)
# define ZEND_MAP_PTR_GET(ptr) \
(*(ZEND_MAP_PTR_IS_OFFSET(ptr) ? \
ZEND_MAP_PTR_OFFSET2PTR((uintptr_t)ZEND_MAP_PTR(ptr)) : \
((void**)(ZEND_MAP_PTR(ptr)))))
((ZEND_MAP_PTR_IS_OFFSET(ptr) ? \
ZEND_MAP_PTR_GET_IMM(ptr) : \
((void*)(ZEND_MAP_PTR(ptr)))))
# define ZEND_MAP_PTR_GET_IMM(ptr) \
(*ZEND_MAP_PTR_OFFSET2PTR((uintptr_t)ZEND_MAP_PTR(ptr)))
# define ZEND_MAP_PTR_SET(ptr, val) do { \
void **__p = (void**)(ZEND_MAP_PTR(ptr)); \
if (ZEND_MAP_PTR_IS_OFFSET(ptr)) { \
__p = ZEND_MAP_PTR_OFFSET2PTR((uintptr_t)ZEND_MAP_PTR(ptr)); \
ZEND_MAP_PTR_SET_IMM(ptr, val); \
} else { \
ZEND_MAP_PTR_INIT(ptr, val); \
} \
*__p = (val); \
} while (0)
# define ZEND_MAP_PTR_SET_IMM(ptr, val) do { \
void **__p = ZEND_MAP_PTR_OFFSET2PTR((uintptr_t)ZEND_MAP_PTR(ptr)); \
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_object_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,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);
ZEND_MAP_PTR_INIT(func->run_time_cache, (void***)&dummy);
ZEND_MAP_PTR_INIT(func->run_time_cache, (void**)dummy);
func->scope = fbc->common.scope;
/* reserve space for arguments, local and temporary variables */
func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, 2) : 2;
Expand Down
4 changes: 2 additions & 2 deletions ext/opcache/jit/zend_jit_arm64.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -9244,8 +9244,8 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
| TST_64_WITH_ONE REG2
| beq >1
| MEM_LOAD_OP_ZTS add, ldr, REG2, compiler_globals, map_ptr_base, REG1, TMP1
|1:
| ldr REG2, [REG2]
|1:
}
} else {
if (func) {
Expand All @@ -9255,8 +9255,8 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
| TST_64_WITH_ONE REG2
| beq >1
| MEM_LOAD_OP_ZTS add, ldr, REG2, compiler_globals, map_ptr_base, REG1, TMP1
|1:
| ldr REG2, [REG2]
|1:
}
#else
# error "Unknown ZEND_MAP_PTR_KIND"
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/jit/zend_jit_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static ZEND_COLD void zend_jit_illegal_string_offset(zval *offset)
zend_type_error("Cannot access offset of type %s on string", zend_zval_type_name(offset));
}

static zend_never_inline zend_function* ZEND_FASTCALL _zend_jit_init_func_run_time_cache(const zend_op_array *op_array) /* {{{ */
static zend_never_inline zend_function* ZEND_FASTCALL _zend_jit_init_func_run_time_cache(zend_op_array *op_array) /* {{{ */
{
void **run_time_cache;

Expand Down
Loading