Skip to content

Commit 8f84f82

Browse files
committed
Eliminate some FFI related type guards
1 parent 6f56cee commit 8f84f82

File tree

2 files changed

+151
-1
lines changed

2 files changed

+151
-1
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,50 @@ static bool zend_jit_ffi_compatible_addr_op(zend_ffi_type *dst_type, uint32_t sr
164164
}
165165
return false;
166166
}
167+
168+
static uint32_t zend_jit_ffi_type_info(zend_ffi_type *type)
169+
{
170+
uint32_t type_kind = type->kind;
171+
uint32_t info = MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
172+
173+
if (type_kind == ZEND_FFI_TYPE_ENUM) {
174+
type_kind = type->enumeration.kind;
175+
}
176+
switch (type_kind) {
177+
case ZEND_FFI_TYPE_VOID:
178+
info = MAY_BE_NULL;
179+
break;
180+
case ZEND_FFI_TYPE_FLOAT:
181+
case ZEND_FFI_TYPE_DOUBLE:
182+
info = MAY_BE_DOUBLE;
183+
break;
184+
case ZEND_FFI_TYPE_UINT8:
185+
case ZEND_FFI_TYPE_SINT8:
186+
case ZEND_FFI_TYPE_UINT16:
187+
case ZEND_FFI_TYPE_SINT16:
188+
case ZEND_FFI_TYPE_UINT32:
189+
case ZEND_FFI_TYPE_SINT32:
190+
case ZEND_FFI_TYPE_UINT64:
191+
case ZEND_FFI_TYPE_SINT64:
192+
info = MAY_BE_LONG;
193+
break;
194+
case ZEND_FFI_TYPE_BOOL:
195+
info = MAY_BE_FALSE|MAY_BE_TRUE;
196+
break;
197+
case ZEND_FFI_TYPE_CHAR:
198+
info = MAY_BE_STRING;
199+
break;
200+
case ZEND_FFI_TYPE_POINTER:
201+
if ((type->attr & ZEND_FFI_ATTR_CONST)
202+
&& ZEND_FFI_TYPE(type->pointer.type)->kind == ZEND_FFI_TYPE_CHAR) {
203+
info = IS_STRING;
204+
}
205+
break;
206+
default:
207+
break;
208+
}
209+
return info;
210+
}
167211
#endif
168212

169213
#ifdef HAVE_PTHREAD_JIT_WRITE_PROTECT_NP

ext/opcache/jit/zend_jit_trace.c

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1804,6 +1804,11 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
18041804
max_used_stack = used_stack = -1;
18051805
}
18061806

1807+
#ifdef HAVE_FFI
1808+
uint32_t frame_flags = 0;
1809+
zend_ffi_type *frame_ffi_func_type = NULL;
1810+
#endif
1811+
18071812
p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE;
18081813
idx = 0;
18091814
level = 0;
@@ -1814,6 +1819,19 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
18141819
uint8_t val_type = IS_UNKNOWN;
18151820
// zend_class_entry *op1_ce = NULL;
18161821
zend_class_entry *op2_ce = NULL;
1822+
// zend_class_entry *op3_ce = NULL;
1823+
#ifdef HAVE_FFI
1824+
zend_ffi_type *op1_ffi_type = NULL;
1825+
zend_ffi_type *op2_ffi_type = NULL;
1826+
zend_ffi_type *op3_ffi_type = NULL;
1827+
zend_ffi_type holder1, holder2, holder3;
1828+
HashTable *op1_ffi_symbols = NULL;
1829+
(void)op2_ffi_type;
1830+
(void)op3_ffi_type;
1831+
1832+
frame_flags = 0;
1833+
frame_ffi_func_type = NULL;
1834+
#endif
18171835

18181836
opline = p->opline;
18191837

