Skip to content

Commit 4116e51

Browse files
committed
JIT/FFI support for "cdata" property of scalar ffi objects
1 parent afc0ac5 commit 4116e51

File tree

2 files changed

+248
-1
lines changed

2 files changed

+248
-1
lines changed

ext/opcache/jit/zend_jit_ir_ffi.c

Lines changed: 181 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,8 +819,27 @@ static int zend_jit_ffi_write(zend_jit_ctx *jit,
819819
}
820820
}
821821
break;
822-
case ZEND_FFI_TYPE_SINT8:
823822
case ZEND_FFI_TYPE_CHAR:
823+
if ((val_info & (MAY_BE_GUARD|MAY_BE_REF|MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING) {
824+
ir_ref str = jit_Z_PTR(jit, val_addr);
825+
826+
// TODO: ZSTR_LEN() == 1 ???
827+
ref = ir_LOAD_C(ir_ADD_OFFSET(str, offsetof(zend_string, val)));
828+
ir_STORE(ptr, ref);
829+
if (res_addr) {
830+
ir_ref type_info = jit_Z_TYPE_INFO(jit, val_addr);
831+
ir_ref if_refcounted = ir_IF(ir_AND_U32(type_info, ir_CONST_U32(0xff00)));
832+
833+
ir_IF_TRUE(if_refcounted);
834+
jit_GC_ADDREF(jit, str);
835+
ir_MERGE_WITH_EMPTY_FALSE(if_refcounted);
836+
jit_set_Z_PTR(jit, res_addr, str);
837+
jit_set_Z_TYPE_INFO_ex(jit, res_addr, type_info);
838+
}
839+
return 1;
840+
}
841+
ZEND_FALLTHROUGH;
842+
case ZEND_FFI_TYPE_SINT8:
824843
if (val_info == MAY_BE_LONG) {
825844
ref = ir_TRUNC_I8(jit_Z_LVAL(jit, val_addr));
826845
} else if (val_ffi_type && val_ffi_type->kind == ffi_type->kind) {
@@ -1311,6 +1330,53 @@ static int zend_jit_ffi_fetch_obj(zend_jit_ctx *jit,
13111330
return 1;
13121331
}
13131332

1333+
static int zend_jit_ffi_fetch_val(zend_jit_ctx *jit,
1334+
const zend_op *opline,
1335+
const zend_op_array *op_array,
1336+
zend_ssa *ssa,
1337+
const zend_ssa_op *ssa_op,
1338+
uint32_t op1_info,
1339+
zend_jit_addr op1_addr,
1340+
bool op1_indirect,
1341+
bool op1_avoid_refcounting,
1342+
zend_jit_addr res_addr,
1343+
zend_ffi_type *op1_ffi_type,
1344+
zend_jit_ffi_info *ffi_info)
1345+
{
1346+
uint32_t res_info = RES_INFO();
1347+
ir_ref obj_ref = jit_Z_PTR(jit, op1_addr);
1348+
1349+
if (!zend_jit_ffi_guard(jit, opline, ssa, ssa_op->op1_use, -1, obj_ref, op1_ffi_type, ffi_info)) {
1350+
return 0;
1351+
}
1352+
1353+
ir_ref ptr = ir_LOAD_A(ir_ADD_OFFSET(obj_ref, offsetof(zend_ffi_cdata, ptr)));
1354+
1355+
if (opline->opcode == ZEND_FETCH_OBJ_W) {
1356+
jit_set_Z_PTR(jit, res_addr,
1357+
ir_CALL_2(IR_ADDR, ir_CONST_FUNC(zend_ffi_cdata_create),
1358+
ptr, ir_CONST_ADDR(op1_ffi_type)));
1359+
jit_set_Z_TYPE_INFO(jit, res_addr, IS_OBJECT_EX);
1360+
} else {
1361+
if (!zend_jit_ffi_read(jit, op1_ffi_type, ptr, res_addr)) {
1362+
return 0;
1363+
}
1364+
}
1365+
1366+
if (res_info & MAY_BE_GUARD) {
1367+
// TODO: ???
1368+
ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
1369+
}
1370+
1371+
if (!op1_avoid_refcounting && !op1_indirect) {
1372+
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
1373+
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline);
1374+
}
1375+
}
1376+
1377+
return 1;
1378+
}
1379+
13141380
static int zend_jit_ffi_fetch_sym(zend_jit_ctx *jit,
13151381
const zend_op *opline,
13161382
const zend_op_array *op_array,
@@ -1410,6 +1476,54 @@ static int zend_jit_ffi_assign_obj(zend_jit_ctx *jit,
14101476
return 1;
14111477
}
14121478

1479+
static int zend_jit_ffi_assign_val(zend_jit_ctx *jit,
1480+
const zend_op *opline,
1481+
const zend_op_array *op_array,
1482+
zend_ssa *ssa,
1483+
const zend_ssa_op *ssa_op,
1484+
uint32_t op1_info,
1485+
zend_jit_addr op1_addr,
1486+
bool op1_indirect,
1487+
uint32_t val_info,
1488+
zend_jit_addr val_addr,
1489+
zend_jit_addr val_def_addr,
1490+
zend_jit_addr res_addr,
1491+
zend_ffi_type *op1_ffi_type,
1492+
zend_ffi_type *val_ffi_type,
1493+
zend_jit_ffi_info *ffi_info)
1494+
{
1495+
ir_ref obj_ref = jit_Z_PTR(jit, op1_addr);
1496+
1497+
if (!zend_jit_ffi_guard(jit, opline, ssa, ssa_op->op1_use, ssa_op->op1_def, obj_ref, op1_ffi_type, ffi_info)) {
1498+
return 0;
1499+
}
1500+
1501+
if (val_addr != val_def_addr && val_def_addr) {
1502+
if (!zend_jit_update_regs(jit, (opline+1)->op1.var, val_addr, val_def_addr, val_info)) {
1503+
return 0;
1504+
}
1505+
if (Z_MODE(val_def_addr) == IS_REG && Z_MODE(val_addr) != IS_REG) {
1506+
val_addr = val_def_addr;
1507+
}
1508+
}
1509+
1510+
ir_ref ptr = ir_LOAD_A(ir_ADD_OFFSET(obj_ref, offsetof(zend_ffi_cdata, ptr)));
1511+
1512+
ZEND_ASSERT(!res_addr || RETURN_VALUE_USED(opline));
1513+
1514+
if (!zend_jit_ffi_write(jit, op1_ffi_type, ptr, val_info, val_addr, val_ffi_type, res_addr)) {
1515+
return 0;
1516+
}
1517+
1518+
jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->op1, val_info, opline);
1519+
1520+
if (!op1_indirect) {
1521+
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline);
1522+
}
1523+
1524+
return 1;
1525+
}
1526+
14131527
static int zend_jit_ffi_assign_sym(zend_jit_ctx *jit,
14141528
const zend_op *opline,
14151529
const zend_op_array *op_array,
@@ -1496,6 +1610,41 @@ static int zend_jit_ffi_assign_obj_op(zend_jit_ctx *jit,
14961610
return 1;
14971611
}
14981612

1613+
static int zend_jit_ffi_assign_val_op(zend_jit_ctx *jit,
1614+
const zend_op *opline,
1615+
const zend_op_array *op_array,
1616+
zend_ssa *ssa,
1617+
const zend_ssa_op *ssa_op,
1618+
uint32_t op1_info,
1619+
zend_jit_addr op1_addr,
1620+
bool op1_indirect,
1621+
uint32_t val_info,
1622+
zend_jit_addr val_addr,
1623+
zend_ffi_type *op1_ffi_type,
1624+
zend_jit_ffi_info *ffi_info)
1625+
{
1626+
ir_ref obj_ref = jit_Z_PTR(jit, op1_addr);
1627+
1628+
if (!zend_jit_ffi_guard(jit, opline, ssa, ssa_op->op1_use, ssa_op->op1_def, obj_ref, op1_ffi_type, ffi_info)) {
1629+
return 0;
1630+
}
1631+
1632+
ir_ref ptr = ir_LOAD_A(ir_ADD_OFFSET(obj_ref, offsetof(zend_ffi_cdata, ptr)));
1633+
1634+
if (!zend_jit_ffi_assign_op_helper(jit, opline, opline->extended_value,
1635+
op1_ffi_type, ptr, val_info, val_addr)) {
1636+
return 0;
1637+
}
1638+
1639+
jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->op1, val_info, opline);
1640+
1641+
if (!op1_indirect) {
1642+
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline);
1643+
}
1644+
1645+
return 1;
1646+
}
1647+
14991648
static int zend_jit_ffi_assign_sym_op(zend_jit_ctx *jit,
15001649
const zend_op *opline,
15011650
const zend_op_array *op_array,
@@ -1767,6 +1916,37 @@ static int zend_jit_ffi_incdec_obj(zend_jit_ctx *jit,
17671916
return 1;
17681917
}
17691918

1919+
static int zend_jit_ffi_incdec_val(zend_jit_ctx *jit,
1920+
const zend_op *opline,
1921+
const zend_op_array *op_array,
1922+
zend_ssa *ssa,
1923+
const zend_ssa_op *ssa_op,
1924+
uint32_t op1_info,
1925+
zend_jit_addr op1_addr,
1926+
bool op1_indirect,
1927+
zend_jit_addr res_addr,
1928+
zend_ffi_type *op1_ffi_type,
1929+
zend_jit_ffi_info *ffi_info)
1930+
{
1931+
ir_ref obj_ref = jit_Z_PTR(jit, op1_addr);
1932+
1933+
if (!zend_jit_ffi_guard(jit, opline, ssa, ssa_op->op1_use, ssa_op->op1_def, obj_ref, op1_ffi_type, ffi_info)) {
1934+
return 0;
1935+
}
1936+
1937+
ir_ref ptr = ir_LOAD_A(ir_ADD_OFFSET(obj_ref, offsetof(zend_ffi_cdata, ptr)));
1938+
1939+
if (!zend_jit_ffi_incdec_helper(jit, opline, opline->opcode, op1_ffi_type, ptr, res_addr)) {
1940+
return 0;
1941+
}
1942+
1943+
if (!op1_indirect) {
1944+
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline);
1945+
}
1946+
1947+
return 1;
1948+
}
1949+
17701950
static int zend_jit_ffi_incdec_sym(zend_jit_ctx *jit,
17711951
const zend_op *opline,
17721952
const zend_op_array *op_array,

ext/opcache/jit/zend_jit_trace.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4938,6 +4938,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
49384938
}
49394939
goto done;
49404940
}
4941+
} else if (op1_ffi_type
4942+
&& op1_ffi_type->kind < ZEND_FFI_TYPE_POINTER
4943+
&& op1_ffi_type->kind != ZEND_FFI_TYPE_VOID
4944+
&& zend_string_equals_literal(Z_STR_P(RT_CONSTANT(opline, opline->op2)), "cdata")
4945+
&& zend_jit_ffi_supported_type(op1_ffi_type)) {
4946+
if (!ffi_info) {
4947+
ffi_info = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_jit_ffi_info));
4948+
}
4949+
if (!zend_jit_ffi_incdec_val(&ctx, opline, op_array, ssa, ssa_op,
4950+
op1_info, op1_addr, op1_indirect,
4951+
(opline->result_type != IS_UNUSED) ? RES_REG_ADDR() : 0,
4952+
op1_ffi_type, ffi_info)) {
4953+
goto jit_failure;
4954+
}
4955+
goto done;
49414956
} else if (op1_ffi_symbols) {
49424957
zend_ffi_symbol *sym = zend_hash_find_ptr(op1_ffi_symbols,
49434958
Z_STR_P(RT_CONSTANT(opline, opline->op2)));
@@ -5078,6 +5093,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
50785093
}
50795094
goto done;
50805095
}
5096+
} else if (op1_ffi_type
5097+
&& op1_ffi_type->kind < ZEND_FFI_TYPE_POINTER
5098+
&& op1_ffi_type->kind != ZEND_FFI_TYPE_VOID
5099+
&& zend_string_equals_literal(Z_STR_P(RT_CONSTANT(opline, opline->op2)), "cdata")
5100+
&& zend_jit_ffi_supported_type(op1_ffi_type)) {
5101+
if (!ffi_info) {
5102+
ffi_info = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_jit_ffi_info));
5103+
}
5104+
if (!zend_jit_ffi_assign_val_op(&ctx, opline, op_array, ssa, ssa_op,
5105+
op1_info, op1_addr, op1_indirect,
5106+
op1_data_info, OP1_DATA_REG_ADDR(),
5107+
op1_ffi_type, ffi_info)) {
5108+
goto jit_failure;
5109+
}
5110+
goto done;
50815111
} else if (op1_ffi_symbols) {
50825112
zend_ffi_symbol *sym = zend_hash_find_ptr(op1_ffi_symbols,
50835113
Z_STR_P(RT_CONSTANT(opline, opline->op2)));
@@ -5208,6 +5238,27 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
52085238
}
52095239
goto done;
52105240
}
5241+
} else if (op1_ffi_type
5242+
&& op1_ffi_type->kind < ZEND_FFI_TYPE_POINTER
5243+
&& op1_ffi_type->kind != ZEND_FFI_TYPE_VOID
5244+
&& zend_string_equals_literal(Z_STR_P(RT_CONSTANT(opline, opline->op2)), "cdata")
5245+
&& zend_jit_ffi_supported_type(op1_ffi_type)) {
5246+
if (!ffi_info) {
5247+
ffi_info = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_jit_ffi_info));
5248+
}
5249+
if (!zend_jit_ffi_assign_val(&ctx, opline, op_array, ssa, ssa_op,
5250+
op1_info, op1_addr, op1_indirect,
5251+
op1_data_info, OP1_DATA_REG_ADDR(), OP1_DATA_DEF_REG_ADDR(),
5252+
(opline->result_type != IS_UNUSED) ? RES_REG_ADDR() : 0,
5253+
op1_ffi_type, op3_ffi_type, ffi_info)) {
5254+
goto jit_failure;
5255+
}
5256+
if ((opline+1)->op1_type == IS_CV
5257+
&& (ssa_op+1)->op1_def >= 0
5258+
&& ssa->vars[(ssa_op+1)->op1_def].alias == NO_ALIAS) {
5259+
ssa->var_info[(ssa_op+1)->op1_def].guarded_reference = ssa->var_info[(ssa_op+1)->op1_use].guarded_reference;
5260+
}
5261+
goto done;
52115262
} else if (op1_ffi_symbols) {
52125263
zend_ffi_symbol *sym = zend_hash_find_ptr(op1_ffi_symbols,
52135264
Z_STR_P(RT_CONSTANT(opline, opline->op2)));
@@ -6425,6 +6476,22 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
64256476
}
64266477
goto done;
64276478
}
6479+
} else if (op1_ffi_type
6480+
&& op1_ffi_type->kind < ZEND_FFI_TYPE_POINTER
6481+
&& op1_ffi_type->kind != ZEND_FFI_TYPE_VOID
6482+
&& zend_string_equals_literal(Z_STR_P(RT_CONSTANT(opline, opline->op2)), "cdata")
6483+
&& zend_jit_ffi_supported_type(op1_ffi_type)) {
6484+
if (!ffi_info) {
6485+
ffi_info = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_jit_ffi_info));
6486+
}
6487+
if (!zend_jit_ffi_fetch_val(&ctx, opline, op_array, ssa, ssa_op,
6488+
op1_info, op1_addr, op1_indirect,
6489+
avoid_refcounting,
6490+
RES_REG_ADDR(),
6491+
op1_ffi_type, ffi_info)) {
6492+
goto jit_failure;
6493+
}
6494+
goto done;
64286495
} else if ((opline->opcode == ZEND_FETCH_OBJ_R
64296496
|| opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG
64306497
|| opline->opcode == ZEND_FETCH_OBJ_W)

0 commit comments

Comments
 (0)