]> granicus.if.org Git - php/commitdiff
Expose information about calls to "fake" closures (created through ReflectionFunction...
authorDmitry Stogov <dmitry@zend.com>
Mon, 26 Sep 2016 14:44:28 +0000 (17:44 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 26 Sep 2016 14:44:28 +0000 (17:44 +0300)
Zend/zend_closures.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute_API.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index bedf022a4b416346c9b8db5bfc218c940da3821c..5645165f5f656f5356b6a0f770a81675b81f9686 100644 (file)
@@ -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;
index 1f0773d9a7abfc42aa30199748b1d304c15c4c3f..506b414583de2d27d01e094b508f1a76b4b6cf3c 100644 (file)
@@ -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
 
index 545056b88c9b9e03519508061484665b80f95387..48f7a7ef0baea076852c17fb1c98f26b401e3190 100644 (file)
@@ -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 */
index 2e299e8515815fc93bc66bcdd81c8a524b9a8634..b315a105137657a1828f7d77288c647ea6f9d198 100644 (file)
@@ -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) {
index a5b24e27e17df9909542b15227e0f03b3e06d844..7d46626e4e4cf07a507c394e42e65a52025f5b96 100644 (file)
@@ -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 */
index 2cf5c28c21624e32aa4f87cf961d55ef2ad2905d..e484663cc2b7a1967768dadbd9d405a5d4972e58 100644 (file)
@@ -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 */