Skip to content

Commit 4ed78a6

Browse files
committed
FFI JIT for FETCH_DIM/OBJ_W
1 parent a77dbb7 commit 4ed78a6

File tree

5 files changed

+95
-28
lines changed

5 files changed

+95
-28
lines changed

Zend/zend.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ ZEND_ATTRIBUTE_NONNULL ZEND_API void (*zend_random_bytes_insecure)(zend_random_b
9999

100100
ZEND_API zend_class_entry *zend_ffi_ce = NULL;
101101
ZEND_API zend_class_entry *zend_ffi_cdata_ce = NULL;
102+
ZEND_API zend_ffi_cdata* (*zend_ffi_cdata_create)(void *ptr, zend_ffi_type *type) = NULL;
102103
ZEND_API zend_ffi_dcl* (*zend_ffi_cache_type_get)(zend_string *str, void *context) = NULL;
103104
ZEND_API zend_ffi_dcl* (*zend_ffi_cache_type_add)(zend_string *str, zend_ffi_dcl *dcl, void *context) = NULL;
104105
ZEND_API zend_ffi_scope* (*zend_ffi_cache_scope_get)(zend_string *str) = NULL;

Zend/zend.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,12 @@ extern ZEND_API zend_utility_values zend_uv;
394394
extern ZEND_API zend_class_entry *zend_ffi_ce;
395395
extern ZEND_API zend_class_entry *zend_ffi_cdata_ce;
396396

397-
typedef struct _zend_ffi_dcl zend_ffi_dcl;
397+
typedef struct _zend_ffi_dcl zend_ffi_dcl;
398398
typedef struct _zend_ffi_scope zend_ffi_scope;
399+
typedef struct _zend_ffi_cdata zend_ffi_cdata;
400+
typedef struct _zend_ffi_type zend_ffi_type;
399401

402+
ZEND_API extern zend_ffi_cdata* (*zend_ffi_cdata_create)(void *ptr, zend_ffi_type *type);
400403
ZEND_API extern zend_ffi_dcl* (*zend_ffi_cache_type_get)(zend_string *str, void *context);
401404
ZEND_API extern zend_ffi_dcl* (*zend_ffi_cache_type_add)(zend_string *str, zend_ffi_dcl *dcl, void *context);
402405
ZEND_API extern zend_ffi_scope* (*zend_ffi_cache_scope_get)(zend_string *str);

ext/ffi/ffi.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,22 @@ static ffi_type *zend_ffi_get_type(zend_ffi_type *type) /* {{{ */
354354
}
355355
/* }}} */
356356