@@ -1837,10 +1855,44 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
18371855
// op1_ce = (zend_class_entry*)(p+1)->ce;
18381856
p++;
18391857
}
1858+
#ifdef HAVE_FFI
1859+
if ((p+1)->op == ZEND_JIT_TRACE_OP1_FFI_TYPE) {
1860+
op1_ffi_type = (zend_ffi_type*)(p+1)->ptr;
1861+
if (ZEND_FFI_TYPE_IS_OWNED(op1_ffi_type)) {
1862+
op1_ffi_type = zend_jit_ffi_type_pointer_to(op1_ffi_type, &holder1);
1863+
}
1864+
p++;
1865+
} else if ((p+1)->op == ZEND_JIT_TRACE_OP1_FFI_SYMBOLS) {
1866+
op1_ffi_symbols = (HashTable*)(p+1)->ptr;
1867+
p++;
1868+
}
1869+
#endif
18401870
if ((p+1)->op == ZEND_JIT_TRACE_OP2_TYPE) {
18411871
op2_ce = (zend_class_entry*)(p+1)->ce;
18421872
p++;
18431873
}
1874+
#ifdef HAVE_FFI
1875+
if ((p+1)->op == ZEND_JIT_TRACE_OP2_FFI_TYPE) {
1876+
op2_ffi_type = (zend_ffi_type*)(p+1)->ptr;
1877+
if (ZEND_FFI_TYPE_IS_OWNED(op2_ffi_type)) {
1878+
op2_ffi_type = zend_jit_ffi_type_pointer_to(op2_ffi_type, &holder2);
1879+
}
1880+
p++;
1881+
}
1882+
#endif
1883+
if ((p+1)->op == ZEND_JIT_TRACE_OP3_TYPE) {
1884+
// op3_ce = (zend_class_entry*)(p+1)->ce;
1885+
p++;
1886+
}
1887+
#ifdef HAVE_FFI
1888+
if ((p+1)->op == ZEND_JIT_TRACE_OP3_FFI_TYPE) {
1889+
op3_ffi_type = (zend_ffi_type*)(p+1)->ptr;
1890+
if (ZEND_FFI_TYPE_IS_OWNED(op3_ffi_type)) {
1891+
op3_ffi_type = zend_jit_ffi_type_pointer_to(op3_ffi_type, &holder3);
1892+
}
1893+
p++;
1894+
}
1895+
#endif
18441896
if ((p+1)->op == ZEND_JIT_TRACE_VAL_INFO) {
18451897
val_type = (p+1)->op1_type;
18461898
p++;
@@ -2259,6 +2311,18 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
22592311
break;
22602312
}
22612313
ADD_OP1_TRACE_GUARD();
2314+
#ifdef HAVE_FFI
2315+
if (op1_ffi_symbols) {
2316+
zend_ffi_symbol *sym = zend_hash_find_ptr(op1_ffi_symbols,
2317+
Z_STR_P(RT_CONSTANT(opline, opline->op2)));
2318+
if (sym
2319+
&& sym->kind == ZEND_FFI_SYM_FUNC
2320+
&& zend_jit_ffi_supported_func(ZEND_FFI_TYPE(sym->type))) {
2321+
frame_flags = TRACE_FRAME_MASK_FFI;
2322+
frame_ffi_func_type = ZEND_FFI_TYPE(sym->type);
2323+
}
2324+
}
2325+
#endif
22622326
break;
22632327
case ZEND_INIT_DYNAMIC_CALL:
22642328
if (orig_op2_type == IS_OBJECT && op2_ce == zend_ce_closure) {
@@ -2356,6 +2420,11 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
23562420
}
23572421
}
23582422
}
2423+
2424+
#ifdef HAVE_FFI
2425+
zend_ssa_op *ssa_op = ssa_ops +idx;
2426+
#endif
2427+
23592428
if (opline->opcode == ZEND_RECV_INIT
23602429
&& !(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
23612430
/* RECV_INIT always copy the constant */
@@ -2365,6 +2434,38 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
23652434
if (ssa_ops[idx].op2_use >= 0 && ssa_ops[idx].op2_def >= 0) {
23662435
ssa_var_info[ssa_ops[idx].op2_def] = ssa_var_info[ssa_ops[idx].op2_use];
23672436
}
2437+
#ifdef HAVE_FFI
2438+
} else if (opline->opcode == ZEND_DO_FCALL
2439+
&& RETURN_VALUE_USED(opline)
2440+
&& frame
2441+
&& frame->call
2442+
&& TRACE_FRAME_FFI(frame->call)) {
2443+
zend_ffi_type *type = (zend_ffi_type*)frame->call->call_opline;
2444+
2445+
ssa_var_info[ssa_ops[idx].result_def].type =
2446+
zend_jit_ffi_type_info(ZEND_FFI_TYPE(type->func.ret_type));
2447+
} else if (op1_ffi_type
2448+
&& (op1_ffi_type->kind == ZEND_FFI_TYPE_ARRAY || op1_ffi_type->kind == ZEND_FFI_TYPE_POINTER)
2449+
&& (opline->opcode == ZEND_FETCH_DIM_R
2450+
|| opline->opcode == ZEND_FETCH_DIM_IS
2451+
|| opline->opcode == ZEND_FETCH_LIST_R)
2452+
&& (OP2_INFO() & MAY_BE_ANY) == MAY_BE_LONG
2453+
&& ZEND_FFI_TYPE(op1_ffi_type->array.type)->kind != ZEND_FFI_TYPE_VOID
2454+
&& zend_jit_ffi_supported_type(ZEND_FFI_TYPE(op1_ffi_type->array.type))) {
2455+
ssa_var_info[ssa_ops[idx].result_def].type =
2456+
zend_jit_ffi_type_info(ZEND_FFI_TYPE(op1_ffi_type->array.type));
2457+
} else if (ssa_ops[idx].op1_def >= 0
2458+
&& frame
2459+
&& frame->call
2460+
&& TRACE_FRAME_FFI(frame->call)
2461+
&& (opline->opcode == ZEND_SEND_VAR_EX
2462+
|| opline->opcode == ZEND_SEND_VAR_NO_REF
2463+
|| opline->opcode == ZEND_SEND_VAR_NO_REF_EX
2464+
|| opline->opcode == ZEND_SEND_FUNC_ARG)
2465+
&& opline->op2_type != IS_CONST) {
2466+
ssa_var_info[ssa_ops[idx].op1_def] = ssa_var_info[ssa_ops[idx].op1_use];
2467+
ssa_var_info[ssa_ops[idx].op1_def].type &= ~MAY_BE_GUARD;
2468+
#endif
23682469
} else {
23692470
if (zend_update_type_info(op_array, tssa, script, (zend_op*)opline, ssa_ops + idx, ssa_opcodes, optimization_level) == FAILURE) {
23702471
// TODO:
@@ -2617,7 +2718,12 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
26172718

26182719
} else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
26192720
call = top;
2620-
TRACE_FRAME_INIT(call, p->func, 0, 0);
2721+
TRACE_FRAME_INIT(call, p->func, frame_flags, 0);
2722+
#ifdef HAVE_FFI
2723+
if (TRACE_FRAME_FFI(call)) {
2724+
call->call_opline = (const zend_op*)(void*)frame_ffi_func_type;
2725+
}
2726+
#endif
26212727
call->prev = frame->call;
26222728
call->used_stack = 0;
26232729
frame->call = call;

0 commit comments

Comments
 (0)