Skip to content

Commit 082d01d

Browse files
committed
JIT for FFI::memcpy(), FFI::memcmp() and FFI::memset()
1 parent c3ec5a7 commit 082d01d

File tree

2 files changed

+260
-1
lines changed

2 files changed

+260
-1
lines changed

ext/opcache/jit/zend_jit_ir_ffi.c

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,141 @@ static int zend_jit_ffi_send_val(zend_jit_ctx *jit,
178178
SET_STACK_TYPE(stack, 1, IS_LONG, 0);
179179
SET_STACK_REF_EX(stack, 1, ref, 0);
180180
}
181+
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_MEMCPY) {
182+
if (opline->op2.num == 1) {
183+
ZEND_ASSERT(op1_ffi_type);
184+
if (op1_ffi_type->kind == ZEND_FFI_TYPE_POINTER) {
185+
arg_flags |= ZREG_FFI_PTR_LOAD;
186+
}
187+
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
188+
arg_flags |= ZREG_FFI_ZVAL_DTOR;
189+
}
190+
if (op1_info & MAY_BE_REF) {
191+
arg_flags |= ZREG_FFI_ZVAL_DEREF;
192+
}
193+
ref = jit_Z_PTR(jit, op1_addr);
194+
SET_STACK_TYPE(stack, 0, IS_OBJECT, 0);
195+
SET_STACK_REF_EX(stack, 0, ref, arg_flags);
196+
} else if (opline->op2.num == 2) {
197+
if (op1_ffi_type) {
198+
if (op1_ffi_type->kind == ZEND_FFI_TYPE_POINTER) {
199+
arg_flags |= ZREG_FFI_PTR_LOAD;
200+
}
201+
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
202+
arg_flags |= ZREG_FFI_ZVAL_DTOR;
203+
}
204+
if (op1_info & MAY_BE_REF) {
205+
arg_flags |= ZREG_FFI_ZVAL_DEREF;
206+
}
207+
ref = jit_Z_PTR(jit, op1_addr);
208+
SET_STACK_TYPE(stack, 1, IS_OBJECT, 0);
209+
SET_STACK_REF_EX(stack, 1, ref, arg_flags);
210+
} else {
211+
ZEND_ASSERT((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING);
212+
if (op1_info & MAY_BE_REF) {
213+
arg_flags |= ZREG_FFI_ZVAL_DEREF;
214+
}
215+
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
216+
arg_flags |= ZREG_FFI_ZVAL_DTOR;
217+
}
218+
ref = jit_Z_PTR(jit, op1_addr);
219+
SET_STACK_TYPE(stack, 1, IS_STRING, 0);
220+
SET_STACK_REF_EX(stack, 1, ref, arg_flags);
221+
}
222+
} else {
223+
ZEND_ASSERT(opline->op2.num == 3);
224+
ZEND_ASSERT(op1_info == MAY_BE_LONG);
225+
ref = jit_Z_LVAL(jit, op1_addr);
226+
SET_STACK_TYPE(stack, 2, IS_LONG, 0);
227+
SET_STACK_REF_EX(stack, 2, ref, 0);
228+
}
229+
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_MEMCMP) {
230+
if (opline->op2.num == 1) {
231+
if (op1_ffi_type) {
232+
if (op1_ffi_type->kind == ZEND_FFI_TYPE_POINTER) {
233+
arg_flags |= ZREG_FFI_PTR_LOAD;
234+
}
235+
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
236+
arg_flags |= ZREG_FFI_ZVAL_DTOR;
237+
}
238+
if (op1_info & MAY_BE_REF) {
239+
arg_flags |= ZREG_FFI_ZVAL_DEREF;
240+
}
241+
ref = jit_Z_PTR(jit, op1_addr);
242+
SET_STACK_TYPE(stack, 0, IS_OBJECT, 0);
243+
SET_STACK_REF_EX(stack, 0, ref, arg_flags);
244+
} else {
245+
ZEND_ASSERT((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING);
246+
if (op1_info & MAY_BE_REF) {
247+
arg_flags |= ZREG_FFI_ZVAL_DEREF;
248+
}
249+
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
250+
arg_flags |= ZREG_FFI_ZVAL_DTOR;
251+
}
252+
ref = jit_Z_PTR(jit, op1_addr);
253+
SET_STACK_TYPE(stack, 0, IS_STRING, 0);
254+
SET_STACK_REF_EX(stack, 0, ref, arg_flags);
255+
}
256+
} else if (opline->op2.num == 2) {
257+
if (op1_ffi_type) {
258+
if (op1_ffi_type->kind == ZEND_FFI_TYPE_POINTER) {
259+
arg_flags |= ZREG_FFI_PTR_LOAD;
260+
}
261+
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
262+
arg_flags |= ZREG_FFI_ZVAL_DTOR;
263+
}
264+
if (op1_info & MAY_BE_REF) {
265+
arg_flags |= ZREG_FFI_ZVAL_DEREF;
266+
}
267+
ref = jit_Z_PTR(jit, op1_addr);
268+
SET_STACK_TYPE(stack, 1, IS_OBJECT, 0);
269+
SET_STACK_REF_EX(stack, 1, ref, arg_flags);
270+
} else {
271+
ZEND_ASSERT((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING);
272+
if (op1_info & MAY_BE_REF) {
273+
arg_flags |= ZREG_FFI_ZVAL_DEREF;
274+
}
275+
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
276+
arg_flags |= ZREG_FFI_ZVAL_DTOR;
277+
}
278+
ref = jit_Z_PTR(jit, op1_addr);
279+
SET_STACK_TYPE(stack, 1, IS_STRING, 0);
280+
SET_STACK_REF_EX(stack, 1, ref, arg_flags);
281+
}
282+
} else {
283+
ZEND_ASSERT(opline->op2.num == 3);
284+
ZEND_ASSERT(op1_info == MAY_BE_LONG);
285+
ref = jit_Z_LVAL(jit, op1_addr);
286+
SET_STACK_TYPE(stack, 2, IS_LONG, 0);
287+
SET_STACK_REF_EX(stack, 2, ref, 0);
288+
}
289+
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_MEMSET) {
290+
if (opline->op2.num == 1) {
291+
ZEND_ASSERT(op1_ffi_type);
292+
if (op1_ffi_type->kind == ZEND_FFI_TYPE_POINTER) {
293+
arg_flags |= ZREG_FFI_PTR_LOAD;
294+
}
295+
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
296+
arg_flags |= ZREG_FFI_ZVAL_DTOR;
297+
}
298+
if (op1_info & MAY_BE_REF) {
299+
arg_flags |= ZREG_FFI_ZVAL_DEREF;
300+
}
301+
ref = jit_Z_PTR(jit, op1_addr);
302+
SET_STACK_TYPE(stack, 0, IS_OBJECT, 0);
303+
SET_STACK_REF_EX(stack, 0, ref, arg_flags);
304+
} else if (opline->op2.num == 2) {
305+
ZEND_ASSERT(op1_info == MAY_BE_LONG);
306+
ref = jit_Z_LVAL(jit, op1_addr);
307+
SET_STACK_TYPE(stack, 1, IS_LONG, 0);
308+
SET_STACK_REF_EX(stack, 1, ref, 0);
309+
} else {
310+
ZEND_ASSERT(opline->op2.num == 3);
311+
ZEND_ASSERT(op1_info == MAY_BE_LONG);
312+
ref = jit_Z_LVAL(jit, op1_addr);
313+
SET_STACK_TYPE(stack, 2, IS_LONG, 0);
314+
SET_STACK_REF_EX(stack, 2, ref, 0);
315+
}
181316
} else {
182317
ZEND_UNREACHABLE();
183318
}
@@ -494,6 +629,108 @@ static int zend_jit_ffi_do_call(zend_jit_ctx *jit,
494629
ir_CALL_3(IR_VOID, ir_CONST_FC_FUNC(zend_jit_zval_stringl),
495630
jit_ZVAL_ADDR(jit, res_addr), ref, STACK_REF(stack, 1));
496631
}
632+
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_MEMCPY) {
633+
ir_ref ref2;
634+
635+
ref = STACK_REF(stack, 0);
636+
if (STACK_FLAGS(stack, 0) & ZREG_FFI_ZVAL_DEREF) {
637+
// TODO: try to remove this dereference ???
638+
ref = zend_jit_gc_deref(jit, ref);
639+
}
640+
ref = jit_FFI_CDATA_PTR(jit, ref);
641+
if (STACK_FLAGS(stack, 0) & ZREG_FFI_PTR_LOAD) {
642+
ref = ir_LOAD_A(ref);
643+
}
644+
645+
if (STACK_TYPE(stack, 1) == IS_OBJECT) {
646+
ref2 = STACK_REF(stack, 1);
647+
if (STACK_FLAGS(stack, 1) & ZREG_FFI_ZVAL_DEREF) {
648+
// TODO: try to remove this dereference ???
649+
ref2 = zend_jit_gc_deref(jit, ref2);
650+
}
651+
ref2 = jit_FFI_CDATA_PTR(jit, ref2);
652+
if (STACK_FLAGS(stack, 1) & ZREG_FFI_PTR_LOAD) {
653+
ref2 = ir_LOAD_A(ref2);
654+
}
655+
} else {
656+
ZEND_ASSERT(STACK_TYPE(stack, 1) == IS_STRING);
657+
ref2 = STACK_REF(stack, 1);
658+
if (STACK_FLAGS(stack, 1) & ZREG_FFI_ZVAL_DEREF) {
659+
// TODO: try to remove this dereference ???
660+
ref2 = zend_jit_gc_deref(jit, ref2);
661+
}
662+
ref2 = ir_ADD_OFFSET(ref2, offsetof(zend_string, val));
663+
}
664+
665+
ir_CALL_3(IR_VOID, ir_CONST_FUNC(memcpy), ref, ref2, STACK_REF(stack, 2));
666+
if (res_addr) {
667+
jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL);
668+
}
669+
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_MEMCMP) {
670+
ir_ref ref2;
671+
672+
if (STACK_TYPE(stack, 0) == IS_OBJECT) {
673+
ref = STACK_REF(stack, 0);
674+
if (STACK_FLAGS(stack, 0) & ZREG_FFI_ZVAL_DEREF) {
675+
// TODO: try to remove this dereference ???
676+
ref = zend_jit_gc_deref(jit, ref);
677+
}
678+
ref = jit_FFI_CDATA_PTR(jit, ref);
679+
if (STACK_FLAGS(stack, 0) & ZREG_FFI_PTR_LOAD) {
680+
ref = ir_LOAD_A(ref);
681+
}
682+
} else {
683+
ZEND_ASSERT(STACK_TYPE(stack, 0) == IS_STRING);
684+
ref = STACK_REF(stack, 0);
685+
if (STACK_FLAGS(stack, 0) & ZREG_FFI_ZVAL_DEREF) {
686+
// TODO: try to remove this dereference ???
687+
ref = zend_jit_gc_deref(jit, ref);
688+
}
689+
ref = ir_ADD_OFFSET(ref, offsetof(zend_string, val));
690+
}
691+
692+
if (STACK_TYPE(stack, 1) == IS_OBJECT) {
693+
ref2 = STACK_REF(stack, 1);
694+
if (STACK_FLAGS(stack, 1) & ZREG_FFI_ZVAL_DEREF) {
695+
// TODO: try to remove this dereference ???
696+
ref2 = zend_jit_gc_deref(jit, ref2);
697+
}
698+
ref2 = jit_FFI_CDATA_PTR(jit, ref2);
699+
if (STACK_FLAGS(stack, 1) & ZREG_FFI_PTR_LOAD) {
700+
ref2 = ir_LOAD_A(ref2);
701+
}
702+
} else {
703+
ZEND_ASSERT(STACK_TYPE(stack, 1) == IS_STRING);
704+
ref2 = STACK_REF(stack, 1);
705+
if (STACK_FLAGS(stack, 1) & ZREG_FFI_ZVAL_DEREF) {
706+
// TODO: try to remove this dereference ???
707+
ref2 = zend_jit_gc_deref(jit, ref2);
708+
}
709+
ref2 = ir_ADD_OFFSET(ref2, offsetof(zend_string, val));
710+
}
711+
712+
ref = ir_CALL_3(IR_I32, ir_CONST_FUNC(memcmp), ref, ref2, STACK_REF(stack, 2));
713+
if (res_addr) {
714+
/* (-1, 0, 1) = (ret > 0) - (ret < 0) */
715+
ref = ir_SUB_L(ir_SEXT_L(ir_GT(ref, ir_CONST_I32(0))), ir_SEXT_L(ir_LT(ref, ir_CONST_I32(0))));
716+
jit_set_Z_LVAL(jit, res_addr, ref);
717+
jit_set_Z_TYPE_INFO(jit, res_addr, IS_LONG);
718+
}
719+
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_MEMSET) {
720+
ref = STACK_REF(stack, 0);
721+
if (STACK_FLAGS(stack, 0) & ZREG_FFI_ZVAL_DEREF) {
722+
// TODO: try to remove this dereference ???
723+
ref = zend_jit_gc_deref(jit, ref);
724+
}
725+
ref = jit_FFI_CDATA_PTR(jit, ref);
726+
if (STACK_FLAGS(stack, 0) & ZREG_FFI_PTR_LOAD) {
727+
ref = ir_LOAD_A(ref);
728+
}
729+
730+
ir_CALL_3(IR_VOID, ir_CONST_FUNC(memset), ref, STACK_REF(stack, 1), STACK_REF(stack, 2));
731+
if (res_addr) {
732+
jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL);
733+
}
497734
} else {
498735
ZEND_UNREACHABLE();
499736
}

