Skip to content

Fix JIT for overridden properties with added hooks #17395

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Zend/tests/gh17376.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
GH-17376: Child classes may add hooks to plain properties
--FILE--
<?php

class A {
public $prop = 1;
}

class B extends A {
public $prop {
get => 2;
}
}

function test(A $a) {
var_dump($a->prop);
}

test(new A);
test(new B);

?>
--EXPECT--
int(1)
int(2)
5 changes: 0 additions & 5 deletions Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should move this to a separate PR, but IMO this should still be fixed.

}

ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) {
Expand Down
25 changes: 24 additions & 1 deletion ext/opcache/jit/zend_jit_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -14291,6 +14291,29 @@ 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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ZEND_JIT_EXIT_TO_VM looks too aggressive. Why can't we record another trace with slow-path JIT-ed code.
To be more accurate instead of checking for the same prop_info, we may check prop_info->hooks == NULL.

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) {
Expand Down Expand Up @@ -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) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could technically be reverted, but seems more logical.

ir_MERGE_list(slow_inputs);
jit_SET_EX_OPLINE(jit, opline);

Expand Down
Loading