@@ -115,22 +115,50 @@ static int zend_jit_ffi_send_val(zend_jit_ctx *jit,
115115 uint8_t arg_type = IS_UNDEF ;
116116 uint8_t arg_flags = 0 ;
117117
118- if (!type ) {
119- ZEND_ASSERT (TRACE_FRAME_FFI_ADDR (call ));
120- ZEND_ASSERT (opline -> op2 .num == 1 );
121- ZEND_ASSERT (op1_ffi_type );
122-
123- if (opline -> op1_type == IS_VAR ) {
124- ref = ir_CALL_1 (IR_ADDR , ir_CONST_FC_FUNC (zend_jit_zval_ffi_addr_var ),
125- jit_ZVAL_ADDR (jit , op1_addr ));
118+ if (TRACE_FRAME_FFI_FUNC (call )) {
119+ if (TRACE_FRAME_FFI_FUNC (call ) == TRACE_FRAME_FFI_FUNC_ADDR ) {
120+ ZEND_ASSERT (opline -> op2 .num == 1 );
121+ ZEND_ASSERT (op1_ffi_type );
122+
123+ if (opline -> op1_type & (IS_VAR |IS_TMP_VAR )) {
124+ arg_flags |= ZREG_FFI_ZVAL_DTOR ;
125+ }
126+ if (op1_info & MAY_BE_REF ) {
127+ arg_flags |= ZREG_FFI_ZVAL_DEREF ;
128+ }
129+ ref = jit_Z_PTR (jit , op1_addr );
130+ SET_STACK_TYPE (stack , 0 , IS_OBJECT , 0 );
131+ SET_STACK_REF_EX (stack , 0 , ref , arg_flags );
132+ } else if (TRACE_FRAME_FFI_FUNC (call ) == TRACE_FRAME_FFI_FUNC_STRING ) {
133+ if (opline -> op2 .num == 1 ) {
134+ ZEND_ASSERT (op1_ffi_type );
135+ if (op1_ffi_type -> kind == ZEND_FFI_TYPE_POINTER ) {
136+ arg_flags |= ZREG_FFI_PTR_LOAD ;
137+ }
138+ if (opline -> op1_type & (IS_VAR |IS_TMP_VAR )) {
139+ arg_flags |= ZREG_FFI_ZVAL_DTOR ;
140+ }
141+ if (op1_info & MAY_BE_REF ) {
142+ arg_flags |= ZREG_FFI_ZVAL_DEREF ;
143+ }
144+ ref = jit_Z_PTR (jit , op1_addr );
145+ SET_STACK_TYPE (stack , 0 , IS_OBJECT , 0 );
146+ SET_STACK_REF_EX (stack , 0 , ref , arg_flags );
147+ } else {
148+ ZEND_ASSERT (opline -> op2 .num == 2 );
149+ if (op1_info == MAY_BE_LONG ) {
150+ ref = jit_Z_LVAL (jit , op1_addr );
151+ } else if (op1_info == MAY_BE_NULL ) {
152+ ref = IR_NULL ;
153+ } else {
154+ ZEND_ASSERT (0 && "NIY" );
155+ }
156+ SET_STACK_TYPE (stack , 1 , IS_LONG , 0 );
157+ SET_STACK_REF_EX (stack , 1 , ref , 0 );
158+ }
126159 } else {
127- ref = ir_CALL_1 (IR_ADDR , ir_CONST_FC_FUNC (zend_jit_zval_ffi_addr ),
128- jit_ZVAL_ADDR (jit , op1_addr ));
160+ ZEND_UNREACHABLE ();
129161 }
130-
131- SET_STACK_TYPE (stack , 0 , IS_OBJECT , 0 );
132- SET_STACK_REF_EX (stack , 0 , ref , 0 );
133-
134162 return 1 ;
135163 }
136164 ZEND_ASSERT (type -> kind == ZEND_FFI_TYPE_FUNC );
@@ -328,6 +356,21 @@ static int zend_jit_ffi_send_val(zend_jit_ctx *jit,
328356 return 1 ;
329357}
330358
359+ static ir_ref zend_jit_gc_deref (zend_jit_ctx * jit , ir_ref ref )
360+ {
361+ ir_ref if_ref , ref2 ;
362+
363+ if_ref = ir_IF (ir_EQ (
364+ ir_AND_U32 (
365+ ir_LOAD_U32 (ir_ADD_OFFSET (ref , offsetof(zend_refcounted_h , u .type_info ))),
366+ ir_CONST_U32 (GC_TYPE_MASK )),
367+ ir_CONST_U32 (IS_REFERENCE )));
368+ ir_IF_TRUE (if_ref );
369+ ref2 = jit_Z_PTR_ref (jit , ir_ADD_OFFSET (ref , offsetof(zend_reference , val )));
370+ ir_MERGE_WITH_EMPTY_FALSE (if_ref );
371+ return ir_PHI_2 (IR_ADDR , ref2 , ref );
372+ }
373+
331374static int zend_jit_ffi_do_call (zend_jit_ctx * jit ,
332375 const zend_op * opline ,
333376 const zend_op_array * op_array ,
@@ -339,20 +382,49 @@ static int zend_jit_ffi_do_call(zend_jit_ctx *jit,
339382 zend_jit_trace_stack * stack = call -> stack ;
340383 zend_ffi_type * type = (zend_ffi_type * )(void * )call -> call_opline ;
341384 ir_ref func_ref = (intptr_t )(void * )call -> ce ;
342- uint32_t i , num_args ;
385+ uint32_t i , num_args = TRACE_FRAME_NUM_ARGS ( call ); ;
343386 ir_type ret_type = IR_VOID ;
344387 ir_ref ref = IR_UNUSED ;
345388 zend_ffi_type_kind type_kind ;
346389
347- if (!type ) {
348- ZEND_ASSERT (TRACE_FRAME_FFI_ADDR (call ));
349-
350- ref = STACK_REF (stack , 0 );
351-
352- jit_set_Z_PTR (jit , res_addr , ref );
353- jit_set_Z_TYPE_INFO (jit , res_addr , IS_OBJECT_EX );
354-
355- return 1 ;
390+ if (TRACE_FRAME_FFI_FUNC (call )) {
391+ if (TRACE_FRAME_FFI_FUNC (call ) == TRACE_FRAME_FFI_FUNC_ADDR ) {
392+ ref = STACK_REF (stack , 0 );
393+ if (STACK_FLAGS (stack , 0 ) & ZREG_FFI_ZVAL_DEREF ) {
394+ // TODO: try to remove this dereference ???
395+ ref = zend_jit_gc_deref (jit , ref );
396+ }
397+ if (STACK_FLAGS (stack , 0 ) & ZREG_FFI_ZVAL_DTOR ) {
398+ ref = ir_CALL_1 (IR_ADDR , ir_CONST_FC_FUNC (zend_jit_zval_ffi_addr_var ), ref );
399+ } else {
400+ ref = ir_CALL_1 (IR_ADDR , ir_CONST_FC_FUNC (zend_jit_zval_ffi_addr ), ref );
401+ }
402+ jit_set_Z_PTR (jit , res_addr , ref );
403+ jit_set_Z_TYPE_INFO (jit , res_addr , IS_OBJECT_EX );
404+ } else if (TRACE_FRAME_FFI_FUNC (call ) == TRACE_FRAME_FFI_FUNC_STRING ) {
405+ ZEND_ASSERT (num_args > 0 && STACK_TYPE (stack , 0 ) == IS_OBJECT );
406+ ref = STACK_REF (stack , 0 );
407+ if (STACK_FLAGS (stack , 0 ) & ZREG_FFI_ZVAL_DEREF ) {
408+ // TODO: try to remove this dereference ???
409+ ref = zend_jit_gc_deref (jit , ref );
410+ }
411+ ref = jit_FFI_CDATA_PTR (jit , ref );
412+ if (STACK_FLAGS (stack , 0 ) & ZREG_FFI_PTR_LOAD ) {
413+ ref = ir_LOAD_A (ref );
414+ }
415+ if (num_args == 1 || STACK_REF (stack , 1 ) == IR_NULL ) {
416+ ir_CALL_2 (IR_VOID , ir_CONST_FC_FUNC (zend_jit_zval_string ),
417+ jit_ZVAL_ADDR (jit , res_addr ), ref );
418+ } else {
419+ ZEND_ASSERT (num_args == 2 );
420+ ZEND_ASSERT (STACK_TYPE (stack , 1 ) == IS_LONG );
421+ ir_CALL_3 (IR_VOID , ir_CONST_FC_FUNC (zend_jit_zval_stringl ),
422+ jit_ZVAL_ADDR (jit , res_addr ), ref , STACK_REF (stack , 1 ));
423+ }
424+ } else {
425+ ZEND_UNREACHABLE ();
426+ }
427+ goto cleanup ;
356428 }
357429
358430 ZEND_ASSERT (type -> kind == ZEND_FFI_TYPE_FUNC );
@@ -417,7 +489,6 @@ static int zend_jit_ffi_do_call(zend_jit_ctx *jit,
417489 }
418490 }
419491
420- num_args = TRACE_FRAME_NUM_ARGS (call );
421492 if (num_args ) {
422493 ir_ref * args = alloca (sizeof (ir_ref ) * num_args );
423494
@@ -543,7 +614,12 @@ static int zend_jit_ffi_do_call(zend_jit_ctx *jit,
543614 uint8_t type = STACK_TYPE (stack , i );
544615 ir_ref ref = STACK_REF (stack , i );
545616
546- if (type == IS_STRING ) {
617+ if (STACK_FLAGS (stack , i ) & ZREG_FFI_ZVAL_DEREF ) {
618+ ir_ref if_not_zero = ir_IF (jit_GC_DELREF (jit , ref ));
619+ ir_IF_FALSE (if_not_zero );
620+ jit_ZVAL_DTOR (jit , ref , MAY_BE_REF |MAY_BE_ANY , opline );
621+ ir_MERGE_WITH_EMPTY_TRUE (if_not_zero ); /* don't add to GC roots */
622+ } else if (type == IS_STRING ) {
547623 ir_ref if_interned = ir_IF (ir_AND_U32 (
548624 ir_LOAD_U32 (ir_ADD_OFFSET (ref , offsetof(zend_refcounted , gc .u .type_info ))),
549625 ir_CONST_U32 (IS_STR_INTERNED )));
@@ -565,12 +641,14 @@ static int zend_jit_ffi_do_call(zend_jit_ctx *jit,
565641 }
566642 }
567643
568- func_ref = (intptr_t )(void * )call -> ce ;
569- if (!IR_IS_CONST_REF (func_ref )) {
570- ir_ref if_not_zero = ir_IF (jit_GC_DELREF (jit , func_ref ));
571- ir_IF_FALSE (if_not_zero );
572- jit_ZVAL_DTOR (jit , func_ref , MAY_BE_OBJECT , opline );
573- ir_MERGE_WITH_EMPTY_TRUE (if_not_zero ); /* don't add to GC roots */
644+ if (!TRACE_FRAME_FFI_FUNC (call )) {
645+ func_ref = (intptr_t )(void * )call -> ce ;
646+ if (!IR_IS_CONST_REF (func_ref )) {
647+ ir_ref if_not_zero = ir_IF (jit_GC_DELREF (jit , func_ref ));
648+ ir_IF_FALSE (if_not_zero );
649+ jit_ZVAL_DTOR (jit , func_ref , MAY_BE_OBJECT , opline );
650+ ir_MERGE_WITH_EMPTY_TRUE (if_not_zero ); /* don't add to GC roots */
651+ }
574652 }
575653
576654 return 1 ;
0 commit comments