summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2018-01-11 22:15:45 +0300
committerDmitry Stogov <dmitry@zend.com>2018-01-11 22:15:45 +0300
commit12c386f5b90387ce373e16cdf74fd4d3155d5aa7 (patch)
tree2103adb0a72abeba6cffd90b96e1ab8392747d1c /Zend
parent0ec631c99676039f7056e939cfd34a7918c1246c (diff)
downloadphp-git-12c386f5b90387ce373e16cdf74fd4d3155d5aa7.tar.gz
Use ZEND_CLOSURE_OBJECT() macro to resolve closure op_array to closure object through address calculation, instead of op_array->prototype reuse. (reapply 781e1573afdc7c336b3577ceabc9c65cafea17e8, now it should be OK).
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_closures.c4
-rw-r--r--Zend/zend_closures.h4
-rw-r--r--Zend/zend_execute.c5
-rw-r--r--Zend/zend_execute_API.c3
-rw-r--r--Zend/zend_generators.c5
-rw-r--r--Zend/zend_vm_def.h13
-rw-r--r--Zend/zend_vm_execute.h23
7 files changed, 27 insertions, 30 deletions
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index 952c018157..af4c474830 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -639,7 +639,7 @@ void zend_register_closure_ce(void) /* {{{ */
static ZEND_NAMED_FUNCTION(zend_closure_internal_handler) /* {{{ */
{
- zend_closure *closure = (zend_closure*)EX(func)->common.prototype;
+ zend_closure *closure = (zend_closure*)ZEND_CLOSURE_OBJECT(EX(func));
closure->orig_internal_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
OBJ_RELEASE((zend_object*)closure);
EX(func) = NULL;
@@ -662,7 +662,6 @@ 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.prototype = (zend_function*)closure;
closure->func.common.fn_flags |= ZEND_ACC_CLOSURE;
if (closure->func.op_array.static_variables) {
closure->func.op_array.static_variables =
@@ -677,7 +676,6 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
}
} else {
memcpy(&closure->func, func, sizeof(zend_internal_function));
- closure->func.common.prototype = (zend_function*)closure;
closure->func.common.fn_flags |= ZEND_ACC_CLOSURE;
/* wrap internal function handler to avoid memory leak */
if (UNEXPECTED(closure->func.internal_function.handler == zend_closure_internal_handler)) {
diff --git a/Zend/zend_closures.h b/Zend/zend_closures.h
index 4c7c041da8..c8b447e498 100644
--- a/Zend/zend_closures.h
+++ b/Zend/zend_closures.h
@@ -24,6 +24,10 @@
BEGIN_EXTERN_C()
+/* This macro depends on zend_closure structure layout */
+#define ZEND_CLOSURE_OBJECT(op_array) \
+ ((zend_object*)((char*)(op_array) - sizeof(zend_object)))
+
void zend_register_closure_ce(void);
void zend_closure_bind_var(zval *closure_zv, zend_string *var_name, zval *var);
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 9b7cbf294d..4de6ba0c07 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -2554,7 +2554,7 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o
OBJ_RELEASE(Z_OBJ(call->This));
}
if (call->func->common.fn_flags & ZEND_ACC_CLOSURE) {
- zend_object_release((zend_object *) call->func->common.prototype);
+ zend_object_release(ZEND_CLOSURE_OBJECT(call->func));
} else if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
zend_string_release(call->func->common.function_name);
zend_free_trampoline(call->func);
@@ -2735,8 +2735,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval *
if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
- ZEND_ASSERT(GC_TYPE((zend_object*)fbc->common.prototype) == IS_OBJECT);
- GC_ADDREF((zend_object*)fbc->common.prototype);
+ GC_ADDREF(ZEND_CLOSURE_OBJECT(fbc));
call_info |= ZEND_CALL_CLOSURE;
if (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE;
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 61d92914bb..f66bd66304 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -776,8 +776,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
uint32_t call_info;
- ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT);
- GC_ADDREF((zend_object*)func->op_array.prototype);
+ GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
call_info = ZEND_CALL_CLOSURE;
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE;
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 755300f92b..6c2495d69d 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -24,6 +24,7 @@
#include "zend_interfaces.h"
#include "zend_exceptions.h"
#include "zend_generators.h"
+#include "zend_closures.h"
ZEND_API zend_class_entry *zend_ce_generator;
ZEND_API zend_class_entry *zend_ce_ClosedGeneratorException;
@@ -145,7 +146,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
/* Free closure object */
if (EX_CALL_INFO() & ZEND_CALL_CLOSURE) {
- OBJ_RELEASE((zend_object *) EX(func)->common.prototype);
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
}
/* Free GC buffer. GC for closed generators doesn't need an allocated buffer */
@@ -335,7 +336,7 @@ static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* {
ZVAL_OBJ(gc_buffer++, Z_OBJ(execute_data->This));
}
if (EX_CALL_INFO() & ZEND_CALL_CLOSURE) {
- ZVAL_OBJ(gc_buffer++, (zend_object *) EX(func)->common.prototype);
+ ZVAL_OBJ(gc_buffer++, ZEND_CLOSURE_OBJECT(EX(func)));
}
if (generator->node.children == 0) {
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index cd0a769f34..9627c045d3 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -2374,7 +2374,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
}
OBJ_RELEASE(object);
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
- OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype);
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
}
EG(vm_stack_top) = (zval*)execute_data;
execute_data = EX(prev_execute_data);
@@ -2405,7 +2405,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
}
OBJ_RELEASE(object);
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
- OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype);
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
}
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
@@ -2447,7 +2447,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
}
EG(current_execute_data) = EX(prev_execute_data);
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
- OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype);
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
}
ZEND_VM_RETURN();
} else /* if (call_kind == ZEND_CALL_TOP_CODE) */ {
@@ -3356,8 +3356,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
}
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
- ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT);
- GC_ADDREF((zend_object*)func->common.prototype);
+ GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
call_info |= ZEND_CALL_CLOSURE;
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE;
@@ -3370,7 +3369,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
FREE_OP2();
if ((OP2_TYPE & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
if (call_info & ZEND_CALL_CLOSURE) {
- zend_object_release((zend_object*)func->common.prototype);
+ zend_object_release(ZEND_CLOSURE_OBJECT(func));
}
if (call_info & ZEND_CALL_RELEASE_THIS) {
zend_object_release(object);
@@ -4532,7 +4531,7 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY, NUM)
}
zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args)));
if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
- OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func));
}
if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
OBJ_RELEASE(Z_OBJ(EX(call)->This));
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 8747a299e8..3845f454da 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -457,7 +457,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
}
OBJ_RELEASE(object);
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
- OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype);
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
}
EG(vm_stack_top) = (zval*)execute_data;
execute_data = EX(prev_execute_data);
@@ -488,7 +488,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
}
OBJ_RELEASE(object);
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
- OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype);
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
}
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
@@ -530,7 +530,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
}
EG(current_execute_data) = EX(prev_execute_data);
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
- OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype);
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
}
ZEND_VM_RETURN();
} else /* if (call_kind == ZEND_CALL_TOP_CODE) */ {
@@ -1361,7 +1361,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O
}
zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args)));
if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
- OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func));
}
if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
OBJ_RELEASE(Z_OBJ(EX(call)->This));
@@ -5585,8 +5585,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
}
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
- ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT);
- GC_ADDREF((zend_object*)func->common.prototype);
+ GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
call_info |= ZEND_CALL_CLOSURE;
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE;
@@ -5598,7 +5597,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
if ((IS_CONST & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
if (call_info & ZEND_CALL_CLOSURE) {
- zend_object_release((zend_object*)func->common.prototype);
+ zend_object_release(ZEND_CLOSURE_OBJECT(func));
}
if (call_info & ZEND_CALL_RELEASE_THIS) {
zend_object_release(object);
@@ -7796,8 +7795,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
}
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
- ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT);
- GC_ADDREF((zend_object*)func->common.prototype);
+ GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
call_info |= ZEND_CALL_CLOSURE;
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE;
@@ -7810,7 +7808,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
zval_ptr_dtor_nogc(free_op2);
if (((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
if (call_info & ZEND_CALL_CLOSURE) {
- zend_object_release((zend_object*)func->common.prototype);
+ zend_object_release(ZEND_CLOSURE_OBJECT(func));
}
if (call_info & ZEND_CALL_RELEASE_THIS) {
zend_object_release(object);
@@ -10933,8 +10931,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
}
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
- ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT);
- GC_ADDREF((zend_object*)func->common.prototype);
+ GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
call_info |= ZEND_CALL_CLOSURE;
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE;
@@ -10946,7 +10943,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
if ((IS_CV & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
if (call_info & ZEND_CALL_CLOSURE) {
- zend_object_release((zend_object*)func->common.prototype);
+ zend_object_release(ZEND_CLOSURE_OBJECT(func));
}
if (call_info & ZEND_CALL_RELEASE_THIS) {
zend_object_release(object);