From 2f30e3da49912ace87738e86ccbb9df9e674bf10 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 7 Jan 2025 22:48:31 +0100 Subject: [PATCH] Fix JIT for overridden properties with added hooks Fixes GH-17376 --- Zend/tests/gh17376.phpt | 26 ++++++++++++++++++++++++++ Zend/zend_inheritance.c | 5 ----- ext/opcache/jit/zend_jit_ir.c | 25 ++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 Zend/tests/gh17376.phpt diff --git a/Zend/tests/gh17376.phpt b/Zend/tests/gh17376.phpt new file mode 100644 index 0000000000000..d9f4ab5fc03d1 --- /dev/null +++ b/Zend/tests/gh17376.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-17376: Child classes may add hooks to plain properties +--FILE-- + 2; + } +} + +function test(A $a) { + var_dump($a->prop); +} + +test(new A); +test(new B); + +?> +--EXPECT-- +int(1) +int(2) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 8197e61628439..d2118cd4e7db1 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1653,11 +1653,6 @@ void zend_build_properties_info_table(zend_class_entry *ce) table, parent_table, sizeof(zend_property_info *) * ce->parent->default_properties_count ); - - /* Child did not add any new properties, we are done */ - if (ce->default_properties_count == ce->parent->default_properties_count) { - return; - } } ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) { diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index e14345215f6f4..0bf083cba3a48 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -14291,8 +14291,31 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit, } } } else { + /* Child classes may add hooks to property. */ + if (ce_is_instanceof && !(prop_info->flags & ZEND_ACC_FINAL)) { + int prop_info_offset = + (((prop_info->offset - (sizeof(zend_object) - sizeof(zval))) / sizeof(zval)) * sizeof(void*)); + ir_ref prop_info_ref = ir_LOAD_A(ir_ADD_OFFSET(obj_ref, offsetof(zend_object, ce))); + prop_info_ref = ir_LOAD_A(ir_ADD_OFFSET(prop_info_ref, offsetof(zend_class_entry, properties_info_table))); + prop_info_ref = ir_LOAD_A(ir_ADD_OFFSET(prop_info_ref, prop_info_offset)); + ir_ref is_same_prop_info = ir_EQ(prop_info_ref, ir_CONST_ADDR(prop_info)); + if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) { + int32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_TO_VM); + const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } + ir_GUARD(is_same_prop_info, ir_CONST_ADDR(exit_addr)); + } else { + ir_ref if_same_prop_info = ir_IF(is_same_prop_info); + ir_IF_FALSE_cold(if_same_prop_info); + ir_END_list(slow_inputs); + ir_IF_TRUE(if_same_prop_info); + } + } prop_ref = ir_ADD_OFFSET(obj_ref, prop_info->offset); prop_addr = ZEND_ADDR_REF_ZVAL(prop_ref); + if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) { if (opline->opcode == ZEND_FETCH_OBJ_W || !(res_info & MAY_BE_GUARD) || !JIT_G(current_frame)) { /* perform IS_UNDEF check only after result type guard (during deoptimization) */ @@ -14435,7 +14458,7 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit, SET_STACK_REG(JIT_G(current_frame)->stack, EX_VAR_TO_NUM(opline->op1.var), ZREG_NONE); } - if (JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE || !prop_info) { + if (slow_inputs) { ir_MERGE_list(slow_inputs); jit_SET_EX_OPLINE(jit, opline);