Skip to content

Commit 6232403

Browse files
committed
JIT for FFI::new() with 2 and 3 arguments
1 parent 53bf1b1 commit 6232403

File tree

3 files changed

+127
-71
lines changed

3 files changed

+127
-71
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,68 @@ static bool zend_jit_ffi_supported_func(zend_ffi_type *type)
107107
return true;
108108
}
109109

110+
static bool zend_jit_is_send_bool_const(const zend_jit_trace_rec *p)
111+
{
112+
if (p->op == ZEND_JIT_TRACE_VM
113+
&& (p->opline->opcode == ZEND_SEND_VAL
114+
|| p->opline->opcode == ZEND_SEND_VAL_EX)
115+
&& p->opline->op1_type == IS_CONST) {
116+
zval *zv = RT_CONSTANT(p->opline, p->opline->op1);
117+
118+
if (Z_TYPE_P(zv) <= IS_STRING) {
119+
return true;
120+
}
121+
}
122+
return false;
123+
}
124+
125+
static zend_ffi_type* zend_jit_ffi_supported_new(const zend_op *opline, HashTable *ffi_symbols, const zend_jit_trace_rec *p)
126+
{
127+
zend_ffi_type *type = NULL;
128+
129+
if ((opline->extended_value == 1
130+
|| opline->extended_value == 2
131+
|| opline->extended_value == 3)
132+
&& (p+1)->op == ZEND_JIT_TRACE_INIT_CALL
133+
&& (p+2)->op == ZEND_JIT_TRACE_VM) {
134+
if (((p+2)->opline->opcode == ZEND_SEND_VAL
135+
|| (p+2)->opline->opcode == ZEND_SEND_VAL_EX)
136+
&& (p+2)->opline->op1_type == IS_CONST) {
137+
zval *zv = RT_CONSTANT((p+2)->opline, (p+2)->opline->op1);
138+
139+
if (Z_TYPE_P(zv) == IS_STRING) {
140+
zend_ffi_dcl *dcl = zend_ffi_api->cache_type_get(Z_STR_P(zv), ffi_symbols);
141+
142+
if (dcl) {
143+
type = dcl->type;
144+
p += 3;
145+
}
146+
}
147+
} else if ((p+2)->opline->opcode == ZEND_SEND_VAR_EX
148+
&& (p+3)->op == ZEND_JIT_TRACE_OP1_TYPE
149+
&& (p+3)->ce == zend_ffi_api->ctype_ce
150+
&& (p+4)->op == ZEND_JIT_TRACE_OP1_FFI_TYPE) {
151+
type = (zend_ffi_type*)(p+4)->ptr;
152+
p += 5;
153+
}
154+
}
155+
156+
if (type
157+
&& !ZEND_FFI_TYPE_IS_OWNED(type)
158+
&& (type->attr & ZEND_FFI_ATTR_PERSISTENT)
159+
&& type->size != 0
160+
&& (opline->extended_value == 1
161+
|| (opline->extended_value == 2
162+
&& zend_jit_is_send_bool_const(p))
163+
|| (opline->extended_value == 3
164+
&& zend_jit_is_send_bool_const(p)
165+
&& zend_jit_is_send_bool_const(p + 1)))) {
166+
return type;
167+
}
168+
169+
return NULL;
170+
}
171+
110172
static bool zend_jit_ffi_compatible(zend_ffi_type *dst_type, uint32_t src_info, zend_ffi_type *src_type)
111173
{
112174
dst_type = ZEND_FFI_TYPE(dst_type);

ext/opcache/jit/zend_jit_ir_ffi.c

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -335,11 +335,34 @@ static int zend_jit_ffi_send_val(zend_jit_ctx *jit,
335335
SET_STACK_REF_EX(stack, 2, ref, 0);
336336
}
337337
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_NEW) {
338-
ZEND_ASSERT(opline->op2.num == 1);
339-
/* nothing to do */
338+
if (opline->op2.num == 1) {
339+
if (op1_ffi_type && (opline->op1_type & (IS_VAR|IS_TMP_VAR))) {
340+
arg_flags |= ZREG_FFI_ZVAL_DTOR;
341+
if (op1_info & MAY_BE_REF) {
342+
arg_flags |= ZREG_FFI_ZVAL_DEREF;
343+
}
344+
ref = jit_Z_PTR(jit, op1_addr);
345+
SET_STACK_TYPE(stack, 0, IS_OBJECT, 0);
346+
SET_STACK_REF_EX(stack, 0, ref, arg_flags);
347+
}
348+
} else if (opline->op2.num == 2) {
349+
ZEND_ASSERT(opline->op1_type == IS_CONST);
350+
SET_STACK_TYPE(stack, 1, zend_is_true(RT_CONSTANT(opline, opline->op1)) ? IS_TRUE : IS_FALSE, 0);
351+
} else if (opline->op2.num == 3) {
352+
ZEND_ASSERT(opline->op1_type == IS_CONST);
353+
SET_STACK_TYPE(stack, 2, zend_is_true(RT_CONSTANT(opline, opline->op1)) ? IS_TRUE : IS_FALSE, 0);
354+
}
340355
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_TYPE) {
341356
ZEND_ASSERT(opline->op2.num == 1);
342-
/* nothing to do */
357+
if (op1_ffi_type && (opline->op1_type & (IS_VAR|IS_TMP_VAR))) {
358+
arg_flags |= ZREG_FFI_ZVAL_DTOR;
359+
if (op1_info & MAY_BE_REF) {
360+
arg_flags |= ZREG_FFI_ZVAL_DEREF;
361+
}
362+
ref = jit_Z_PTR(jit, op1_addr);
363+
SET_STACK_TYPE(stack, 0, IS_OBJECT, 0);
364+
SET_STACK_REF_EX(stack, 0, ref, arg_flags);
365+
}
343366
} else {
344367
ZEND_UNREACHABLE();
345368
}
@@ -768,19 +791,32 @@ static int zend_jit_ffi_do_call(zend_jit_ctx *jit,
768791
}
769792
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_NEW) {
770793
if (res_addr) {
794+
uint32_t flags = ZEND_FFI_FLAG_OWNED;
795+
796+
if (num_args > 1 && STACK_TYPE(stack, 1) == IS_FALSE) {
797+
flags &= ~ZEND_FFI_FLAG_OWNED;
798+
}
799+
if (num_args > 2 && STACK_TYPE(stack, 2) == IS_TRUE) {
800+
flags |= ZEND_FFI_FLAG_PERSISTENT;
801+
}
802+
// TODO: ZEND_FFI_FLAG_CONST flag ???
803+
if (flags & ZEND_FFI_FLAG_PERSISTENT) {
804+
ref = ir_CALL_2(IR_ADDR, ir_CONST_FUNC(calloc), ir_CONST_LONG(1), ir_CONST_ADDR(type->size));
805+
} else {
771806
#if ZEND_DEBUG
772-
ref = ir_CALL_6(IR_ADDR, ir_CONST_FC_FUNC(_ecalloc),
773-
ir_CONST_LONG(1),
774-
ir_CONST_ADDR(type->size),
775-
op_array->filename ? ir_CONST_ADDR(op_array->filename->val) : IR_NULL,
776-
ir_CONST_U32(opline ? opline->lineno : 0),
777-
IR_NULL,
778-
ir_CONST_U32(0));
807+
ref = ir_CALL_6(IR_ADDR, ir_CONST_FC_FUNC(_ecalloc),
808+
ir_CONST_LONG(1),
809+
ir_CONST_ADDR(type->size),
810+
op_array->filename ? ir_CONST_ADDR(op_array->filename->val) : IR_NULL,
811+
ir_CONST_U32(opline ? opline->lineno : 0),
812+
IR_NULL,
813+
ir_CONST_U32(0));
779814
#else
780-
ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(_ecalloc), ir_CONST_LONG(1), ir_CONST_ADDR(type->size));
815+
ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(_ecalloc), ir_CONST_LONG(1), ir_CONST_ADDR(type->size));
781816
#endif
817+
}
782818
ref = ir_CALL_2(IR_ADDR, ir_CONST_FUNC(zend_ffi_api->cdata_create), ref, ir_CONST_ADDR(type));
783-
ir_STORE(ir_ADD_OFFSET(ref, offsetof(zend_ffi_cdata, flags)), ir_CONST_U32(ZEND_FFI_FLAG_OWNED));
819+
ir_STORE(ir_ADD_OFFSET(ref, offsetof(zend_ffi_cdata, flags)), ir_CONST_U32(flags));
784820
jit_set_Z_PTR(jit, res_addr, ref);
785821
jit_set_Z_TYPE_INFO(jit, res_addr, IS_OBJECT_EX);
786822
}

