Skip to content

Commit 5caa01e

Browse files
committed
JIR for FFI::string()
1 parent 1f4654c commit 5caa01e

File tree

6 files changed

+160
-73
lines changed

6 files changed

+160
-73
lines changed

ext/opcache/jit/zend_jit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ void zend_jit_restart(void);
184184

185185
#define ZREG_FFI_PTR_LOAD (1<<3)
186186
#define ZREG_FFI_ZVAL_DTOR (1<<4)
187+
#define ZREG_FFI_ZVAL_DEREF (1<<5)
187188

188189
#define ZREG_NONE -1
189190

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3373,6 +3373,15 @@ static void ZEND_FASTCALL zend_jit_zval_string(zval *zv, const char *str)
33733373
}
33743374
}
33753375

3376+
static void ZEND_FASTCALL zend_jit_zval_stringl(zval *zv, const char *str, size_t len)
3377+
{
3378+
if (str) {
3379+
ZVAL_STRINGL(zv, str, len);
3380+
} else {
3381+
ZVAL_NULL(zv);
3382+
}
3383+
}
3384+
33763385
static void ZEND_FASTCALL zend_jit_zval_ffi_ptr(zval *zv, zend_ffi_type *type, void *ptr)
33773386
{
33783387
ZEND_ASSERT(type->kind == ZEND_FFI_TYPE_POINTER);
@@ -3421,18 +3430,11 @@ static void ZEND_FASTCALL zend_jit_zval_ffi_obj(zval *zv, zend_ffi_type *type, v
34213430
}
34223431
}
34233432

3424-
static zend_ffi_cdata* ZEND_FASTCALL zend_jit_zval_ffi_addr(zval *zv)
3433+
static zend_ffi_cdata* ZEND_FASTCALL zend_jit_zval_ffi_addr(zend_ffi_cdata *cdata)
34253434
{
3426-
zend_ffi_cdata *cdata, *new_cdata;
3435+
zend_ffi_cdata *new_cdata;
34273436
zend_ffi_type *type, *new_type;
34283437

3429-
if (Z_TYPE_P(zv) == IS_INDIRECT) {
3430-
zv = Z_INDIRECT_P(zv);
3431-
}
3432-
ZVAL_DEREF(zv);
3433-
ZEND_ASSERT(Z_TYPE_P(zv) == IS_OBJECT);
3434-
3435-
cdata = (zend_ffi_cdata*)Z_OBJ_P(zv);
34363438
type = ZEND_FFI_TYPE(cdata->type);
34373439

34383440
// if (GC_REFCOUNT(&cdata->std) == 1 && Z_REFCOUNT_P(arg) == 1 && type->kind == ZEND_FFI_TYPE_POINTER
@@ -3467,19 +3469,11 @@ static zend_ffi_cdata* ZEND_FASTCALL zend_jit_zval_ffi_addr(zval *zv)
34673469
return new_cdata;
34683470
}
34693471

