From c4995fab7ce7cff877a44f8c0608270a745ca0d3 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 1 Oct 2024 22:11:06 +0300 Subject: [PATCH 1/5] Implement JIT for ZEND_FETCH_STATIC_PROP_* and improve interpretation --- Zend/zend_execute.c | 94 +++++++++++---- Zend/zend_execute.h | 1 + Zend/zend_vm_def.h | 38 +++--- Zend/zend_vm_execute.h | 47 +++++--- ext/opcache/jit/zend_jit.c | 16 +++ ext/opcache/jit/zend_jit_helpers.c | 7 ++ ext/opcache/jit/zend_jit_ir.c | 183 +++++++++++++++++++++++++++++ ext/opcache/jit/zend_jit_trace.c | 23 ++++ 8 files changed, 353 insertions(+), 56 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index a0eacb14dcf4c..149257fdead01 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3532,7 +3532,8 @@ static zend_never_inline void zend_assign_to_property_reference_var_var(zval *co OPLINE_CC EXECUTE_DATA_CC); } -static zend_never_inline zend_result zend_fetch_static_property_address_ex(zval **retval, zend_property_info **prop_info, uint32_t cache_slot, int fetch_type OPLINE_DC EXECUTE_DATA_DC) { +static zend_never_inline zval* zend_fetch_static_property_address_ex(zend_property_info **prop_info, uint32_t cache_slot, int fetch_type OPLINE_DC EXECUTE_DATA_DC) { + zval *result; zend_string *name; zend_class_entry *ce; zend_property_info *property_info; @@ -3548,7 +3549,7 @@ static zend_never_inline zend_result zend_fetch_static_property_address_ex(zval ce = zend_fetch_class_by_name(Z_STR_P(class_name), Z_STR_P(class_name + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { FREE_OP(op1_type, opline->op1.var); - return FAILURE; + return NULL; } if (UNEXPECTED(op1_type != IS_CONST)) { CACHE_PTR(cache_slot, ce); @@ -3559,21 +3560,21 @@ static zend_never_inline zend_result zend_fetch_static_property_address_ex(zval ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { FREE_OP(op1_type, opline->op1.var); - return FAILURE; + return NULL; } } else { ce = Z_CE_P(EX_VAR(opline->op2.var)); } - if (EXPECTED(op1_type == IS_CONST) && EXPECTED(CACHED_PTR(cache_slot) == ce)) { - *retval = CACHED_PTR(cache_slot + sizeof(void *)); + if (EXPECTED(op1_type == IS_CONST) && EXPECTED(CACHED_PTR(cache_slot + sizeof(void *)) == ce)) { + result = CACHED_PTR(cache_slot + sizeof(void *)); *prop_info = CACHED_PTR(cache_slot + sizeof(void *) * 2); - return SUCCESS; + return result; } } if (EXPECTED(op1_type == IS_CONST)) { name = Z_STR_P(RT_CONSTANT(opline, opline->op1)); - *retval = zend_std_get_static_property_with_info(ce, name, fetch_type, &property_info); + result = zend_std_get_static_property_with_info(ce, name, fetch_type, &property_info); } else { zend_string *tmp_name; zval *varname = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); @@ -3586,62 +3587,109 @@ static zend_never_inline zend_result zend_fetch_static_property_address_ex(zval } name = zval_get_tmp_string(varname, &tmp_name); } - *retval = zend_std_get_static_property_with_info(ce, name, fetch_type, &property_info); + result = zend_std_get_static_property_with_info(ce, name, fetch_type, &property_info); zend_tmp_string_release(tmp_name); FREE_OP(op1_type, opline->op1.var); } - if (UNEXPECTED(*retval == NULL)) { - return FAILURE; + if (UNEXPECTED(result == NULL)) { + return NULL; } *prop_info = property_info; if (EXPECTED(op1_type == IS_CONST) && EXPECTED(!(property_info->ce->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(cache_slot, ce, *retval); + CACHE_POLYMORPHIC_PTR(cache_slot, ce, result); CACHE_PTR(cache_slot + sizeof(void *) * 2, property_info); } - return SUCCESS; + return result; } -static zend_always_inline zend_result zend_fetch_static_property_address(zval **retval, zend_property_info **prop_info, uint32_t cache_slot, int fetch_type, int flags OPLINE_DC EXECUTE_DATA_DC) { +static zend_always_inline zval* zend_fetch_static_property_address(zend_property_info **prop_info, uint32_t cache_slot, int fetch_type, int flags OPLINE_DC EXECUTE_DATA_DC) { + zval *result; zend_property_info *property_info; - if (opline->op1_type == IS_CONST && (opline->op2_type == IS_CONST || (opline->op2_type == IS_UNUSED && (opline->op2.num == ZEND_FETCH_CLASS_SELF || opline->op2.num == ZEND_FETCH_CLASS_PARENT))) && EXPECTED(CACHED_PTR(cache_slot) != NULL)) { - *retval = CACHED_PTR(cache_slot + sizeof(void *)); + if (opline->op1_type == IS_CONST + && (opline->op2_type == IS_CONST + || (opline->op2_type == IS_UNUSED + && (opline->op2.num == ZEND_FETCH_CLASS_SELF + || opline->op2.num == ZEND_FETCH_CLASS_PARENT))) + && EXPECTED(CACHED_PTR(cache_slot + sizeof(void *)) != NULL)) { + result = CACHED_PTR(cache_slot + sizeof(void *)); property_info = CACHED_PTR(cache_slot + sizeof(void *) * 2); if ((fetch_type == BP_VAR_R || fetch_type == BP_VAR_RW) - && UNEXPECTED(Z_TYPE_P(*retval) == IS_UNDEF) + && UNEXPECTED(Z_TYPE_P(result) == IS_UNDEF) && ZEND_TYPE_IS_SET(property_info->type)) { zend_throw_error(NULL, "Typed static property %s::$%s must not be accessed before initialization", ZSTR_VAL(property_info->ce->name), zend_get_unmangled_property_name(property_info->name)); - return FAILURE; + return NULL; } } else { - zend_result success; - success = zend_fetch_static_property_address_ex(retval, &property_info, cache_slot, fetch_type OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(success != SUCCESS)) { - return FAILURE; + result = zend_fetch_static_property_address_ex(&property_info, cache_slot, fetch_type OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!result)) { + return NULL; } } flags &= ZEND_FETCH_OBJ_FLAGS; if (flags && ZEND_TYPE_IS_SET(property_info->type)) { - zend_handle_fetch_obj_flags(NULL, *retval, NULL, property_info, flags); + zend_handle_fetch_obj_flags(NULL, result, NULL, property_info, flags); } if (prop_info) { *prop_info = property_info; } - return SUCCESS; + return result; +} + +ZEND_API zval* zend_fetch_static_property(zend_execute_data *ex, int fetch_type) { + zval *result; + zend_property_info *property_info; +#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + zend_execute_data *orig_execute_data = execute_data; +#else + zend_execute_data *execute_data; +#endif + execute_data = ex; +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + const zend_op *orig_opline = opline; +#else + const zend_op *opline; +#endif + opline = execute_data->opline; + + uint32_t cache_slot = opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS; + uint32_t flags = 0; + + if (fetch_type == BP_VAR_W) { + flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS; + } + result = zend_fetch_static_property_address_ex(&property_info, cache_slot, fetch_type OPLINE_CC EXECUTE_DATA_CC); + if (EXPECTED(result)) { + if (flags && ZEND_TYPE_IS_SET(property_info->type)) { + zend_handle_fetch_obj_flags(NULL, result, NULL, property_info, flags); + } + } else { + result = &EG(uninitialized_zval); + } + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + EX(opline) = opline; + opline = orig_opline; +#endif +#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + execute_data = orig_execute_data; +#endif + + return result; } ZEND_API ZEND_COLD void zend_throw_ref_type_error_type(const zend_property_info *prop1, const zend_property_info *prop2, const zval *zv) { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 3f59e2b371a13..f90041c80744c 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -434,6 +434,7 @@ ZEND_API void zend_unfinished_calls_gc(zend_execute_data *execute_data, zend_exe ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num); ZEND_API ZEND_ATTRIBUTE_DEPRECATED HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer); ZEND_API HashTable *zend_unfinished_execution_gc_ex(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer, bool suspended_by_yield); +ZEND_API zval* zend_fetch_static_property(zend_execute_data *ex, int fetch_type); ZEND_API void zend_frameless_observed_call(zend_execute_data *execute_data); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 55675e4a0b5c2..62b73e5892d8b 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1109,7 +1109,8 @@ ZEND_VM_HANDLER(29, ZEND_ASSIGN_STATIC_PROP_OP, ANY, ANY, OP) SAVE_OPLINE(); - if (UNEXPECTED(zend_fetch_static_property_address(&prop, &prop_info, (opline+1)->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) { + prop = zend_fetch_static_property_address(&prop_info, (opline+1)->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { UNDEF_RESULT(); FREE_OP_DATA(); HANDLE_EXCEPTION(); @@ -1423,7 +1424,8 @@ ZEND_VM_HANDLER(38, ZEND_PRE_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT) SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -1449,7 +1451,8 @@ ZEND_VM_HANDLER(40, ZEND_POST_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT) SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -1829,14 +1832,17 @@ ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED, VAR_FETCH) } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -ZEND_VM_HELPER(zend_fetch_static_prop_helper, ANY, ANY, int type) +ZEND_VM_INLINE_HELPER(zend_fetch_static_prop_helper, ANY, ANY, int type) { USE_OPLINE zval *prop; SAVE_OPLINE(); - if (UNEXPECTED(zend_fetch_static_property_address(&prop, NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, opline->extended_value OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) { + prop = zend_fetch_static_property_address( + NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, + type == BP_VAR_W ? opline->extended_value : 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); prop = &EG(uninitialized_zval); } @@ -1870,10 +1876,11 @@ ZEND_VM_HANDLER(175, ZEND_FETCH_STATIC_PROP_RW, ANY, CLASS_FETCH, CACHE_SLOT) /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, ANY, CLASS_FETCH, FETCH_REF|CACHE_SLOT) { - int fetch_type = - (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? - BP_VAR_W : BP_VAR_R; - ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, fetch_type); + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_STATIC_PROP_W); + } else { + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_STATIC_PROP_R); + } } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ @@ -2584,7 +2591,8 @@ ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA= SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { FREE_OP_DATA(); UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -2878,7 +2886,8 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC) SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value & ~ZEND_RETURNS_FUNCTION, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value & ~ZEND_RETURNS_FUNCTION, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { FREE_OP_DATA(); UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -7430,18 +7439,17 @@ ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, ANY, CLASS_FETCH, ISSET|CAC { USE_OPLINE zval *value; - zend_result fetch_result; bool result; SAVE_OPLINE(); - fetch_result = zend_fetch_static_property_address(&value, NULL, opline->extended_value & ~ZEND_ISEMPTY, BP_VAR_IS, 0 OPLINE_CC EXECUTE_DATA_CC); + value = zend_fetch_static_property_address(NULL, opline->extended_value & ~ZEND_ISEMPTY, BP_VAR_IS, 0 OPLINE_CC EXECUTE_DATA_CC); if (!(opline->extended_value & ZEND_ISEMPTY)) { - result = fetch_result == SUCCESS && Z_TYPE_P(value) > IS_NULL && + result = value != NULL && Z_TYPE_P(value) > IS_NULL && (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); } else { - result = fetch_result != SUCCESS || !i_zend_is_true(value); + result = value == NULL || !i_zend_is_true(value); } ZEND_VM_SMART_BRANCH(result, 1); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 088c29cf408e8..3f0c3ab471655 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -776,7 +776,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN SAVE_OPLINE(); - if (UNEXPECTED(zend_fetch_static_property_address(&prop, &prop_info, (opline+1)->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) { + prop = zend_fetch_static_property_address(&prop_info, (opline+1)->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { UNDEF_RESULT(); FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); HANDLE_EXCEPTION(); @@ -819,7 +820,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_STATIC_PROP_SPEC_HANDL SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -839,7 +841,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_STATIC_PROP_SPEC_HAND SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -851,14 +854,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_STATIC_PROP_SPEC_HAND } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC(int type ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_SPEC(int type ZEND_OPCODE_HANDLER_ARGS_DC) { USE_OPLINE zval *prop; SAVE_OPLINE(); - if (UNEXPECTED(zend_fetch_static_property_address(&prop, NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, opline->extended_value OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) { + prop = zend_fetch_static_property_address( + NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, + type == BP_VAR_W ? opline->extended_value : 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); prop = &EG(uninitialized_zval); } @@ -892,10 +898,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_HAND /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - int fetch_type = - (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? - BP_VAR_W : BP_VAR_R; - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(fetch_type ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + ZEND_VM_TAIL_CALL(ZEND_FETCH_STATIC_PROP_W_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_STATIC_PROP_R_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ @@ -943,7 +950,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -979,7 +987,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -1015,7 +1024,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -1051,7 +1061,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -1087,7 +1098,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HA SAVE_OPLINE(); - if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value & ~ZEND_RETURNS_FUNCTION, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value & ~ZEND_RETURNS_FUNCTION, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -3008,18 +3020,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC { USE_OPLINE zval *value; - zend_result fetch_result; bool result; SAVE_OPLINE(); - fetch_result = zend_fetch_static_property_address(&value, NULL, opline->extended_value & ~ZEND_ISEMPTY, BP_VAR_IS, 0 OPLINE_CC EXECUTE_DATA_CC); + value = zend_fetch_static_property_address(NULL, opline->extended_value & ~ZEND_ISEMPTY, BP_VAR_IS, 0 OPLINE_CC EXECUTE_DATA_CC); if (!(opline->extended_value & ZEND_ISEMPTY)) { - result = fetch_result == SUCCESS && Z_TYPE_P(value) > IS_NULL && + result = value != NULL && Z_TYPE_P(value) > IS_NULL && (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); } else { - result = fetch_result != SUCCESS || !i_zend_is_true(value); + result = value == NULL || !i_zend_is_true(value); } ZEND_VM_SMART_BRANCH(result, 1); diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 5657764926706..d39eaea9fb36a 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -2349,6 +2349,22 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op goto jit_failure; } goto done; + case ZEND_FETCH_STATIC_PROP_R: + case ZEND_FETCH_STATIC_PROP_IS: + case ZEND_FETCH_STATIC_PROP_W: + case ZEND_FETCH_STATIC_PROP_RW: + case ZEND_FETCH_STATIC_PROP_UNSET: + if (!(opline->op1_type == IS_CONST + && (opline->op2_type == IS_CONST + || (opline->op2_type == IS_UNUSED + && (opline->op2.num == ZEND_FETCH_CLASS_SELF + || opline->op2.num == ZEND_FETCH_CLASS_PARENT))))) { + break; + } + if (!zend_jit_fetch_static_prop(&ctx, opline, op_array)) { + goto jit_failure; + } + goto done; case ZEND_BIND_GLOBAL: if (!ssa->ops || !ssa->var_info) { op1_info = MAY_BE_ANY|MAY_BE_REF; diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 4172cd6697e42..a8f2bbe65bb0d 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -3212,6 +3212,13 @@ static void ZEND_FASTCALL zend_jit_post_dec_obj_helper(zend_object *zobj, zend_s } } +static void ZEND_FASTCALL zend_jit_uninit_static_prop(const zend_property_info *property_info) +{ + zend_throw_error(NULL, "Typed static property %s::$%s must not be accessed before initialization", + ZSTR_VAL(property_info->ce->name), + zend_get_unmangled_property_name(property_info->name)); +} + static void ZEND_FASTCALL zend_jit_free_trampoline_helper(zend_function *func) { ZEND_ASSERT(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE); diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index c3ab026deec2f..283918fd9c322 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -3093,6 +3093,7 @@ static void zend_jit_setup_disasm(void) REGISTER_HELPER(zend_jit_post_inc_obj_helper); REGISTER_HELPER(zend_jit_pre_dec_obj_helper); REGISTER_HELPER(zend_jit_post_dec_obj_helper); + REGISTER_HELPER(zend_jit_uninit_static_prop); REGISTER_HELPER(zend_jit_rope_end); REGISTER_HELPER(zend_fcall_interrupt); @@ -15609,6 +15610,188 @@ static int zend_jit_incdec_obj(zend_jit_ctx *jit, return 1; } +static int zend_jit_fetch_static_prop(zend_jit_ctx *jit, const zend_op *opline, const zend_op_array *op_array) +{ + zend_jit_addr res_addr = RES_ADDR(); + uint32_t cache_slot = opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS; + uint32_t flags; + ir_ref ref, ref2, if_cached, fast_path, cold_path, prop_info_ref, if_typed, if_def; + int fetch_type; + zend_property_info *known_prop_info = NULL; + zend_class_entry *ce = NULL; + + if (opline->op2_type == IS_CONST) { + zval *zv = RT_CONSTANT(opline, opline->op2); + zend_string *class_name; + + ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING); + class_name = Z_STR_P(zv); + ce = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (ce && (ce->type == ZEND_INTERNAL_CLASS || ce->info.user.filename != op_array->filename)) { + ce = NULL; + } + } else { + ZEND_ASSERT(opline->op2_type == IS_UNUSED); + if (opline->op2.num == ZEND_FETCH_CLASS_SELF) { + ce = op_array->scope; + } else { + ZEND_ASSERT(opline->op2.num == ZEND_FETCH_CLASS_PARENT); + ce = op_array->scope; + if (ce) { + if (ce->parent) { + ce = ce->parent; + if (ce->type == ZEND_INTERNAL_CLASS || ce->info.user.filename != op_array->filename) { + ce = NULL; + } + } else { + ce = NULL; + } + } + } + } + + if (ce) { + zval *zv = RT_CONSTANT(opline, opline->op1); + zend_string *prop_name; + + ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING); + prop_name = Z_STR_P(zv); + zv = zend_hash_find(&ce->properties_info, prop_name); + if (zv) { + zend_property_info *prop_info = Z_PTR_P(zv); + + if (prop_info->flags & ZEND_ACC_STATIC) { + if (prop_info->ce == op_array->scope + || (prop_info->flags & ZEND_ACC_PUBLIC) + || ((prop_info->flags & ZEND_ACC_PROTECTED) + && instanceof_function_slow(op_array->scope, prop_info->ce))) { + known_prop_info = prop_info; + } + } + } + } + + switch (opline->opcode) { + case ZEND_FETCH_STATIC_PROP_R: + case ZEND_FETCH_STATIC_PROP_FUNC_ARG: + fetch_type = BP_VAR_R; + break; + case ZEND_FETCH_STATIC_PROP_IS: + fetch_type = BP_VAR_IS; + break; + case ZEND_FETCH_STATIC_PROP_W: + fetch_type = BP_VAR_W; + break; + case ZEND_FETCH_STATIC_PROP_RW: + fetch_type = BP_VAR_RW; + break; + case ZEND_FETCH_STATIC_PROP_UNSET: + fetch_type = BP_VAR_UNSET; + break; + default: + ZEND_UNREACHABLE(); + } + + // JIT: result = CACHED_PTR(cache_slot + sizeof(void *)); + ref = ir_LOAD_A( + ir_ADD_OFFSET(ir_LOAD_A(jit_EX(run_time_cache)), cache_slot + sizeof(void*))); + + // JIT: if (result) + if_cached = ir_IF(ref); + ir_IF_TRUE(if_cached); + + if (fetch_type == BP_VAR_R || fetch_type == BP_VAR_RW) { + if (!known_prop_info || ZEND_TYPE_IS_SET(known_prop_info->type)) { + ir_ref merge = IR_UNUSED; + + // JIT: if (UNEXPECTED(Z_TYPE_P(result) == IS_UNDEF) + if_typed = IR_UNUSED; + if_def = ir_IF(jit_Z_TYPE_ref(jit, ref)); + ir_IF_FALSE_cold(if_def); + if (!known_prop_info) { + // JIT: if (ZEND_TYPE_IS_SET(property_info->type)) + prop_info_ref = ir_LOAD_L( + ir_ADD_OFFSET(ir_LOAD_A(jit_EX(run_time_cache)), cache_slot + sizeof(void*) * 2)); + if_typed = ir_IF(ir_AND_U32( + ir_LOAD_U32(ir_ADD_OFFSET(prop_info_ref, offsetof(zend_property_info, type.type_mask))), + ir_CONST_U32(_ZEND_TYPE_MASK))); + ir_IF_FALSE(if_typed); + ir_END_list(merge); + ir_IF_TRUE(if_typed); + } else { + prop_info_ref = ir_CONST_ADDR(known_prop_info); + } + // JIT: zend_throw_error(NULL, "Typed static property %s::$%s must not be accessed before initialization", + // ZSTR_VAL(property_info->ce->name), + // zend_get_unmangled_property_name(property_info->name)); + jit_SET_EX_OPLINE(jit, opline); + ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_uninit_static_prop), prop_info_ref); + ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler_undef)); + + ir_IF_TRUE(if_def); + if (!known_prop_info) { + ir_END_list(merge); + ir_MERGE_list(merge); + } + } + } else if (fetch_type == BP_VAR_W) { + flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS; + if (flags && (!known_prop_info || ZEND_TYPE_IS_SET(known_prop_info->type))) { + ir_ref merge = IR_UNUSED; + + if (!known_prop_info) { + // JIT: if (ZEND_TYPE_IS_SET(property_info->type)) + prop_info_ref = ir_LOAD_L( + ir_ADD_OFFSET(ir_LOAD_A(jit_EX(run_time_cache)), cache_slot + sizeof(void*) * 2)); + if_typed = ir_IF(ir_AND_U32( + ir_LOAD_U32(ir_ADD_OFFSET(prop_info_ref, offsetof(zend_property_info, type.type_mask))), + ir_CONST_U32(_ZEND_TYPE_MASK))); + ir_IF_FALSE(if_typed); + ir_END_list(merge); + ir_IF_TRUE(if_typed); + } else { + prop_info_ref = ir_CONST_ADDR(known_prop_info); + } + + // JIT: zend_handle_fetch_obj_flags(NULL, *retval, NULL, property_info, flags); + ir_ref if_ok = ir_IF(ir_CALL_5(IR_BOOL, ir_CONST_FUNC(zend_handle_fetch_obj_flags), + IR_NULL, ref, IR_NULL, prop_info_ref, ir_CONST_U32(flags))); + ir_IF_FALSE_cold(if_ok); + ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler_undef)); + ir_IF_TRUE(if_ok); + if (!known_prop_info) { + ir_END_list(merge); + ir_MERGE_list(merge); + } + } + } + + fast_path = ir_END(); + + ir_IF_FALSE_cold(if_cached); + jit_SET_EX_OPLINE(jit, opline); + ref2 = ir_CALL_2(IR_ADDR, ir_CONST_FUNC(zend_fetch_static_property), jit_FP(jit), ir_CONST_I32(fetch_type)); + zend_jit_check_exception_undef_result(jit, opline); + cold_path = ir_END(); + + ir_MERGE_2(fast_path, cold_path); + ref = ir_PHI_2(IR_ADDR, ref, ref2); + + if (fetch_type == BP_VAR_R || fetch_type == BP_VAR_IS) { + // JIT: ZVAL_COPY_DEREF(EX_VAR(opline->result.var), result); + if (!zend_jit_zval_copy_deref(jit, res_addr, ZEND_ADDR_REF_ZVAL(ref), + jit_Z_TYPE_INFO_ref(jit, ref))) { + return 0; + } + } else { + // JIT: ZVAL_INDIRECT(EX_VAR(opline->result.var), result); + jit_set_Z_PTR(jit, res_addr, ref); + jit_set_Z_TYPE_INFO(jit, res_addr, IS_INDIRECT); + } + + return 1; +} + static int zend_jit_switch(zend_jit_ctx *jit, const zend_op *opline, const zend_op_array *op_array, zend_ssa *ssa, zend_jit_trace_rec *trace, zend_jit_trace_info *trace_info) { HashTable *jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index a36beab6fef10..562938e5d36a3 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -6071,6 +6071,29 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par goto jit_failure; } goto done; + case ZEND_FETCH_STATIC_PROP_FUNC_ARG: + if (!JIT_G(current_frame) + || !JIT_G(current_frame)->call + || !TRACE_FRAME_IS_LAST_SEND_BY_VAL(JIT_G(current_frame)->call)) { + break; + } + ZEND_FALLTHROUGH; + case ZEND_FETCH_STATIC_PROP_R: + case ZEND_FETCH_STATIC_PROP_IS: + case ZEND_FETCH_STATIC_PROP_W: + case ZEND_FETCH_STATIC_PROP_RW: + case ZEND_FETCH_STATIC_PROP_UNSET: + if (!(opline->op1_type == IS_CONST + && (opline->op2_type == IS_CONST + || (opline->op2_type == IS_UNUSED + && (opline->op2.num == ZEND_FETCH_CLASS_SELF + || opline->op2.num == ZEND_FETCH_CLASS_PARENT))))) { + break; + } + if (!zend_jit_fetch_static_prop(&ctx, opline, op_array)) { + goto jit_failure; + } + goto done; case ZEND_BIND_GLOBAL: orig_opline = opline; orig_ssa_op = ssa_op; From cb4390dc7e5b144e13e7b3796db2e1c1cec90add Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 2 Oct 2024 10:00:40 +0300 Subject: [PATCH 2/5] Revert incorrect change --- Zend/zend_execute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 149257fdead01..c044a11f1581a 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3565,7 +3565,7 @@ static zend_never_inline zval* zend_fetch_static_property_address_ex(zend_proper } else { ce = Z_CE_P(EX_VAR(opline->op2.var)); } - if (EXPECTED(op1_type == IS_CONST) && EXPECTED(CACHED_PTR(cache_slot + sizeof(void *)) == ce)) { + if (EXPECTED(op1_type == IS_CONST) && EXPECTED(CACHED_PTR(cache_slot) == ce)) { result = CACHED_PTR(cache_slot + sizeof(void *)); *prop_info = CACHED_PTR(cache_slot + sizeof(void *) * 2); return result; From 8965fe6d749e5cfe6aebb061c55ce54725250edb Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 2 Oct 2024 19:26:22 +0300 Subject: [PATCH 3/5] Use FASTCALL calling convention --- Zend/zend_execute.c | 2 +- Zend/zend_execute.h | 2 +- ext/opcache/jit/zend_jit_ir.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c044a11f1581a..8b44f5c86d60f 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3650,7 +3650,7 @@ static zend_always_inline zval* zend_fetch_static_property_address(zend_property return result; } -ZEND_API zval* zend_fetch_static_property(zend_execute_data *ex, int fetch_type) { +ZEND_API zval* ZEND_FASTCALL zend_fetch_static_property(zend_execute_data *ex, int fetch_type) { zval *result; zend_property_info *property_info; #if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index f90041c80744c..a11aca81e84c1 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -434,7 +434,7 @@ ZEND_API void zend_unfinished_calls_gc(zend_execute_data *execute_data, zend_exe ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num); ZEND_API ZEND_ATTRIBUTE_DEPRECATED HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer); ZEND_API HashTable *zend_unfinished_execution_gc_ex(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer, bool suspended_by_yield); -ZEND_API zval* zend_fetch_static_property(zend_execute_data *ex, int fetch_type); +ZEND_API zval* ZEND_FASTCALL zend_fetch_static_property(zend_execute_data *ex, int fetch_type); ZEND_API void zend_frameless_observed_call(zend_execute_data *execute_data); diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 283918fd9c322..9a6343f961c91 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -15770,7 +15770,7 @@ static int zend_jit_fetch_static_prop(zend_jit_ctx *jit, const zend_op *opline, ir_IF_FALSE_cold(if_cached); jit_SET_EX_OPLINE(jit, opline); - ref2 = ir_CALL_2(IR_ADDR, ir_CONST_FUNC(zend_fetch_static_property), jit_FP(jit), ir_CONST_I32(fetch_type)); + ref2 = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(zend_fetch_static_property), jit_FP(jit), ir_CONST_I32(fetch_type)); zend_jit_check_exception_undef_result(jit, opline); cold_path = ir_END(); From 8a05272b7ebaad9edddcbb33160f9c9c7dcc0220 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 2 Oct 2024 19:33:00 +0300 Subject: [PATCH 4/5] Use EMPTY_SWITCH_DEFAULT_CASE --- ext/opcache/jit/zend_jit_ir.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 9a6343f961c91..e2b3002327de4 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -15688,8 +15688,7 @@ static int zend_jit_fetch_static_prop(zend_jit_ctx *jit, const zend_op *opline, case ZEND_FETCH_STATIC_PROP_UNSET: fetch_type = BP_VAR_UNSET; break; - default: - ZEND_UNREACHABLE(); + EMPTY_SWITCH_DEFAULT_CASE(); } // JIT: result = CACHED_PTR(cache_slot + sizeof(void *)); From b6f7f9a8f46c1c757c441f70ca08667e3a70f68a Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 2 Oct 2024 20:17:28 +0300 Subject: [PATCH 5/5] Move the loading of the property info into zend_jit_uninit_static_prop() --- ext/opcache/jit/zend_jit_helpers.c | 7 ++++++- ext/opcache/jit/zend_jit_ir.c | 4 +--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index a8f2bbe65bb0d..63f4863cf4e6c 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -3212,8 +3212,13 @@ static void ZEND_FASTCALL zend_jit_post_dec_obj_helper(zend_object *zobj, zend_s } } -static void ZEND_FASTCALL zend_jit_uninit_static_prop(const zend_property_info *property_info) +static void ZEND_FASTCALL zend_jit_uninit_static_prop(void) { + zend_execute_data *execute_data = EG(current_execute_data); + const zend_op *opline = EX(opline); + uint32_t cache_slot = opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS; + const zend_property_info *property_info = CACHED_PTR(cache_slot + sizeof(void *) * 2); + zend_throw_error(NULL, "Typed static property %s::$%s must not be accessed before initialization", ZSTR_VAL(property_info->ce->name), zend_get_unmangled_property_name(property_info->name)); diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index e2b3002327de4..4f1663bc0c053 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -15717,14 +15717,12 @@ static int zend_jit_fetch_static_prop(zend_jit_ctx *jit, const zend_op *opline, ir_IF_FALSE(if_typed); ir_END_list(merge); ir_IF_TRUE(if_typed); - } else { - prop_info_ref = ir_CONST_ADDR(known_prop_info); } // JIT: zend_throw_error(NULL, "Typed static property %s::$%s must not be accessed before initialization", // ZSTR_VAL(property_info->ce->name), // zend_get_unmangled_property_name(property_info->name)); jit_SET_EX_OPLINE(jit, opline); - ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_uninit_static_prop), prop_info_ref); + ir_CALL(IR_VOID, ir_CONST_FC_FUNC(zend_jit_uninit_static_prop)); ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler_undef)); ir_IF_TRUE(if_def);