@@ -1804,6 +1804,11 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
18041804 max_used_stack = used_stack = -1 ;
18051805 }
18061806
1807+ #ifdef HAVE_FFI
1808+ uint32_t frame_flags = 0 ;
1809+ zend_ffi_type * frame_ffi_func_type = NULL ;
1810+ #endif
1811+
18071812 p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE ;
18081813 idx = 0 ;
18091814 level = 0 ;
@@ -1814,6 +1819,19 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
18141819 uint8_t val_type = IS_UNKNOWN ;
18151820// zend_class_entry *op1_ce = NULL;
18161821 zend_class_entry * op2_ce = NULL ;
1822+ // zend_class_entry *op3_ce = NULL;
1823+ #ifdef HAVE_FFI
1824+ zend_ffi_type * op1_ffi_type = NULL ;
1825+ zend_ffi_type * op2_ffi_type = NULL ;
1826+ zend_ffi_type * op3_ffi_type = NULL ;
1827+ zend_ffi_type holder1 , holder2 , holder3 ;
1828+ HashTable * op1_ffi_symbols = NULL ;
1829+ (void )op2_ffi_type ;
1830+ (void )op3_ffi_type ;
1831+
1832+ frame_flags = 0 ;
1833+ frame_ffi_func_type = NULL ;
1834+ #endif
18171835
18181836 opline = p -> opline ;
18191837
@@ -1837,10 +1855,44 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
18371855// op1_ce = (zend_class_entry*)(p+1)->ce;
18381856 p ++ ;
18391857 }
1858+ #ifdef HAVE_FFI
1859+ if ((p + 1 )-> op == ZEND_JIT_TRACE_OP1_FFI_TYPE ) {
1860+ op1_ffi_type = (zend_ffi_type * )(p + 1 )-> ptr ;
1861+ if (ZEND_FFI_TYPE_IS_OWNED (op1_ffi_type )) {
1862+ op1_ffi_type = zend_jit_ffi_type_pointer_to (op1_ffi_type , & holder1 );
1863+ }
1864+ p ++ ;
1865+ } else if ((p + 1 )-> op == ZEND_JIT_TRACE_OP1_FFI_SYMBOLS ) {
1866+ op1_ffi_symbols = (HashTable * )(p + 1 )-> ptr ;
1867+ p ++ ;
1868+ }
1869+ #endif
18401870 if ((p + 1 )-> op == ZEND_JIT_TRACE_OP2_TYPE ) {
18411871 op2_ce = (zend_class_entry * )(p + 1 )-> ce ;
18421872 p ++ ;
18431873 }
1874+ #ifdef HAVE_FFI
1875+ if ((p + 1 )-> op == ZEND_JIT_TRACE_OP2_FFI_TYPE ) {
1876+ op2_ffi_type = (zend_ffi_type * )(p + 1 )-> ptr ;
1877+ if (ZEND_FFI_TYPE_IS_OWNED (op2_ffi_type )) {
1878+ op2_ffi_type = zend_jit_ffi_type_pointer_to (op2_ffi_type , & holder2 );
1879+ }
1880+ p ++ ;
1881+ }
1882+ #endif
1883+ if ((p + 1 )-> op == ZEND_JIT_TRACE_OP3_TYPE ) {
1884+ // op3_ce = (zend_class_entry*)(p+1)->ce;
1885+ p ++ ;
1886+ }
1887+ #ifdef HAVE_FFI
1888+ if ((p + 1 )-> op == ZEND_JIT_TRACE_OP3_FFI_TYPE ) {
1889+ op3_ffi_type = (zend_ffi_type * )(p + 1 )-> ptr ;
1890+ if (ZEND_FFI_TYPE_IS_OWNED (op3_ffi_type )) {
1891+ op3_ffi_type = zend_jit_ffi_type_pointer_to (op3_ffi_type , & holder3 );
1892+ }
1893+ p ++ ;
1894+ }
1895+ #endif
18441896 if ((p + 1 )-> op == ZEND_JIT_TRACE_VAL_INFO ) {
18451897 val_type = (p + 1 )-> op1_type ;
18461898 p ++ ;
@@ -2259,6 +2311,18 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
22592311 break ;
22602312 }
22612313 ADD_OP1_TRACE_GUARD ();
2314+ #ifdef HAVE_FFI
2315+ if (op1_ffi_symbols ) {
2316+ zend_ffi_symbol * sym = zend_hash_find_ptr (op1_ffi_symbols ,
2317+ Z_STR_P (RT_CONSTANT (opline , opline -> op2 )));
2318+ if (sym
2319+ && sym -> kind == ZEND_FFI_SYM_FUNC
2320+ && zend_jit_ffi_supported_func (ZEND_FFI_TYPE (sym -> type ))) {
2321+ frame_flags = TRACE_FRAME_MASK_FFI ;
2322+ frame_ffi_func_type = ZEND_FFI_TYPE (sym -> type );
2323+ }
2324+ }
2325+ #endif
22622326 break ;
22632327 case ZEND_INIT_DYNAMIC_CALL :
22642328 if (orig_op2_type == IS_OBJECT && op2_ce == zend_ce_closure ) {
@@ -2356,6 +2420,11 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
23562420 }
23572421 }
23582422 }
2423+
2424+ #ifdef HAVE_FFI
2425+ zend_ssa_op * ssa_op = ssa_ops + idx ;
2426+ #endif
2427+
23592428 if (opline -> opcode == ZEND_RECV_INIT
23602429 && !(op_array -> fn_flags & ZEND_ACC_HAS_TYPE_HINTS )) {
23612430 /* RECV_INIT always copy the constant */
@@ -2365,6 +2434,38 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
23652434 if (ssa_ops [idx ].op2_use >= 0 && ssa_ops [idx ].op2_def >= 0 ) {
23662435 ssa_var_info [ssa_ops [idx ].op2_def ] = ssa_var_info [ssa_ops [idx ].op2_use ];
23672436 }
2437+ #ifdef HAVE_FFI
2438+ } else if (opline -> opcode == ZEND_DO_FCALL
2439+ && RETURN_VALUE_USED (opline )
2440+ && frame
2441+ && frame -> call
2442+ && TRACE_FRAME_FFI (frame -> call )) {
2443+ zend_ffi_type * type = (zend_ffi_type * )frame -> call -> call_opline ;
2444+
2445+ ssa_var_info [ssa_ops [idx ].result_def ].type =
2446+ zend_jit_ffi_type_info (ZEND_FFI_TYPE (type -> func .ret_type ));
2447+ } else if (op1_ffi_type
2448+ && (op1_ffi_type -> kind == ZEND_FFI_TYPE_ARRAY || op1_ffi_type -> kind == ZEND_FFI_TYPE_POINTER )
2449+ && (opline -> opcode == ZEND_FETCH_DIM_R
2450+ || opline -> opcode == ZEND_FETCH_DIM_IS
2451+ || opline -> opcode == ZEND_FETCH_LIST_R )
2452+ && (OP2_INFO () & MAY_BE_ANY ) == MAY_BE_LONG
2453+ && ZEND_FFI_TYPE (op1_ffi_type -> array .type )-> kind != ZEND_FFI_TYPE_VOID
2454+ && zend_jit_ffi_supported_type (ZEND_FFI_TYPE (op1_ffi_type -> array .type ))) {
2455+ ssa_var_info [ssa_ops [idx ].result_def ].type =
2456+ zend_jit_ffi_type_info (ZEND_FFI_TYPE (op1_ffi_type -> array .type ));
2457+ } else if (ssa_ops [idx ].op1_def >= 0
2458+ && frame
2459+ && frame -> call
2460+ && TRACE_FRAME_FFI (frame -> call )
2461+ && (opline -> opcode == ZEND_SEND_VAR_EX
2462+ || opline -> opcode == ZEND_SEND_VAR_NO_REF
2463+ || opline -> opcode == ZEND_SEND_VAR_NO_REF_EX
2464+ || opline -> opcode == ZEND_SEND_FUNC_ARG )
2465+ && opline -> op2_type != IS_CONST ) {
2466+ ssa_var_info [ssa_ops [idx ].op1_def ] = ssa_var_info [ssa_ops [idx ].op1_use ];
2467+ ssa_var_info [ssa_ops [idx ].op1_def ].type &= ~MAY_BE_GUARD ;
2468+ #endif
23682469 } else {
23692470 if (zend_update_type_info (op_array , tssa , script , (zend_op * )opline , ssa_ops + idx , ssa_opcodes , optimization_level ) == FAILURE ) {
23702471 // TODO:
@@ -2617,7 +2718,12 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
26172718
26182719 } else if (p -> op == ZEND_JIT_TRACE_INIT_CALL ) {
26192720 call = top ;
2620- TRACE_FRAME_INIT (call , p -> func , 0 , 0 );
2721+ TRACE_FRAME_INIT (call , p -> func , frame_flags , 0 );
2722+ #ifdef HAVE_FFI
2723+ if (TRACE_FRAME_FFI (call )) {
2724+ call -> call_opline = (const zend_op * )(void * )frame_ffi_func_type ;
2725+ }
2726+ #endif
26212727 call -> prev = frame -> call ;
26222728 call -> used_stack = 0 ;
26232729 frame -> call = call ;
0 commit comments