From: Dmitry Stogov Date: Mon, 26 Sep 2016 14:44:28 +0000 (+0300) Subject: Expose information about calls to "fake" closures (created through ReflectionFunction... X-Git-Tag: php-7.2.0alpha1~1232^2~23 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=97628da24aa684883acd124ea3d0ef9a95b595e5;p=php Expose information about calls to "fake" closures (created through ReflectionFunction::getClosure), to allow extra specialization of RETRUN opcode handler. --- diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index bedf022a4b..5645165f5f 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -34,9 +34,6 @@ #define ZEND_CLOSURE_PROPERTY_ERROR() \ zend_throw_error(NULL, "Closure object cannot have properties") -/* reuse bit to mark "fake" closures (it wasn't used for functions before) */ -#define ZEND_ACC_FAKE_CLOSURE ZEND_ACC_INTERFACE - typedef struct _zend_closure { zend_object std; zend_function func; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 1f0773d9a7..506b414583 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -253,6 +253,7 @@ typedef struct _zend_oparray_context { #define ZEND_ACC_CLOSURE 0x100000 +#define ZEND_ACC_FAKE_CLOSURE 0x40 #define ZEND_ACC_GENERATOR 0x800000 #define ZEND_ACC_NO_RT_ARENA 0x80000 @@ -473,6 +474,7 @@ struct _zend_execute_data { #define ZEND_CALL_ALLOCATED (1 << 7) #define ZEND_CALL_GENERATOR (1 << 8) #define ZEND_CALL_DYNAMIC (1 << 9) +#define ZEND_CALL_FAKE_CLOSURE (1 << 10) #define ZEND_CALL_INFO_SHIFT 16 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 545056b88c..48f7a7ef0b 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2651,6 +2651,9 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval * ZEND_ASSERT(GC_TYPE((zend_object*)fbc->common.prototype) == IS_OBJECT); GC_REFCOUNT((zend_object*)fbc->common.prototype)++; call_info |= ZEND_CALL_CLOSURE; + if (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + call_info |= ZEND_CALL_FAKE_CLOSURE; + } } else if (object) { call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 2e299e8515..b315a10513 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -815,9 +815,15 @@ 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_REFCOUNT((zend_object*)func->op_array.prototype)++; - ZEND_ADD_CALL_FLAG(call, ZEND_CALL_CLOSURE); + call_info = ZEND_CALL_CLOSURE; + if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + call_info |= ZEND_CALL_FAKE_CLOSURE; + } + ZEND_ADD_CALL_FLAG(call, call_info); } if (func->type == ZEND_USER_FUNCTION) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index a5b24e27e1..7d46626e4e 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3499,6 +3499,9 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT); GC_REFCOUNT((zend_object*)func->common.prototype)++; call_info |= ZEND_CALL_CLOSURE; + if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + call_info |= ZEND_CALL_FAKE_CLOSURE; + } } else if (object) { call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 2cf5c28c21..e484663cc2 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -5574,6 +5574,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT); GC_REFCOUNT((zend_object*)func->common.prototype)++; call_info |= ZEND_CALL_CLOSURE; + if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + call_info |= ZEND_CALL_FAKE_CLOSURE; + } } else if (object) { call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ @@ -9469,6 +9472,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT); GC_REFCOUNT((zend_object*)func->common.prototype)++; call_info |= ZEND_CALL_CLOSURE; + if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + call_info |= ZEND_CALL_FAKE_CLOSURE; + } } else if (object) { call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ @@ -11425,6 +11431,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT); GC_REFCOUNT((zend_object*)func->common.prototype)++; call_info |= ZEND_CALL_CLOSURE; + if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + call_info |= ZEND_CALL_FAKE_CLOSURE; + } } else if (object) { call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */