@@ -93,10 +93,7 @@ static int zend_jit_ffi_init_call_obj(zend_jit_ctx *jit,
9393 return 0 ;
9494 }
9595
96- * ffi_func_ref = ir_LOAD_A (jit_FFI_CDATA_PTR (jit , obj_ref ));
97- if (type -> func .abi == ZEND_FFI_ABI_FASTCALL ) {
98- * ffi_func_ref = ir_CAST_FC_FUNC (* ffi_func_ref );
99- }
96+ * ffi_func_ref = obj_ref ;
10097
10198 return 1 ;
10299}
@@ -115,6 +112,8 @@ static int zend_jit_ffi_send_val(zend_jit_ctx *jit,
115112 zend_jit_trace_stack * stack = call -> stack ;
116113 zend_ffi_type * type = (zend_ffi_type * )(void * )call -> call_opline ;
117114 ir_ref ref = IR_UNUSED ;
115+ uint8_t arg_type = IS_UNDEF ;
116+ uint8_t arg_flags = 0 ;
118117
119118 ZEND_ASSERT (type -> kind == ZEND_FFI_TYPE_FUNC );
120119 if (type -> attr & ZEND_FFI_ATTR_VARIADIC ) {
@@ -233,16 +232,28 @@ static int zend_jit_ffi_send_val(zend_jit_ctx *jit,
233232 case ZEND_FFI_TYPE_POINTER :
234233 if ((op1_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_STRING
235234 && ZEND_FFI_TYPE (type -> pointer .type )-> kind == ZEND_FFI_TYPE_CHAR ) {
236- ref = ir_ADD_OFFSET (jit_Z_PTR (jit , op1_addr ), offsetof(zend_string , val ));
235+ arg_type = IS_STRING ;
236+ ref = jit_Z_PTR (jit , op1_addr );
237+ if (opline -> op1_type & (IS_VAR |IS_TMP_VAR )) {
238+ arg_flags |= ZREG_FFI_ZVAL_DTOR ;
239+ }
237240 } else if (op1_ffi_type
238241 && op1_ffi_type -> kind == ZEND_FFI_TYPE_POINTER
239242 && ZEND_FFI_TYPE (type -> pointer .type ) == ZEND_FFI_TYPE (op1_ffi_type -> pointer .type )) {
240- ref = jit_FFI_CDATA_PTR (jit , jit_Z_PTR (jit , op1_addr ));
241- ref = ir_LOAD_A (ref ); // TODO: is this always necessary ???
243+ arg_type = IS_OBJECT ;
244+ ref = jit_Z_PTR (jit , op1_addr );
245+ arg_flags |= ZREG_FFI_PTR_LOAD ;
246+ if (opline -> op1_type & (IS_VAR |IS_TMP_VAR )) {
247+ arg_flags |= ZREG_FFI_ZVAL_DTOR ;
248+ }
242249 } else if (op1_ffi_type
243250 && op1_ffi_type -> kind == ZEND_FFI_TYPE_ARRAY
244251 && ZEND_FFI_TYPE (type -> pointer .type ) == ZEND_FFI_TYPE (op1_ffi_type -> array .type )) {
245- ref = jit_FFI_CDATA_PTR (jit , jit_Z_PTR (jit , op1_addr ));
252+ arg_type = IS_OBJECT ;
253+ ref = jit_Z_PTR (jit , op1_addr );
254+ if (opline -> op1_type & (IS_VAR |IS_TMP_VAR )) {
255+ arg_flags |= ZREG_FFI_ZVAL_DTOR ;
256+ }
246257 } else {
247258 ZEND_UNREACHABLE ();
248259 }
@@ -264,13 +275,18 @@ static int zend_jit_ffi_send_val(zend_jit_ctx *jit,
264275 } else if (op1_info == MAY_BE_DOUBLE ) {
265276 ref = jit_Z_DVAL (jit , op1_addr );
266277 } else if ((op1_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_STRING ) {
267- ref = ir_ADD_OFFSET (jit_Z_PTR (jit , op1_addr ), offsetof(zend_string , val ));
278+ arg_type = IS_STRING ;
279+ ref = jit_Z_PTR (jit , op1_addr );
280+ if (opline -> op1_type & (IS_VAR |IS_TMP_VAR )) {
281+ arg_flags |= ZREG_FFI_ZVAL_DTOR ;
282+ }
268283 } else {
269284 ZEND_UNREACHABLE ();
270285 }
271286 }
272287
273- SET_STACK_REF (stack , opline -> op2 .num - 1 , ref );
288+ SET_STACK_TYPE (stack , opline -> op2 .num - 1 , arg_type , 0 );
289+ SET_STACK_REF_EX (stack , opline -> op2 .num - 1 , ref , arg_flags );
274290
275291 return 1 ;
276292}
@@ -340,13 +356,31 @@ static int zend_jit_ffi_do_call(zend_jit_ctx *jit,
340356 ZEND_UNREACHABLE ();
341357 }
342358
359+ if (!IR_IS_CONST_REF (func_ref )) {
360+ func_ref = ir_LOAD_A (jit_FFI_CDATA_PTR (jit , func_ref ));
361+ if (type -> func .abi == ZEND_FFI_ABI_FASTCALL ) {
362+ func_ref = ir_CAST_FC_FUNC (func_ref );
363+ }
364+ }
365+
343366 num_args = TRACE_FRAME_NUM_ARGS (call );
344367 if (num_args ) {
345368 ir_ref * args = alloca (sizeof (ir_ref ) * num_args );
346369 zend_jit_trace_stack * stack = call -> stack ;
347370
348371 for (i = 0 ; i < num_args ; i ++ ) {
349- args [i ] = STACK_REF (stack , i );
372+ uint8_t type = STACK_TYPE (stack , i );
373+ ir_ref ref = STACK_REF (stack , i );
374+
375+ if (type == IS_STRING ) {
376+ ref = ir_ADD_OFFSET (ref , offsetof(zend_string , val ));
377+ } else if (type == IS_OBJECT ) {
378+ ref = jit_FFI_CDATA_PTR (jit , ref );
379+ if (STACK_FLAGS (stack , i ) & ZREG_FFI_PTR_LOAD ) {
380+ ref = ir_LOAD_A (ref );
381+ }
382+ }
383+ args [i ] = ref ;
350384 }
351385 ref = ir_CALL_N (ret_type , func_ref , num_args , args );
352386 } else {
@@ -443,6 +477,44 @@ static int zend_jit_ffi_do_call(zend_jit_ctx *jit,
443477 }
444478 }
445479
480+ if (num_args ) {
481+ zend_jit_trace_stack * stack = call -> stack ;
482+
483+ for (i = 0 ; i < num_args ; i ++ ) {
484+ if (STACK_FLAGS (stack , i ) & ZREG_FFI_ZVAL_DTOR ) {
485+ uint8_t type = STACK_TYPE (stack , i );
486+ ir_ref ref = STACK_REF (stack , i );
487+
488+ if (type == IS_STRING ) {
489+ ir_ref if_interned = ir_IF (ir_AND_U32 (
490+ ir_LOAD_U32 (ir_ADD_OFFSET (ref , offsetof(zend_refcounted , gc .u .type_info ))),
491+ ir_CONST_U32 (IS_STR_INTERNED )));
492+ ir_IF_FALSE (if_interned );
493+ ir_ref if_not_zero = ir_IF (jit_GC_DELREF (jit , ref ));
494+ ir_IF_FALSE (if_not_zero );
495+ jit_ZVAL_DTOR (jit , ref , MAY_BE_STRING , opline );
496+ ir_MERGE_WITH_EMPTY_TRUE (if_not_zero );
497+ ir_MERGE_WITH_EMPTY_TRUE (if_interned );
498+ } else if (type == IS_OBJECT ) {
499+ ir_ref if_not_zero = ir_IF (jit_GC_DELREF (jit , ref ));
500+ ir_IF_FALSE (if_not_zero );
501+ jit_ZVAL_DTOR (jit , ref , MAY_BE_OBJECT , opline );
502+ ir_MERGE_WITH_EMPTY_TRUE (if_not_zero ); /* don't add to GC roots */
503+ } else {
504+ ZEND_ASSERT (0 );
505+ }
506+ }
507+ }
508+ }
509+
510+ func_ref = (intptr_t )(void * )call -> ce ;
511+ if (!IR_IS_CONST_REF (func_ref )) {
512+ ir_ref if_not_zero = ir_IF (jit_GC_DELREF (jit , func_ref ));
513+ ir_IF_FALSE (if_not_zero );
514+ jit_ZVAL_DTOR (jit , func_ref , MAY_BE_OBJECT , opline );
515+ ir_MERGE_WITH_EMPTY_TRUE (if_not_zero ); /* don't add to GC roots */
516+ }
517+
446518 return 1 ;
447519}
448520
0 commit comments