ext/opcache/jit/zend_jit_trace.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5849,7 +5849,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
58495849
if (JIT_G(current_frame)
58505850
&& JIT_G(current_frame)->call
58515851
&& TRACE_FRAME_FFI(JIT_G(current_frame)->call)) {
5852-
if (!zend_jit_ffi_do_call(&ctx, opline, op_array, ssa, ssa_op, RES_REG_ADDR())) {
5852+
if (!zend_jit_ffi_do_call(&ctx, opline, op_array, ssa, ssa_op,
5853+
(opline->result_type != IS_UNUSED) ? RES_REG_ADDR() : 0 )) {
58535854
goto jit_failure;
58545855
}
58555856
goto done;
@@ -7034,6 +7035,27 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
70347035
frame_ffi_func_type = NULL;
70357036
frame_ffi_func_ref = IR_UNUSED;
70367037
goto done;
7038+
} else if (Z_TYPE_P(zv) == IS_STRING
7039+
&& zend_string_equals_literal_ci(Z_STR_P(zv), "memcpy")
7040+
&& opline->extended_value == 3) {
7041+
frame_flags = TRACE_FRAME_MASK_FFI | TRACE_FRAME_FFI_FUNC_MEMCPY;
7042+
frame_ffi_func_type = NULL;
7043+
frame_ffi_func_ref = IR_UNUSED;
7044+
goto done;
7045+
} else if (Z_TYPE_P(zv) == IS_STRING
7046+
&& zend_string_equals_literal_ci(Z_STR_P(zv), "memcmp")
7047+
&& opline->extended_value == 3) {
7048+
frame_flags = TRACE_FRAME_MASK_FFI | TRACE_FRAME_FFI_FUNC_MEMCMP;
7049+
frame_ffi_func_type = NULL;
7050+
frame_ffi_func_ref = IR_UNUSED;
7051+
goto done;
7052+
} else if (Z_TYPE_P(zv) == IS_STRING
7053+
&& zend_string_equals_literal_ci(Z_STR_P(zv), "memset")
7054+
&& opline->extended_value == 3) {
7055+
frame_flags = TRACE_FRAME_MASK_FFI | TRACE_FRAME_FFI_FUNC_MEMSET;
7056+
frame_ffi_func_type = NULL;
7057+
frame_ffi_func_ref = IR_UNUSED;
7058+
goto done;
70377059
}
70387060
}
70397061
}

0 commit comments

Comments
 (0)