Skip to content

Commit 1dcdf87

Browse files
php-genericsLlama
andcommitted
Add JIT support for generic constructor arg inference
Infers generic type arguments from constructor parameters in JIT-compiled code paths. Adds zend_jit_infer_generic_ctor_args helper and hooks it into both the IR backend and VM leave-func helpers to run before $this is released. Co-Authored-By: Llama <noreply@meta.com>
1 parent 6ca9222 commit 1dcdf87

File tree

3 files changed

+28
-0
lines changed

3 files changed

+28
-0
lines changed

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2058,6 +2058,16 @@ static void ZEND_FASTCALL zend_jit_verify_generic_return(
20582058
zend_verify_return_error((zend_function*)op_array, arg);
20592059
}
20602060

2061+
static void ZEND_FASTCALL zend_jit_infer_generic_ctor_args(zend_execute_data *execute_data)
2062+
{
2063+
if (UNEXPECTED(EX(func)->common.fn_flags & ZEND_ACC_CTOR)) {
2064+
zend_object *obj = Z_OBJ(execute_data->This);
2065+
if (obj->ce->generic_params_info && !obj->generic_args) {
2066+
zend_infer_generic_args_from_constructor(obj, execute_data);
2067+
}
2068+
}
2069+
}
2070+
20612071
static void ZEND_FASTCALL zend_jit_fetch_obj_r_slow(zend_object *zobj)
20622072
{
20632073
zval *retval;

ext/opcache/jit/zend_jit_ir.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3137,6 +3137,7 @@ static void zend_jit_setup_disasm(void)
31373137
REGISTER_HELPER(zend_jit_verify_arg_slow);
31383138
REGISTER_HELPER(zend_jit_verify_generic_arg);
31393139
REGISTER_HELPER(zend_jit_verify_generic_return);
3140+
REGISTER_HELPER(zend_jit_infer_generic_ctor_args);
31403141
REGISTER_HELPER(zend_missing_arg_error);
31413142
REGISTER_HELPER(zend_jit_only_vars_by_reference);
31423143
REGISTER_HELPER(zend_jit_leave_func_helper);
@@ -11286,6 +11287,8 @@ static int zend_jit_leave_func(zend_jit_ctx *jit,
1128611287
fast_path = ir_END();
1128711288
ir_IF_TRUE(if_release);
1128811289
}
11290+
// JIT: Infer generic args from constructor before releasing $this
11291+
ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_infer_generic_ctor_args), jit_FP(jit));
1128911292
// JIT: OBJ_RELEASE(execute_data->This))
1129011293
jit_OBJ_RELEASE(jit, ir_LOAD_A(jit_EX(This.value.obj)));
1129111294
if (fast_path) {

ext/opcache/jit/zend_jit_vm_helpers.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "Zend/zend_closures.h"
2424
#include "Zend/zend_constants.h"
2525
#include "Zend/zend_API.h"
26+
#include "Zend/zend_generics.h"
2627

2728
#include <ZendAccelerator.h>
2829
#include "Optimizer/zend_func_info.h"
@@ -59,6 +60,13 @@ ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_leave_func_helper_tai
5960

6061
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
6162
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
63+
/* Infer generic args from constructor before releasing $this */
64+
if (UNEXPECTED(EX(func)->common.fn_flags & ZEND_ACC_CTOR)) {
65+
zend_object *obj = Z_OBJ(execute_data->This);
66+
if (obj->ce->generic_params_info && !obj->generic_args) {
67+
zend_infer_generic_args_from_constructor(obj, execute_data);
68+
}
69+
}
6270
OBJ_RELEASE(Z_OBJ(execute_data->This));
6371
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
6472
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
@@ -110,6 +118,13 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(ZEND_OPC
110118

111119
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
112120
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
121+
/* Infer generic args from constructor before releasing $this */
122+
if (UNEXPECTED(EX(func)->common.fn_flags & ZEND_ACC_CTOR)) {
123+
zend_object *obj = Z_OBJ(execute_data->This);
124+
if (obj->ce->generic_params_info && !obj->generic_args) {
125+
zend_infer_generic_args_from_constructor(obj, execute_data);
126+
}
127+
}
113128
OBJ_RELEASE(Z_OBJ(execute_data->This));
114129
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
115130
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));

0 commit comments

Comments
 (0)