1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Expose information about calls to "fake" closures (created through ReflectionFunction::getClosure), to allow extra specialization of RETRUN opcode handler.

This commit is contained in:
Dmitry Stogov
2016-09-26 17:44:28 +03:00
parent 558f684e60
commit 97628da24a
6 changed files with 24 additions and 4 deletions

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

View 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

View 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 */

View 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) {

View 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 */

View 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 */