Skip to content

Commit 53bf1b1

Browse files
committed
JIT for FFI::new() with single argument
1 parent 7dc7aea commit 53bf1b1

File tree

2 files changed

+107
-12
lines changed

2 files changed

+107
-12
lines changed

ext/opcache/jit/zend_jit_ir_ffi.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,11 @@ static int zend_jit_ffi_send_val(zend_jit_ctx *jit,
334334
SET_STACK_TYPE(stack, 2, IS_LONG, 0);
335335
SET_STACK_REF_EX(stack, 2, ref, 0);
336336
}
337+
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_NEW) {
338+
ZEND_ASSERT(opline->op2.num == 1);
339+
/* nothing to do */
337340
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_TYPE) {
341+
ZEND_ASSERT(opline->op2.num == 1);
338342
/* nothing to do */
339343
} else {
340344
ZEND_UNREACHABLE();
@@ -762,11 +766,31 @@ static int zend_jit_ffi_do_call(zend_jit_ctx *jit,
762766
if (res_addr) {
763767
jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL);
764768
}
769+
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_NEW) {
770+
if (res_addr) {
771+
#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));
779+
#else
780+
ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(_ecalloc), ir_CONST_LONG(1), ir_CONST_ADDR(type->size));
781+
#endif
782+
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));
784+
jit_set_Z_PTR(jit, res_addr, ref);
785+
jit_set_Z_TYPE_INFO(jit, res_addr, IS_OBJECT_EX);
786+
}
765787
} else if (TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_TYPE) {
766-
ref = ir_CONST_ADDR(type);
767-
ref = ir_CALL_1(IR_ADDR, ir_CONST_FUNC(zend_ffi_api->ctype_create), ref);
768-
jit_set_Z_PTR(jit, res_addr, ref);
769-
jit_set_Z_TYPE_INFO(jit, res_addr, IS_OBJECT_EX);
788+
if (res_addr) {
789+
ref = ir_CONST_ADDR(type);
790+
ref = ir_CALL_1(IR_ADDR, ir_CONST_FUNC(zend_ffi_api->ctype_create), ref);
791+
jit_set_Z_PTR(jit, res_addr, ref);
792+
jit_set_Z_TYPE_INFO(jit, res_addr, IS_OBJECT_EX);
793+
}
770794
} else {
771795
ZEND_UNREACHABLE();
772796
}
@@ -987,9 +1011,11 @@ static int zend_jit_ffi_do_call(zend_jit_ctx *jit,
9871011
}
9881012
}
9891013

990-
if (!TRACE_FRAME_FFI_FUNC(call)) {
1014+
if (!TRACE_FRAME_FFI_FUNC(call)
1015+
|| TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_NEW
1016+
|| TRACE_FRAME_FFI_FUNC(call) == TRACE_FRAME_FFI_FUNC_TYPE) {
9911017
func_ref = (intptr_t)(void*)call->ce;
992-
if (!IR_IS_CONST_REF(func_ref)) {
1018+
if (func_ref && !IR_IS_CONST_REF(func_ref)) {
9931019
ir_ref if_not_zero = ir_IF(jit_GC_DELREF(jit, func_ref));
9941020
ir_IF_FALSE(if_not_zero);
9951021
jit_ZVAL_DTOR(jit, func_ref, MAY_BE_OBJECT, opline);

ext/opcache/jit/zend_jit_trace.c

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6942,10 +6942,72 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
69426942
}
69436943
}
69446944
#ifdef HAVE_FFI
6945-
if (op1_ffi_symbols) {
6945+
if (zend_ffi_api && op1_ce == zend_ffi_api->scope_ce && !ZEND_OBSERVER_ENABLED) {
69466946
zend_string *name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
69476947

6948-
if (zend_string_equals_literal_ci(name, "type")) {
6948+
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+
}
7008+
}
7009+
}
7010+
} else if (zend_string_equals_literal_ci(name, "type")) {
69497011
if (opline->extended_value == 1
69507012
&& (p+1)->op == ZEND_JIT_TRACE_INIT_CALL
69517013
&& (p+2)->op == ZEND_JIT_TRACE_VM
@@ -6957,7 +7019,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
69577019
if (Z_TYPE_P(zv) == IS_STRING) {
69587020
zend_ffi_dcl *dcl = zend_ffi_api->cache_type_get(Z_STR_P(zv), op1_ffi_symbols);
69597021

6960-
if (dcl) {
7022+
if (dcl
7023+
&& !ZEND_FFI_TYPE_IS_OWNED(dcl->type)
7024+
&& (dcl->type->attr & ZEND_FFI_ATTR_PERSISTENT)) {
69617025
if (!ffi_info) {
69627026
ffi_info = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_jit_ffi_info));
69637027
}
@@ -6967,12 +7031,16 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
69677031
}
69687032
frame_flags = TRACE_FRAME_MASK_FFI | TRACE_FRAME_FFI_FUNC_TYPE;
69697033
frame_ffi_func_type = dcl->type;
6970-
frame_ffi_func_ref = IR_UNUSED;
7034+
if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
7035+
frame_ffi_func_ref = jit_Z_PTR(jit, op1_addr);
7036+
} else {
7037+
frame_ffi_func_ref = IR_UNUSED;
7038+
}
69717039
goto done;
69727040
}
69737041
}
69747042
}
6975-
} else {
7043+
} else if (op1_ffi_symbols) {
69767044
zend_ffi_symbol *sym = zend_hash_find_ptr(op1_ffi_symbols, name);
69777045

69787046
if (sym
@@ -7019,7 +7087,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
70197087
}
70207088
#ifdef HAVE_FFI
70217089
if (opline->op1_type == IS_CONST
7022-
&& opline->op2_type == IS_CONST) {
7090+
&& opline->op2_type == IS_CONST
7091+
&& !ZEND_OBSERVER_ENABLED) {
70237092
zval *zv = RT_CONSTANT(opline, opline->op1);
70247093
if (Z_TYPE_P(zv) == IS_STRING
70257094
&& (zend_string_equals_literal_ci(Z_STR_P(zv), "FFI")

0 commit comments

Comments
 (0)