3470-
static zend_ffi_cdata* ZEND_FASTCALL zend_jit_zval_ffi_addr_var(zval *zv)
3472+
static zend_ffi_cdata* ZEND_FASTCALL zend_jit_zval_ffi_addr_var(zend_ffi_cdata *cdata)
34713473
{
3472-
zend_ffi_cdata *cdata, *new_cdata;
3474+
zend_ffi_cdata *new_cdata;
34733475
zend_ffi_type *type, *new_type;
3474-
zval *arg = zv;
3475-
3476-
if (Z_TYPE_P(zv) == IS_INDIRECT) {
3477-
zv = Z_INDIRECT_P(zv);
3478-
}
3479-
ZVAL_DEREF(zv);
3480-
ZEND_ASSERT(Z_TYPE_P(zv) == IS_OBJECT);
34813476

3482-
cdata = (zend_ffi_cdata*)Z_OBJ_P(zv);
34833477
type = ZEND_FFI_TYPE(cdata->type);
34843478

34853479
// if (GC_REFCOUNT(&cdata->std) == 1 && Z_REFCOUNT_P(arg) == 1 && type->kind == ZEND_FFI_TYPE_POINTER
@@ -3511,23 +3505,16 @@ static zend_ffi_cdata* ZEND_FASTCALL zend_jit_zval_ffi_addr_var(zval *zv)
35113505
new_cdata->ptr = (void*)&new_cdata->ptr_holder;
35123506
new_cdata->ptr_holder = cdata->ptr;
35133507

3514-
if (Z_REFCOUNTED_P(arg)) {
3515-
zend_refcounted *ref = Z_COUNTED_P(arg);
3516-
3517-
if (!GC_DELREF(ref)) {
3518-
if (ref == (zend_refcounted*)cdata || GC_REFCOUNT(&cdata->std) == 1) {
3519-
if (ZEND_FFI_TYPE_IS_OWNED(cdata->type)) {
3520-
/* transfer type ownership */
3521-
cdata->type = type;
3522-
new_type->pointer.type = ZEND_FFI_TYPE_MAKE_OWNED(type);
3523-
}
3524-
if (cdata->flags & ZEND_FFI_FLAG_OWNED) {
3525-
/* transfer ownership */
3526-
cdata->flags &= ~ZEND_FFI_FLAG_OWNED;
3527-
new_cdata->flags |= ZEND_FFI_FLAG_OWNED;
3528-
}
3529-
}
3530-
rc_dtor_func(ref);
3508+
if (GC_REFCOUNT(&cdata->std) == 1 /*&& Z_REFCOUNT_P(arg) == 1*/) {
3509+
if (ZEND_FFI_TYPE_IS_OWNED(cdata->type)) {
3510+
/* transfer type ownership */
3511+
cdata->type = type;
3512+
new_type->pointer.type = ZEND_FFI_TYPE_MAKE_OWNED(type);
3513+
}
3514+
if (cdata->flags & ZEND_FFI_FLAG_OWNED) {
3515+
/* transfer ownership */
3516+
cdata->flags &= ~ZEND_FFI_FLAG_OWNED;
3517+
new_cdata->flags |= ZEND_FFI_FLAG_OWNED;
35313518
}
35323519
}
35333520

ext/opcache/jit/zend_jit_internal.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,20 @@ struct _zend_jit_trace_stack_frame {
575575
#define TRACE_FRAME_MASK_ALWAYS_RELEASE_THIS 0x00000400
576576

577577
#define TRACE_FRAME_MASK_FFI 0x00000800
578-
#define TRACE_FRAME_MASK_FFI_ADDR 0x00001000
578+
#define TRACE_FRAME_MASK_FFI_FUNC 0x0000f000
579+
580+
#define TRACE_FRAME_FFI_FUNC_NEW 0x00001000
581+
#define TRACE_FRAME_FFI_FUNC_FREE 0x00002000
582+
#define TRACE_FRAME_FFI_FUNC_CAST 0x00003000
583+
#define TRACE_FRAME_FFI_FUNC_TYPEOF 0x00004000
584+
#define TRACE_FRAME_FFI_FUNC_ARRAY_TYPE 0x00005000
585+
#define TRACE_FRAME_FFI_FUNC_ADDR 0x00006000
586+
#define TRACE_FRAME_FFI_FUNC_SIZEOF 0x00007000
587+
#define TRACE_FRAME_FFI_FUNC_MEMCPY 0x00008000
588+
#define TRACE_FRAME_FFI_FUNC_MEMCMP 0x00009000
589+
#define TRACE_FRAME_FFI_FUNC_MEMSET 0x0000a000
590+
#define TRACE_FRAME_FFI_FUNC_STRING 0x0000b000
591+
#define TRACE_FRAME_FFI_FUNC_IS_NULL 0x0000c000
579592

580593

581594
#define TRACE_FRAME_INIT(frame, _func, _flags, num_args) do { \
@@ -617,8 +630,8 @@ struct _zend_jit_trace_stack_frame {
617630
((frame)->_info & TRACE_FRAME_MASK_ALWAYS_RELEASE_THIS)
618631
#define TRACE_FRAME_FFI(frame) \
619632
((frame)->_info & TRACE_FRAME_MASK_FFI)
620-
#define TRACE_FRAME_FFI_ADDR(frame) \
621-
((frame)->_info & TRACE_FRAME_MASK_FFI_ADDR)
633+
#define TRACE_FRAME_FFI_FUNC(frame) \
634+
((frame)->_info & TRACE_FRAME_MASK_FFI_FUNC)
622635

623636
#define TRACE_FRAME_SET_UNKNOWN_NUM_ARGS(frame) do { \
624637
(frame)->_info |= (0xffffu << TRACE_FRAME_SHIFT_NUM_ARGS); \

ext/opcache/jit/zend_jit_ir.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3102,6 +3102,7 @@ static void zend_jit_setup_disasm(void)
31023102

31033103
#ifdef HAVE_FFI
31043104
REGISTER_HELPER(zend_jit_zval_string);
3105+
REGISTER_HELPER(zend_jit_zval_stringl);
31053106
REGISTER_HELPER(zend_jit_zval_ffi_ptr);
31063107
REGISTER_HELPER(zend_jit_zval_ffi_obj);
31073108
REGISTER_HELPER(zend_jit_zval_ffi_addr);

ext/opcache/jit/zend_jit_ir_ffi.c

Lines changed: 110 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
331374
static 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;

ext/opcache/jit/zend_jit_trace.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6987,9 +6987,16 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
69876987
|| zend_string_equals_literal_ci(Z_STR_P(zv), "\\FFI"))) {
69886988
zval *zv = RT_CONSTANT(opline, opline->op2);
69896989
if (Z_TYPE_P(zv) == IS_STRING
6990-
&& zend_string_equals_literal(Z_STR_P(zv), "addr")
6990+
&& zend_string_equals_literal_ci(Z_STR_P(zv), "addr")
69916991
&& opline->extended_value == 1) {
6992-
frame_flags = TRACE_FRAME_MASK_FFI | TRACE_FRAME_MASK_FFI_ADDR;
6992+
frame_flags = TRACE_FRAME_MASK_FFI | TRACE_FRAME_FFI_FUNC_ADDR;
6993+
frame_ffi_func_type = NULL;
6994+
frame_ffi_func_ref = IR_UNUSED;
6995+
goto done;
6996+
} else if (Z_TYPE_P(zv) == IS_STRING
6997+
&& zend_string_equals_literal_ci(Z_STR_P(zv), "string")
6998+
&& (opline->extended_value == 1 || opline->extended_value == 2)) {
6999+
frame_flags = TRACE_FRAME_MASK_FFI | TRACE_FRAME_FFI_FUNC_STRING;
69937000
frame_ffi_func_type = NULL;
69947001
frame_ffi_func_ref = IR_UNUSED;
69957002
goto done;

0 commit comments

Comments
 (0)