ext/opcache/jit/zend_jit_trace.c

Lines changed: 17 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6946,66 +6946,24 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
69466946
zend_string *name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
69476947

69486948
if (zend_string_equals_literal_ci(name, "new")) {
6949-
if (opline->extended_value == 1
6950-
// TODO: support for FFI::new() with 2 and 3 arguments ???
6951-
&& (p+1)->op == ZEND_JIT_TRACE_INIT_CALL
6952-
&& (p+2)->op == ZEND_JIT_TRACE_VM) {
6953-
if (((p+2)->opline->opcode == ZEND_SEND_VAL
6954-
|| (p+2)->opline->opcode == ZEND_SEND_VAL_EX)
6955-
&& (p+2)->opline->op1_type == IS_CONST) {
6956-
zval *zv = RT_CONSTANT((p+2)->opline, (p+2)->opline->op1);
6957-
6958-
if (Z_TYPE_P(zv) == IS_STRING) {
6959-
zend_ffi_dcl *dcl = zend_ffi_api->cache_type_get(Z_STR_P(zv), op1_ffi_symbols);
6960-
6961-
if (dcl
6962-
&& !ZEND_FFI_TYPE_IS_OWNED(dcl->type)
6963-
&& (dcl->type->attr & ZEND_FFI_ATTR_PERSISTENT)
6964-
&& dcl->type->size != 0) {
6965-
if (!ffi_info) {
6966-
ffi_info = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_jit_ffi_info));
6967-
}
6968-
if (!zend_jit_ffi_symbols_guard(&ctx, opline, ssa,
6969-
ssa_op->op1_use, -1, op1_info, op1_addr, op1_ffi_symbols, ffi_info)) {
6970-
goto jit_failure;
6971-
}
6972-
frame_flags = TRACE_FRAME_MASK_FFI | TRACE_FRAME_FFI_FUNC_NEW;
6973-
frame_ffi_func_type = dcl->type;
6974-
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
6975-
frame_ffi_func_ref = jit_Z_PTR(jit, op1_addr);
6976-
} else {
6977-
frame_ffi_func_ref = IR_UNUSED;
6978-
}
6979-
goto done;
6980-
}
6981-
}
6982-
} else if ((p+2)->opline->opcode == ZEND_SEND_VAR_EX
6983-
&& (p+3)->op == ZEND_JIT_TRACE_OP1_TYPE
6984-
&& (p+3)->ce == zend_ffi_api->ctype_ce
6985-
&& (p+4)->op == ZEND_JIT_TRACE_OP1_FFI_TYPE) {
6986-
zend_ffi_type *type = (zend_ffi_type*)(p+4)->ptr;
6987-
6988-
if (!ZEND_FFI_TYPE_IS_OWNED(type)
6989-
&& (type->attr & ZEND_FFI_ATTR_PERSISTENT)
6990-
&& type->size != 0) {
6991-
if (!ffi_info) {
6992-
ffi_info = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_jit_ffi_info));
6993-
}
6994-
if (!zend_jit_ffi_symbols_guard(&ctx, opline, ssa,
6995-
ssa_op->op1_use, -1, op1_info, op1_addr, op1_ffi_symbols, ffi_info)) {
6996-
goto jit_failure;
6997-
}
6998-
// TODO: Guard for FFI::CType argument
6999-
frame_flags = TRACE_FRAME_MASK_FFI | TRACE_FRAME_FFI_FUNC_NEW;
7000-
frame_ffi_func_type = type;
7001-
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
7002-
frame_ffi_func_ref = jit_Z_PTR(jit, op1_addr);
7003-
} else {
7004-
frame_ffi_func_ref = IR_UNUSED;
7005-
}
7006-
goto done;
7007-
}
6949+
zend_ffi_type *type = zend_jit_ffi_supported_new(opline, op1_ffi_symbols, p);
6950+
if (type) {
6951+
if (!ffi_info) {
6952+
ffi_info = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_jit_ffi_info));
6953+
}
6954+
if (!zend_jit_ffi_symbols_guard(&ctx, opline, ssa,
6955+
ssa_op->op1_use, -1, op1_info, op1_addr, op1_ffi_symbols, ffi_info)) {
6956+
goto jit_failure;
6957+
}
6958+
// TODO: Guard for FFI::CType argument ???
6959+
frame_flags = TRACE_FRAME_MASK_FFI | TRACE_FRAME_FFI_FUNC_NEW;
6960+
frame_ffi_func_type = type;
6961+
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
6962+
frame_ffi_func_ref = jit_Z_PTR(jit, op1_addr);
6963+
} else {
6964+
frame_ffi_func_ref = IR_UNUSED;
70086965
}
6966+
goto done;
70096967
}
70106968
} else if (zend_string_equals_literal_ci(name, "type")) {
70116969
if (opline->extended_value == 1

0 commit comments

Comments
 (0)