@@ -2401,12 +2401,15 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
2401
2401
if (UNEXPECTED (call_info & ZEND_CALL_CLOSURE )) {
2402
2402
OBJ_RELEASE ((zend_object * )old_execute_data -> func -> op_array .prototype );
2403
2403
}
2404
- object = Z_OBJ (old_execute_data -> This );
2405
- zend_vm_stack_free_call_frame (old_execute_data );
2406
-
2407
- if (object ) {
2404
+ if (call_info & ZEND_CALL_RELEASE_THIS ) {
2405
+ object = Z_OBJ (old_execute_data -> This );
2406
+ #if 0
2408
2407
if (UNEXPECTED (EG (exception ) != NULL ) && (EX (opline )-> op1 .num & ZEND_CALL_CTOR )) {
2409
2408
if (!(EX (opline )-> op1 .num & ZEND_CALL_CTOR_RESULT_UNUSED )) {
2409
+ #else
2410
+ if (UNEXPECTED (EG (exception ) != NULL ) && (call_info & ZEND_CALL_CTOR )) {
2411
+ if (!(call_info & ZEND_CALL_CTOR_RESULT_UNUSED )) {
2412
+ #endif
2410
2413
GC_REFCOUNT (object )-- ;
2411
2414
}
2412
2415
if (GC_REFCOUNT (object ) == 1 ) {
@@ -2417,6 +2420,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
2417
2420
}
2418
2421
EG (scope ) = EX (func )-> op_array .scope ;
2419
2422
2423
+ zend_vm_stack_free_call_frame (old_execute_data );
2424
+
2420
2425
if (UNEXPECTED (EG (exception ) != NULL )) {
2421
2426
const zend_op * old_opline = EX (opline );
2422
2427
zend_throw_exception_internal (NULL );
@@ -2882,6 +2887,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
2882
2887
zend_class_entry * called_scope ;
2883
2888
zend_object * obj ;
2884
2889
zend_execute_data * call ;
2890
+ uint32_t call_info ;
2885
2891
2886
2892
SAVE_OPLINE ();
2887
2893
@@ -2959,13 +2965,15 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
2959
2965
}
2960
2966
}
2961
2967
2968
+ call_info = ZEND_CALL_NESTED_FUNCTION ;
2962
2969
if (UNEXPECTED ((fbc -> common .fn_flags & ZEND_ACC_STATIC ) != 0 )) {
2963
2970
obj = NULL ;
2964
- } else {
2971
+ } else if (OP1_TYPE & (IS_VAR |IS_TMP_VAR )) {
2972
+ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS ;
2965
2973
GC_REFCOUNT (obj )++ ; /* For $this pointer */
2966
2974
}
2967
2975
2968
- call = zend_vm_stack_push_call_frame (ZEND_CALL_NESTED_FUNCTION ,
2976
+ call = zend_vm_stack_push_call_frame (call_info ,
2969
2977
fbc , opline -> extended_value , called_scope , obj );
2970
2978
call -> prev_execute_data = EX (call );
2971
2979
EX (call ) = call ;
@@ -3070,7 +3078,6 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
3070
3078
if (!(fbc -> common .fn_flags & ZEND_ACC_STATIC )) {
3071
3079
if (Z_OBJ (EX (This )) && instanceof_function (Z_OBJCE (EX (This )), ce )) {
3072
3080
object = Z_OBJ (EX (This ));
3073
- GC_REFCOUNT (object )++ ;
3074
3081
}
3075
3082
if (!object ) {
3076
3083
if (fbc -> common .fn_flags & ZEND_ACC_ALLOW_STATIC ) {
@@ -3175,9 +3182,6 @@ ZEND_VM_C_LABEL(try_function_name):
3175
3182
EXPECTED (Z_TYPE_P (function_name ) == IS_OBJECT ) &&
3176
3183
Z_OBJ_HANDLER_P (function_name , get_closure ) &&
3177
3184
Z_OBJ_HANDLER_P (function_name , get_closure )(function_name , & called_scope , & fbc , & object ) == SUCCESS ) {
3178
- if (object ) {
3179
- GC_REFCOUNT (object )++ ;
3180
- }
3181
3185
if (fbc -> common .fn_flags & ZEND_ACC_CLOSURE ) {
3182
3186
/* Delay closure destruction until its invocation */
3183
3187
ZEND_ASSERT (GC_TYPE (fbc -> common .prototype ) == IS_OBJECT );
@@ -3262,6 +3266,7 @@ ZEND_VM_C_LABEL(try_function_name):
3262
3266
if ((fbc -> common .fn_flags & ZEND_ACC_STATIC ) != 0 ) {
3263
3267
object = NULL ;
3264
3268
} else {
3269
+ call_info |= ZEND_CALL_RELEASE_THIS ;
3265
3270
GC_REFCOUNT (object )++ ; /* For $this pointer */
3266
3271
}
3267
3272
}
@@ -3318,6 +3323,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
3318
3323
called_scope = fcc .called_scope ;
3319
3324
object = fcc .object ;
3320
3325
if (object ) {
3326
+ call_info |= ZEND_CALL_RELEASE_THIS ;
3321
3327
GC_REFCOUNT (object )++ ; /* For $this pointer */
3322
3328
} else if (func -> common .scope &&
3323
3329
!(func -> common .fn_flags & ZEND_ACC_STATIC )) {
@@ -3595,7 +3601,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
3595
3601
USE_OPLINE
3596
3602
zend_execute_data * call = EX (call );
3597
3603
zend_function * fbc = call -> func ;
3598
- zend_object * object = Z_OBJ ( call -> This ) ;
3604
+ zend_object * object ;
3599
3605
zval * ret ;
3600
3606
3601
3607
SAVE_OPLINE ();
@@ -3628,8 +3634,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
3628
3634
} else {
3629
3635
zend_vm_stack_free_args (call );
3630
3636
}
3631
-
3632
- zend_vm_stack_free_call_frame (call );
3633
3637
} else {
3634
3638
ret = NULL ;
3635
3639
call -> symbol_table = NULL ;
@@ -3670,7 +3674,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
3670
3674
if (UNEXPECTED (EG (exception ) != NULL )) {
3671
3675
EG (current_execute_data ) = call -> prev_execute_data ;
3672
3676
zend_vm_stack_free_args (call );
3673
- zend_vm_stack_free_call_frame (call );
3674
3677
if (RETURN_VALUE_USED (opline )) {
3675
3678
ZVAL_UNDEF (EX_VAR (opline -> result .var ));
3676
3679
}
@@ -3704,7 +3707,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
3704
3707
3705
3708
EG (current_execute_data ) = call -> prev_execute_data ;
3706
3709
zend_vm_stack_free_args (call );
3707
- zend_vm_stack_free_call_frame (call );
3708
3710
3709
3711
if (!RETURN_VALUE_USED (opline )) {
3710
3712
zval_ptr_dtor (EX_VAR (opline -> result .var ));
@@ -3721,6 +3723,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
3721
3723
ZVAL_NULL (EX_VAR (opline -> result .var ));
3722
3724
3723
3725
/* Not sure what should be done here if it's a static method */
3726
+ object = Z_OBJ (call -> This );
3724
3727
if (EXPECTED (object != NULL )) {
3725
3728
call -> prev_execute_data = execute_data ;
3726
3729
EG (current_execute_data ) = call ;
@@ -3744,8 +3747,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
3744
3747
3745
3748
zend_vm_stack_free_args (call );
3746
3749
3747
- zend_vm_stack_free_call_frame (call );
3748
-
3749
3750
if (fbc -> type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ) {
3750
3751
zend_string_release (fbc -> common .function_name );
3751
3752
}
@@ -3759,9 +3760,15 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
3759
3760
}
3760
3761
3761
3762
ZEND_VM_C_LABEL (fcall_end_change_scope ):
3762
- if (object ) {
3763
+ if (ZEND_CALL_INFO (call ) & ZEND_CALL_RELEASE_THIS ) {
3764
+ object = Z_OBJ (call -> This );
3765
+ #if 0
3763
3766
if (UNEXPECTED (EG (exception ) != NULL ) && (opline -> op1 .num & ZEND_CALL_CTOR )) {
3764
3767
if (!(opline -> op1 .num & ZEND_CALL_CTOR_RESULT_UNUSED )) {
3768
+ #else
3769
+ if (UNEXPECTED (EG (exception ) != NULL ) && (ZEND_CALL_INFO (call ) & ZEND_CALL_CTOR )) {
3770
+ if (!(ZEND_CALL_INFO (call ) & ZEND_CALL_CTOR_RESULT_UNUSED )) {
3771
+ #endif
3765
3772
GC_REFCOUNT (object )-- ;
3766
3773
}
3767
3774
if (GC_REFCOUNT (object ) == 1 ) {
@@ -3773,6 +3780,7 @@ ZEND_VM_C_LABEL(fcall_end_change_scope):
3773
3780
EG (scope ) = EX (func )-> op_array .scope ;
3774
3781
3775
3782
ZEND_VM_C_LABEL (fcall_end ):
3783
+ zend_vm_stack_free_call_frame (call );
3776
3784
if (UNEXPECTED (EG (exception ) != NULL )) {
3777
3785
zend_throw_exception_internal (NULL );
3778
3786
if (RETURN_VALUE_USED (opline )) {
@@ -4891,7 +4899,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
4891
4899
} else {
4892
4900
/* We are not handling overloaded classes right now */
4893
4901
zend_execute_data * call = zend_vm_stack_push_call_frame (
4894
- ZEND_CALL_FUNCTION | ZEND_CALL_CTOR |
4902
+ ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR |
4895
4903
(EXPECTED (RETURN_VALUE_USED (opline )) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED ),
4896
4904
constructor ,
4897
4905
opline -> extended_value ,
@@ -7121,7 +7129,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
7121
7129
7122
7130
zend_vm_stack_free_args (EX (call ));
7123
7131
7124
- if (Z_OBJ (call -> This ) ) {
7132
+ if (ZEND_CALL_INFO (call ) & ZEND_CALL_RELEASE_THIS ) {
7125
7133
if (ZEND_CALL_INFO (call ) & ZEND_CALL_CTOR ) {
7126
7134
if (!(ZEND_CALL_INFO (call ) & ZEND_CALL_CTOR_RESULT_UNUSED )) {
7127
7135
GC_REFCOUNT (Z_OBJ (call -> This ))-- ;
@@ -7882,7 +7890,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
7882
7890
zend_function * fbc = EX (func );
7883
7891
zend_object * object = Z_OBJ (EX (This ));
7884
7892
zval * ret = EX (return_value );
7885
- zend_call_kind call_kind = EX_CALL_KIND ( );
7893
+ uint32_t call_info = EX_CALL_INFO () & ( ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS );
7886
7894
zend_class_entry * scope = EX (called_scope );
7887
7895
uint32_t num_args = EX_NUM_ARGS ();
7888
7896
zend_execute_data * call ;
@@ -7907,7 +7915,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
7907
7915
call = execute_data ;
7908
7916
execute_data = EG (current_execute_data ) = EX (prev_execute_data );
7909
7917
zend_vm_stack_free_call_frame (call );
7910
- call = zend_vm_stack_push_call_frame (call_kind , fbc -> common .prototype , 2 , scope , object );
7918
+ call = zend_vm_stack_push_call_frame (call_info , fbc -> common .prototype , 2 , scope , object );
7911
7919
call -> prev_execute_data = execute_data ;
7912
7920
7913
7921
ZVAL_STR (ZEND_CALL_ARG (call , 1 ), fbc -> common .function_name );
@@ -7981,7 +7989,6 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
7981
7989
EG (current_execute_data ) = call -> prev_execute_data ;
7982
7990
7983
7991
zend_vm_stack_free_args (call );
7984
- zend_vm_stack_free_call_frame (call );
7985
7992
7986
7993
if (ret == & retval ) {
7987
7994
zval_ptr_dtor (ret );
@@ -7991,16 +7998,18 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
7991
7998
ZEND_VM_C_LABEL (call_trampoline_end ):
7992
7999
execute_data = EG (current_execute_data );
7993
8000
7994
- if (!EX (func ) || !ZEND_USER_CODE (EX (func )-> type ) || (call_kind & ZEND_CALL_TOP )) {
8001
+ if (!EX (func ) || !ZEND_USER_CODE (EX (func )-> type ) || (call_info & ZEND_CALL_TOP )) {
7995
8002
ZEND_VM_RETURN ();
7996
8003
}
7997
8004
7998
8005
opline = EX (opline );
7999
8006
8000
- if (object ) {
8007
+ if (call_info & ZEND_CALL_RELEASE_THIS ) {
8008
+ object = Z_OBJ (call -> This );
8001
8009
OBJ_RELEASE (object );
8002
8010
}
8003
8011
EG (scope ) = EX (func )-> op_array .scope ;
8012
+ zend_vm_stack_free_call_frame (call );
8004
8013
8005
8014
if (UNEXPECTED (EG (exception ) != NULL )) {
8006
8015
zend_throw_exception_internal (NULL );
0 commit comments