From cc900edd775dc87e74b5412e7cea324a60a01e74 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 11 Apr 2019 02:08:32 +0300 Subject: Simplify call frame initialization --- Zend/zend_compile.h | 48 ++-- Zend/zend_execute.c | 31 ++- Zend/zend_execute.h | 21 +- Zend/zend_execute_API.c | 17 +- Zend/zend_generators.c | 5 +- Zend/zend_types.h | 1 - Zend/zend_vm_def.h | 73 +++--- Zend/zend_vm_execute.h | 513 +++++++++++++++++++------------------ Zend/zend_vm_execute.skl | 13 +- ext/opcache/jit/zend_jit_helpers.c | 4 +- ext/opcache/jit/zend_jit_x86.dasc | 8 +- sapi/fpm/fpm/fpm_php_trace.c | 4 +- 12 files changed, 393 insertions(+), 345 deletions(-) diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 3aa5e6c113..fefe566c58 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -497,25 +497,31 @@ struct _zend_execute_data { #endif }; -#define ZEND_CALL_FUNCTION (0 << 0) -#define ZEND_CALL_CODE (1 << 0) -#define ZEND_CALL_NESTED (0 << 1) -#define ZEND_CALL_TOP (1 << 1) -#define ZEND_CALL_FREE_EXTRA_ARGS (1 << 2) -#define ZEND_CALL_CTOR (1 << 3) -#define ZEND_CALL_HAS_SYMBOL_TABLE (1 << 4) -#define ZEND_CALL_CLOSURE (1 << 5) -#define ZEND_CALL_RELEASE_THIS (1 << 6) -#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_SEND_ARG_BY_REF (1 << 11) - -#define ZEND_CALL_INFO_SHIFT 16 +#define ZEND_CALL_HAS_THIS IS_OBJECT_EX + +/* Top 16 bits of Z_TYPE_INFO(EX(This)) are used as call_info flags */ +#define ZEND_CALL_FUNCTION (0 << 16) +#define ZEND_CALL_CODE (1 << 16) +#define ZEND_CALL_NESTED (0 << 17) +#define ZEND_CALL_TOP (1 << 17) +#define ZEND_CALL_ALLOCATED (1 << 18) +#define ZEND_CALL_FREE_EXTRA_ARGS (1 << 19) +#define ZEND_CALL_HAS_SYMBOL_TABLE (1 << 20) +#define ZEND_CALL_RELEASE_THIS (1 << 21) +#define ZEND_CALL_CTOR (1 << 22) +#define ZEND_CALL_CLOSURE (1 << 23) +#define ZEND_CALL_FAKE_CLOSURE (1 << 24) +#define ZEND_CALL_GENERATOR (1 << 25) +#define ZEND_CALL_DYNAMIC (1 << 26) +#define ZEND_CALL_SEND_ARG_BY_REF (1 << 31) + +#define ZEND_CALL_NESTED_FUNCTION (ZEND_CALL_FUNCTION | ZEND_CALL_NESTED) +#define ZEND_CALL_NESTED_CODE (ZEND_CALL_CODE | ZEND_CALL_NESTED) +#define ZEND_CALL_TOP_FUNCTION (ZEND_CALL_TOP | ZEND_CALL_FUNCTION) +#define ZEND_CALL_TOP_CODE (ZEND_CALL_CODE | ZEND_CALL_TOP) #define ZEND_CALL_INFO(call) \ - (Z_TYPE_INFO((call)->This) >> ZEND_CALL_INFO_SHIFT) + Z_TYPE_INFO((call)->This) #define ZEND_CALL_KIND_EX(call_info) \ (call_info & (ZEND_CALL_CODE | ZEND_CALL_TOP)) @@ -523,16 +529,12 @@ struct _zend_execute_data { #define ZEND_CALL_KIND(call) \ ZEND_CALL_KIND_EX(ZEND_CALL_INFO(call)) -#define ZEND_SET_CALL_INFO(call, object, info) do { \ - Z_TYPE_INFO((call)->This) = ((object) ? IS_OBJECT_EX : IS_UNDEF) | ((info) << ZEND_CALL_INFO_SHIFT); \ - } while (0) - #define ZEND_ADD_CALL_FLAG_EX(call_info, flag) do { \ - call_info |= ((flag) << ZEND_CALL_INFO_SHIFT); \ + call_info |= (flag); \ } while (0) #define ZEND_DEL_CALL_FLAG_EX(call_info, flag) do { \ - call_info &= ~((flag) << ZEND_CALL_INFO_SHIFT); \ + call_info &= ~(flag); \ } while (0) #define ZEND_ADD_CALL_FLAG(call, flag) do { \ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c596be73a6..1d626a0def 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3854,13 +3854,14 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s } return zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC, - fbc, num_args, called_scope, NULL); + fbc, num_args, called_scope); } /* }}} */ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_object *function, uint32_t num_args) /* {{{ */ { zend_function *fbc; + void *object_or_called_scope; zend_class_entry *called_scope; zend_object *object; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; @@ -3868,6 +3869,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_o if (EXPECTED(function->handlers->get_closure) && EXPECTED(function->handlers->get_closure(function, &called_scope, &fbc, &object) == SUCCESS)) { + object_or_called_scope = called_scope; if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(fbc)); @@ -3875,9 +3877,14 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_o if (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { call_info |= ZEND_CALL_FAKE_CLOSURE; } + if (object) { + call_info |= ZEND_CALL_HAS_THIS; + object_or_called_scope = object; + } } else if (object) { - call_info |= ZEND_CALL_RELEASE_THIS; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; GC_ADDREF(object); /* For $this pointer */ + object_or_called_scope = object; } } else { zend_throw_error(NULL, "Function name must be a string"); @@ -3889,15 +3896,14 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_o } return zend_vm_stack_push_call_frame(call_info, - fbc, num_args, called_scope, object); + fbc, num_args, object_or_called_scope); } /* }}} */ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_array *function, uint32_t num_args) /* {{{ */ { zend_function *fbc; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; if (zend_hash_num_elements(function) == 2) { @@ -3924,8 +3930,8 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar } if (Z_TYPE_P(obj) == IS_STRING) { - object = NULL; - called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + zend_class_entry *called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(called_scope == NULL)) { return NULL; } @@ -3945,9 +3951,9 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar zend_non_static_method_call(fbc); return NULL; } + object_or_called_scope = called_scope; } else { - called_scope = Z_OBJCE_P(obj); - object = Z_OBJ_P(obj); + zend_object *object = Z_OBJ_P(obj); fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL); if (UNEXPECTED(fbc == NULL)) { @@ -3958,10 +3964,11 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { - object = NULL; + object_or_called_scope = object->ce; } else { - call_info |= ZEND_CALL_RELEASE_THIS; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; GC_ADDREF(object); /* For $this pointer */ + object_or_called_scope = object; } } } else { @@ -3974,7 +3981,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar } return zend_vm_stack_push_call_frame(call_info, - fbc, num_args, called_scope, object); + fbc, num_args, object_or_called_scope); } /* }}} */ diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 78b33171df..4abdaca9fd 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -206,20 +206,15 @@ ZEND_API void zend_vm_stack_init_ex(size_t page_size); ZEND_API void zend_vm_stack_destroy(void); ZEND_API void* zend_vm_stack_extend(size_t size); -static zend_always_inline void zend_vm_init_call_frame(zend_execute_data *call, uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object) +static zend_always_inline void zend_vm_init_call_frame(zend_execute_data *call, uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) { call->func = func; - if (object) { - Z_OBJ(call->This) = object; - ZEND_SET_CALL_INFO(call, 1, call_info); - } else { - Z_CE(call->This) = called_scope; - ZEND_SET_CALL_INFO(call, 0, call_info); - } + Z_PTR(call->This) = object_or_called_scope; + ZEND_CALL_INFO(call) = call_info; ZEND_CALL_NUM_ARGS(call) = num_args; } -static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object) +static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) { zend_execute_data *call = (zend_execute_data*)EG(vm_stack_top); @@ -228,11 +223,11 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(ui if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) { call = (zend_execute_data*)zend_vm_stack_extend(used_stack); ZEND_ASSERT_VM_STACK_GLOBAL; - zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, called_scope, object); + zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, object_or_called_scope); return call; } else { EG(vm_stack_top) = (zval*)((char*)call + used_stack); - zend_vm_init_call_frame(call, call_info, func, num_args, called_scope, object); + zend_vm_init_call_frame(call, call_info, func, num_args, object_or_called_scope); return call; } } @@ -247,12 +242,12 @@ static zend_always_inline uint32_t zend_vm_calc_used_stack(uint32_t num_args, ze return used_stack * sizeof(zval); } -static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object) +static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) { uint32_t used_stack = zend_vm_calc_used_stack(num_args, func); return zend_vm_stack_push_call_frame_ex(used_stack, call_info, - func, num_args, called_scope, object); + func, num_args, object_or_called_scope); } static zend_always_inline void zend_vm_stack_free_extra_args_ex(uint32_t call_info, zend_execute_data *call) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 07113bf69e..0c55abaa2e 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -634,6 +634,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / zend_execute_data *call, dummy_execute_data; zend_fcall_info_cache fci_cache_local; zend_function *func; + uint32_t call_info; + void *object_or_called_scope; ZVAL_UNDEF(fci->retval); @@ -695,11 +697,18 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } func = fci_cache->function_handler; - fci->object = (func->common.fn_flags & ZEND_ACC_STATIC) ? - NULL : fci_cache->object; + if ((func->common.fn_flags & ZEND_ACC_STATIC) || !fci_cache->object) { + fci->object = NULL; + object_or_called_scope = fci_cache->called_scope; + call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC; + } else { + fci->object = fci_cache->object; + object_or_called_scope = fci->object; + call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_HAS_THIS; + } - call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC, - func, fci->param_count, fci_cache->called_scope, fci->object); + call = zend_vm_stack_push_call_frame(call_info, + func, fci->param_count, object_or_called_scope); if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_DEPRECATED)) { zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 958cf94202..841489eca7 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -40,10 +40,7 @@ ZEND_API void zend_generator_restore_call_stack(zend_generator *generator) /* {{ (ZEND_CALL_INFO(call) & ~ZEND_CALL_ALLOCATED), call->func, ZEND_CALL_NUM_ARGS(call), - (Z_TYPE(call->This) == IS_UNDEF) ? - (zend_class_entry*)Z_OBJ(call->This) : NULL, - (Z_TYPE(call->This) != IS_UNDEF) ? - Z_OBJ(call->This) : NULL); + Z_PTR(call->This)); memcpy(((zval*)new_call) + ZEND_CALL_FRAME_SLOT, ((zval*)call) + ZEND_CALL_FRAME_SLOT, ZEND_CALL_NUM_ARGS(call) * sizeof(zval)); new_call->prev_execute_data = prev_call; prev_call = new_call; diff --git a/Zend/zend_types.h b/Zend/zend_types.h index f1e959f0e2..6ba488d88b 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -201,7 +201,6 @@ struct _zval_struct { zend_uchar type, /* active type */ zend_uchar type_flags, union { - uint16_t call_info; /* call info for EX(This) */ uint16_t extra; /* not further specified */ } u) } v; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 0a69450326..917cf16f24 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3507,27 +3507,29 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, FREE_OP2(); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; FREE_OP1(); if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (OP1_TYPE == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ FREE_OP1(); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -3539,7 +3541,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -3639,31 +3641,30 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (OP1_TYPE == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (OP1_TYPE == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -3691,7 +3692,7 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT) CACHE_PTR(opline->result.num, fbc); } call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -3763,8 +3764,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; @@ -3773,8 +3773,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { ZEND_ASSERT(!error); func = fcc.function_handler; - called_scope = fcc.called_scope; - object = fcc.object; + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -3782,9 +3781,14 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) 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_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } FREE_OP2(); @@ -3793,7 +3797,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) zend_object_release(ZEND_CLOSURE_OBJECT(func)); } if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -3809,7 +3813,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -3842,7 +3846,7 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT) } call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -3873,7 +3877,7 @@ ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT) call = zend_vm_stack_push_call_frame_ex( opline->op1.num, ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -4357,7 +4361,7 @@ ZEND_VM_HANDLER(41, ZEND_GENERATOR_CREATE, ANY, ANY) gen_execute_data->return_value = (zval*)generator; call_info = Z_TYPE_INFO(EX(This)); if ((call_info & Z_TYPE_MASK) == IS_OBJECT - && (!(call_info & ((ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS) << ZEND_CALL_INFO_SHIFT)) + && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS)) /* Bug #72523 */ || UNEXPECTED(zend_execute_ex != execute_ex))) { ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS); @@ -5345,17 +5349,16 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -5764,10 +5767,10 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL) new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index fa3dac4aa6..0138bac77f 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1459,7 +1459,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_CREATE_SPEC_HANDLER( gen_execute_data->return_value = (zval*)generator; call_info = Z_TYPE_INFO(EX(This)); if ((call_info & Z_TYPE_MASK) == IS_OBJECT - && (!(call_info & ((ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS) << ZEND_CALL_INFO_SHIFT)) + && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS)) /* Bug #72523 */ || UNEXPECTED(zend_execute_ex != execute_ex))) { ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS); @@ -2307,7 +2307,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME CACHE_PTR(opline->result.num, fbc); } call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -2396,7 +2396,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_N } call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -2427,7 +2427,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CO call = zend_vm_stack_push_call_frame_ex( opline->op1.num, ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -3470,10 +3470,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); @@ -5445,26 +5445,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -5476,7 +5478,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -5576,31 +5578,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_CONST == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -5615,8 +5616,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; @@ -5625,8 +5625,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { ZEND_ASSERT(!error); func = fcc.function_handler; - called_scope = fcc.called_scope; - object = fcc.object; + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -5634,9 +5633,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS 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_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } if ((IS_CONST & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { @@ -5644,7 +5648,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS zend_object_release(ZEND_CLOSURE_OBJECT(func)); } if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -5660,7 +5664,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -7703,26 +7707,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -7734,7 +7740,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -7834,31 +7840,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_CONST == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -7873,8 +7878,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; @@ -7883,8 +7887,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { ZEND_ASSERT(!error); func = fcc.function_handler; - called_scope = fcc.called_scope; - object = fcc.object; + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -7892,9 +7895,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV 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_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } zval_ptr_dtor_nogc(free_op2); @@ -7903,7 +7911,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV zend_object_release(ZEND_CLOSURE_OBJECT(func)); } if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -7919,7 +7927,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -8880,7 +8888,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -8980,31 +8988,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_CONST == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -9113,17 +9120,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER( /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -10656,26 +10662,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -10687,7 +10695,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -10787,31 +10795,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_CONST == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -10826,8 +10833,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; @@ -10836,8 +10842,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { ZEND_ASSERT(!error); func = fcc.function_handler; - called_scope = fcc.called_scope; - object = fcc.object; + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -10845,9 +10850,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H 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_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } if ((IS_CV & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { @@ -10855,7 +10865,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H zend_object_release(ZEND_CLOSURE_OBJECT(func)); } if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -10871,7 +10881,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -12970,10 +12980,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); @@ -14404,27 +14414,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; zval_ptr_dtor_nogc(free_op1); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ zval_ptr_dtor_nogc(free_op1); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -16066,27 +16078,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; zval_ptr_dtor_nogc(free_op1); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ zval_ptr_dtor_nogc(free_op1); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -17756,27 +17770,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; zval_ptr_dtor_nogc(free_op1); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ zval_ptr_dtor_nogc(free_op1); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -24744,7 +24760,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -24844,31 +24860,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_VAR == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -27534,7 +27549,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -27634,31 +27649,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_VAR == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -29220,7 +29234,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -29320,31 +29334,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_VAR == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -29453,17 +29466,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -32032,7 +32044,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -32132,31 +32144,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_VAR == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -34413,26 +34424,28 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -34444,7 +34457,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -34544,31 +34557,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -36479,26 +36491,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -36510,7 +36524,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -36610,31 +36624,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -37059,7 +37072,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -37159,31 +37172,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -37292,17 +37304,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -39187,26 +39198,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -39218,7 +39231,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -39318,31 +39331,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); HANDLE_EXCEPTION(); } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -40712,10 +40724,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); @@ -44754,26 +44766,28 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -48982,26 +48996,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -55178,26 +55194,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -66622,13 +66640,22 @@ zend_leave_helper_SPEC_LABEL: ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value) { zend_execute_data *execute_data; + void *object_or_called_scope; + uint32_t call_info; if (EG(exception) != NULL) { return; } - execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, - (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data))); + object_or_called_scope = zend_get_this_object(EG(current_execute_data)); + if (EXPECTED(!object_or_called_scope)) { + object_or_called_scope = zend_get_called_scope(EG(current_execute_data)); + call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE; + } else { + call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE | ZEND_CALL_HAS_THIS; + } + execute_data = zend_vm_stack_push_call_frame(call_info, + (zend_function*)op_array, 0, object_or_called_scope); if (EG(current_execute_data)) { execute_data->symbol_table = zend_rebuild_symbol_table(); } else { diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 30f0017cbd..5e6e98bb24 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -24,13 +24,22 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *ex) ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value) { zend_execute_data *execute_data; + void *object_or_called_scope; + uint32_t call_info; if (EG(exception) != NULL) { return; } - execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, - (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data))); + object_or_called_scope = zend_get_this_object(EG(current_execute_data)); + if (EXPECTED(!object_or_called_scope)) { + object_or_called_scope = zend_get_called_scope(EG(current_execute_data)); + call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE; + } else { + call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE | ZEND_CALL_HAS_THIS; + } + execute_data = zend_vm_stack_push_call_frame(call_info, + (zend_function*)op_array, 0, object_or_called_scope); if (EG(current_execute_data)) { execute_data->symbol_table = zend_rebuild_symbol_table(); } else { diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index c2cac6f7d2..8df29adce0 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -61,14 +61,14 @@ static zend_execute_data* ZEND_FASTCALL zend_jit_extend_stack_helper(uint32_t us { zend_execute_data *call = (zend_execute_data*)zend_vm_stack_extend(used_stack); call->func = fbc; - ZEND_SET_CALL_INFO(call, 0, ZEND_CALL_NESTED_FUNCTION|ZEND_CALL_ALLOCATED); + ZEND_CALL_INFO(call) = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_ALLOCATED; return call; } static zend_execute_data* ZEND_FASTCALL zend_jit_int_extend_stack_helper(uint32_t used_stack) { zend_execute_data *call = (zend_execute_data*)zend_vm_stack_extend(used_stack); - ZEND_SET_CALL_INFO(call, 0, ZEND_CALL_NESTED_FUNCTION|ZEND_CALL_ALLOCATED); + ZEND_CALL_INFO(call) = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_ALLOCATED; return call; } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 01f88c031c..6f230dc678 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -7077,7 +7077,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, zen } | // zend_vm_init_call_frame(call, call_info, func, num_args, called_scope, object); | // ZEND_SET_CALL_INFO(call, 0, call_info); - | mov dword EX:RX->This.u1.type_info, (IS_UNDEF | (ZEND_CALL_NESTED_FUNCTION << ZEND_CALL_INFO_SHIFT)) + | mov dword EX:RX->This.u1.type_info, (IS_UNDEF | ZEND_CALL_NESTED_FUNCTION) | // call->func = func; #ifdef _WIN32 if (0) { @@ -7726,7 +7726,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, zend_op_ar if (opline->opcode == ZEND_DO_FCALL) { // TODO: optimize ??? | // if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) - | test byte [RX + offsetof(zend_execute_data, This.u1.type_info) + 2], ZEND_CALL_RELEASE_THIS + | test byte [RX + offsetof(zend_execute_data, This.u1.type_info) + 2], (ZEND_CALL_RELEASE_THIS >> 16) | jnz >1 |.cold_code |1: @@ -7750,7 +7750,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, zend_op_ar } | // zend_vm_stack_free_call_frame(call); - | test byte [RX + offsetof(zend_execute_data, This.u1.type_info) + 2], ZEND_CALL_ALLOCATED + | test byte [RX + offsetof(zend_execute_data, This.u1.type_info) + 2], (ZEND_CALL_ALLOCATED >> 16) | jnz >1 |.cold_code |1: @@ -8591,7 +8591,7 @@ static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, zend_op_ return 0; } - | movzx FCARG1d, word [FP + offsetof(zend_execute_data, This.u1.type_info) + 2] + | mov FCARG1d, dword [FP + offsetof(zend_execute_data, This.u1.type_info)] | test FCARG1d, (ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_FAKE_CLOSURE) | jnz ->leave_function_handler diff --git a/sapi/fpm/fpm/fpm_php_trace.c b/sapi/fpm/fpm/fpm_php_trace.c index 3174eef2fb..cfdcf65094 100644 --- a/sapi/fpm/fpm/fpm_php_trace.c +++ b/sapi/fpm/fpm/fpm_php_trace.c @@ -99,9 +99,9 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog) /* {{{ * return -1; } - if (ZEND_CALL_KIND_EX((*call_info) >> ZEND_CALL_INFO_SHIFT) == ZEND_CALL_TOP_CODE) { + if (ZEND_CALL_KIND_EX(*call_info) == ZEND_CALL_TOP_CODE) { return 0; - } else if (ZEND_CALL_KIND_EX(*(call_info) >> ZEND_CALL_INFO_SHIFT) == ZEND_CALL_NESTED_CODE) { + } else if (ZEND_CALL_KIND_EX(*call_info) == ZEND_CALL_NESTED_CODE) { memcpy(buf, "[INCLUDE_OR_EVAL]", sizeof("[INCLUDE_OR_EVAL]")); } else { ZEND_ASSERT(0); -- cgit v1.2.1