357+
static zend_ffi_cdata* _zend_ffi_cdata_create(void *ptr, zend_ffi_type *type) /* {{{ */
358+
{
359+
zend_ffi_cdata *cdata = emalloc(sizeof(zend_ffi_cdata));
360+
361+
zend_ffi_object_init(&cdata->std, zend_ffi_cdata_ce);
362+
cdata->std.handlers =
363+
(type->kind < ZEND_FFI_TYPE_POINTER) ?
364+
&zend_ffi_cdata_value_handlers :
365+
&zend_ffi_cdata_handlers;
366+
cdata->type = type;
367+
cdata->flags = 0;
368+
cdata->ptr = ptr;
369+
return cdata;
370+
}
371+
/* }}} */
372+
357373
static zend_never_inline zend_ffi_cdata *zend_ffi_cdata_to_zval_slow(void *ptr, zend_ffi_type *type, zend_ffi_flags flags) /* {{{ */
358374
{
359375
zend_ffi_cdata *cdata = emalloc(sizeof(zend_ffi_cdata));
@@ -5533,6 +5549,8 @@ ZEND_MINIT_FUNCTION(ffi)
55335549
zend_ffi_ctype_handlers.get_properties = zend_fake_get_properties;
55345550
zend_ffi_ctype_handlers.get_gc = zend_fake_get_gc;
55355551

5552+
zend_ffi_cdata_create = _zend_ffi_cdata_create;
5553+
55365554
if (FFI_G(preload)) {
55375555
return zend_ffi_preload(FFI_G(preload));
55385556
}

ext/opcache/jit/zend_jit_ir.c

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13087,20 +13087,21 @@ static int zend_jit_ffi_symbols_guard(zend_jit_ctx *jit,
1308713087
return 1;
1308813088
}
1308913089

13090-
static int zend_jit_ffi_fetch_dim_read(zend_jit_ctx *jit,
13091-
const zend_op *opline,
13092-
zend_ssa *ssa,
13093-
const zend_ssa_op *ssa_op,
13094-
uint32_t op1_info,
13095-
zend_jit_addr op1_addr,
13096-
bool op1_avoid_refcounting,
13097-
uint32_t op2_info,
13098-
zend_jit_addr op2_addr,
13099-
zend_ssa_range *op2_range,
13100-
uint32_t res_info,
13101-
zend_jit_addr res_addr,
13102-
zend_ffi_type *op1_ffi_type,
13103-
zend_jit_ffi_info *ffi_info)
13090+
static int zend_jit_ffi_fetch_dim(zend_jit_ctx *jit,
13091+
const zend_op *opline,
13092+
zend_ssa *ssa,
13093+
const zend_ssa_op *ssa_op,
13094+
uint32_t op1_info,
13095+
zend_jit_addr op1_addr,
13096+
bool op1_indirect,
13097+
bool op1_avoid_refcounting,
13098+
uint32_t op2_info,
13099+
zend_jit_addr op2_addr,
13100+
zend_ssa_range *op2_range,
13101+
uint32_t res_info,
13102+
zend_jit_addr res_addr,
13103+
zend_ffi_type *op1_ffi_type,
13104+
zend_jit_ffi_info *ffi_info)
1310413105
{
1310513106
zend_ffi_type *el_type = ZEND_FFI_TYPE(op1_ffi_type->array.type);
1310613107
ir_ref obj_ref = jit_Z_PTR(jit, op1_addr);
@@ -13122,16 +13123,23 @@ static int zend_jit_ffi_fetch_dim_read(zend_jit_ctx *jit,
1312213123

1312313124
ir_ref ptr = ir_ADD_A(cdata_ref, ir_MUL_L(jit_Z_LVAL(jit, op2_addr), ir_CONST_LONG(el_type->size)));
1312413125

13125-
if (!zend_jit_ffi_read(jit, el_type, ptr, res_addr)) {
13126-
return 0;
13126+
if (opline->opcode == ZEND_FETCH_DIM_W || opline->opcode == ZEND_FETCH_DIM_RW) {
13127+
jit_set_Z_PTR(jit, res_addr,
13128+
ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(zend_ffi_cdata_create),
13129+
ptr, ir_CONST_ADDR(el_type)));
13130+
jit_set_Z_TYPE_INFO(jit, res_addr, IS_OBJECT_EX);
13131+
} else {
13132+
if (!zend_jit_ffi_read(jit, el_type, ptr, res_addr)) {
13133+
return 0;
13134+
}
1312713135
}
1312813136

1312913137
if (res_info & MAY_BE_GUARD) {
1313013138
// TODO: ???
1313113139
ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
1313213140
}
1313313141

13134-
if (opline->opcode != ZEND_FETCH_LIST_R && !op1_avoid_refcounting) {
13142+
if (opline->opcode != ZEND_FETCH_LIST_R && !op1_avoid_refcounting && !op1_indirect) {
1313513143
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
1313613144
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline);
1313713145
}
@@ -15005,16 +15013,23 @@ static int zend_jit_ffi_fetch_obj(zend_jit_ctx *jit,
1500515013
ir_ref cdata_ref = ir_LOAD_A(ir_ADD_OFFSET(obj_ref, offsetof(zend_ffi_cdata, ptr)));
1500615014
ir_ref ptr = ir_ADD_A(cdata_ref, ir_CONST_LONG(field->offset));
1500715015

15008-
if (!zend_jit_ffi_read(jit, field_type, ptr, res_addr)) {
15009-
return 0;
15016+
if (opline->opcode == ZEND_FETCH_OBJ_W) {
15017+
jit_set_Z_PTR(jit, res_addr,
15018+
ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(zend_ffi_cdata_create),
15019+
ptr, ir_CONST_ADDR(field_type)));
15020+
jit_set_Z_TYPE_INFO(jit, res_addr, IS_OBJECT_EX);
15021+
} else {
15022+
if (!zend_jit_ffi_read(jit, field_type, ptr, res_addr)) {
15023+
return 0;
15024+
}
1501015025
}
1501115026

1501215027
if (res_info & MAY_BE_GUARD) {
1501315028
// TODO: ???
1501415029
ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
1501515030
}
1501615031

15017-
if (!op1_avoid_refcounting) {
15032+
if (!op1_avoid_refcounting && !op1_indirect) {
1501815033
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
1501915034
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline);
1502015035
}
@@ -15045,16 +15060,24 @@ static int zend_jit_ffi_fetch_sym(zend_jit_ctx *jit,
1504515060
}
1504615061

1504715062
ir_ref ptr = ir_CONST_ADDR(sym->addr);
15048-
if (!zend_jit_ffi_read(jit, sym_type, ptr, res_addr)) {
15049-
return 0;
15063+
15064+
if (opline->opcode == ZEND_FETCH_OBJ_W) {
15065+
jit_set_Z_PTR(jit, res_addr,
15066+
ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(zend_ffi_cdata_create),
15067+
ptr, ir_CONST_ADDR(sym_type)));
15068+
jit_set_Z_TYPE_INFO(jit, res_addr, IS_OBJECT_EX);
15069+
} else {
15070+
if (!zend_jit_ffi_read(jit, sym_type, ptr, res_addr)) {
15071+
return 0;
15072+
}
1505015073
}
1505115074

1505215075
if (res_info & MAY_BE_GUARD) {
1505315076
// TODO: ???
1505415077
ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
1505515078
}
1505615079

15057-
if (!op1_avoid_refcounting) {
15080+
if (!op1_avoid_refcounting && !op1_indirect) {
1505815081
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
1505915082
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline);
1506015083
}

ext/opcache/jit/zend_jit_trace.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6001,8 +6001,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
60016001
if (!ffi_info) {
60026002
ffi_info = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_jit_ffi_info));
60036003
}
6004-
if (!zend_jit_ffi_fetch_dim_read(&ctx, opline, ssa, ssa_op,
6005-
op1_info, op1_addr, avoid_refcounting,
6004+
if (!zend_jit_ffi_fetch_dim(&ctx, opline, ssa, ssa_op,
6005+
op1_info, op1_addr, 0, avoid_refcounting,
60066006
op2_info, OP2_REG_ADDR(), OP2_RANGE(),
60076007
res_info, RES_REG_ADDR(),
60086008
op1_ffi_type, ffi_info)) {
@@ -6031,9 +6031,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
60316031
}
60326032
op1_info = OP1_INFO();
60336033
op1_addr = OP1_REG_ADDR();
6034+
op1_indirect = 0;
60346035
if (opline->op1_type == IS_VAR) {
60356036
if (orig_op1_type != IS_UNKNOWN
60366037
&& (orig_op1_type & IS_TRACE_INDIRECT)) {
6038+
op1_indirect = 1;
60376039
if (!zend_jit_fetch_indirect_var(&ctx, opline, orig_op1_type,
60386040
&op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) {
60396041
goto jit_failure;
@@ -6058,6 +6060,24 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
60586060
op2_info = OP2_INFO();
60596061
CHECK_OP2_TRACE_TYPE();
60606062
op1_def_info = OP1_DEF_INFO();
6063+
#ifdef HAVE_FFI
6064+
if (op1_ffi_type
6065+
&& (op1_ffi_type->kind == ZEND_FFI_TYPE_ARRAY || op1_ffi_type->kind == ZEND_FFI_TYPE_POINTER)
6066+
&& op2_info == MAY_BE_LONG
6067+
&& ZEND_FFI_TYPE(op1_ffi_type->array.type)->kind != ZEND_FFI_TYPE_VOID
6068+
&& zend_jit_ffi_supported_type(ZEND_FFI_TYPE(op1_ffi_type->array.type))) {
6069+
if (!ffi_info) {
6070+
ffi_info = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_jit_ffi_info));
6071+
}
6072+
if (!zend_jit_ffi_fetch_dim(&ctx, opline, ssa, ssa_op,
6073+
op1_info, op1_addr, op1_indirect, avoid_refcounting,
6074+
op2_info, OP2_REG_ADDR(), OP2_RANGE(),
6075+
res_info, RES_REG_ADDR(),
6076+
op1_ffi_type, ffi_info)) {
6077+
goto jit_failure;
6078+
}
6079+
} else
6080+
#endif
60616081
if (!zend_jit_fetch_dim(&ctx, opline,
60626082
op1_info, op1_addr,
60636083
op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
@@ -6246,7 +6266,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
62466266
}
62476267
#ifdef HAVE_FFI
62486268
if ((opline->opcode == ZEND_FETCH_OBJ_R
6249-
|| opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG)
6269+
|| opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG
6270+
|| opline->opcode == ZEND_FETCH_OBJ_W)
62506271
&& op1_ffi_type && op1_ffi_type->kind == ZEND_FFI_TYPE_STRUCT) {
62516272
zend_ffi_field *field = zend_hash_find_ptr(&op1_ffi_type->record.fields,
62526273
Z_STR_P(RT_CONSTANT(opline, opline->op2)));
@@ -6268,7 +6289,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
62686289
goto done;
62696290
}
62706291
} else if ((opline->opcode == ZEND_FETCH_OBJ_R
6271-
|| opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG)
6292+
|| opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG
6293+
|| opline->opcode == ZEND_FETCH_OBJ_W)
62726294
&& op1_ffi_symbols) {
62736295
zend_ffi_symbol *sym = zend_hash_find_ptr(op1_ffi_symbols,
62746296
Z_STR_P(RT_CONSTANT(opline, opline->op2)));

0 commit comments

Comments
 (0)