Skip to content

Commit ccc49ea

Browse files
committed
Change jit_trace_stack_frame layout
1 parent 7283dbb commit ccc49ea

File tree

3 files changed

+97
-63
lines changed

3 files changed

+97
-63
lines changed

ext/opcache/jit/zend_jit_internal.h

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -331,18 +331,67 @@ struct _zend_jit_trace_stack_frame {
331331
zend_jit_trace_stack_frame *call;
332332
zend_jit_trace_stack_frame *prev;
333333
const zend_function *func;
334-
union {
335-
struct {
336-
int8_t return_value_used;
337-
int8_t nested;
338-
int8_t num_args;
339-
int8_t last_send_by_ref;
340-
};
341-
int return_ssa_var;
342-
};
334+
uint32_t _info;
343335
zend_jit_trace_stack stack[1];
344336
};
345337

338+
#define TRACE_FRAME_SHIFT_NUM_ARGS 16
339+
#define TRACE_FRAME_MAX_NUM_ARGS 32767
340+
341+
#define TRACE_FRAME_MASK_NUM_ARGS 0xffff0000
342+
#define TRACE_FRAME_MASK_NESTED 0x00000001
343+
#define TRACE_FRAME_MASK_LAST_SEND_BY_REF 0x00000002
344+
#define TRACE_FRAME_MASK_LAST_SEND_BY_VAL 0x00000004
345+
#define TRACE_FRAME_MASK_RETURN_VALUE_USED 0x00000008
346+
#define TRACE_FRAME_MASK_RETURN_VALUE_UNUSED 0x00000010
347+
348+
349+
#define TRACE_FRAME_INIT(frame, _func, nested, num_args) do { \
350+
zend_jit_trace_stack_frame *_frame = (frame); \
351+
_frame->call = NULL; \
352+
_frame->prev = NULL; \
353+
_frame->func = (const zend_function*)_func; \
354+
_frame->_info = (uint32_t)((((int)(num_args)) << TRACE_FRAME_SHIFT_NUM_ARGS) & TRACE_FRAME_MASK_NUM_ARGS); \
355+
if (nested) { \
356+
_frame->_info |= TRACE_FRAME_MASK_NESTED; \
357+
}; \
358+
} while (0)
359+
360+
#define TRACE_FRAME_RETURN_SSA_VAR(frame) \
361+
((int)(frame)->_info)
362+
#define TRACE_FRAME_NUM_ARGS(frame) \
363+
((int)((frame)->_info) >> TRACE_FRAME_SHIFT_NUM_ARGS)
364+
#define TRACE_FRAME_IS_NESTED(frame) \
365+
((frame)->_info & TRACE_FRAME_MASK_NESTED)
366+
#define TRACE_FRAME_IS_LAST_SEND_BY_REF(frame) \
367+
((frame)->_info & TRACE_FRAME_MASK_LAST_SEND_BY_REF)
368+
#define TRACE_FRAME_IS_LAST_SEND_BY_VAL(frame) \
369+
((frame)->_info & TRACE_FRAME_MASK_LAST_SEND_BY_VAL)
370+
#define TRACE_FRAME_IS_RETURN_VALUE_USED(frame) \
371+
((frame)->_info & TRACE_FRAME_MASK_RETURN_VALUE_USED)
372+
#define TRACE_FRAME_IS_RETURN_VALUE_UNUSED(frame) \
373+
((frame)->_info & TRACE_FRAME_MASK_RETURN_VALUE_UNUSED)
374+
375+
#define TRACE_FRAME_SET_RETURN_SSA_VAR(frame, var) do { \
376+
(frame)->_info = var; \
377+
} while (0)
378+
#define TRACE_FRAME_SET_LAST_SEND_BY_REF(frame) do { \
379+
(frame)->_info |= TRACE_FRAME_MASK_LAST_SEND_BY_REF; \
380+
(frame)->_info &= ~TRACE_FRAME_MASK_LAST_SEND_BY_VAL; \
381+
} while (0)
382+
#define TRACE_FRAME_SET_LAST_SEND_BY_VAL(frame) do { \
383+
(frame)->_info |= TRACE_FRAME_MASK_LAST_SEND_BY_VAL; \
384+
(frame)->_info &= ~TRACE_FRAME_MASK_LAST_SEND_BY_REF; \
385+
} while (0)
386+
#define TRACE_FRAME_SET_RETURN_VALUE_USED(frame) do { \
387+
(frame)->_info |= TRACE_FRAME_MASK_RETURN_VALUE_USED; \
388+
(frame)->_info &= ~TRACE_FRAME_MASK_RETURN_VALUE_UNUSED; \
389+
} while (0)
390+
#define TRACE_FRAME_SET_RETURN_VALUE_UNUSED(frame) do { \
391+
(frame)->_info |= TRACE_FRAME_MASK_RETURN_VALUE_UNUSED; \
392+
(frame)->_info &= ~TRACE_FRAME_MASK_RETURN_VALUE_USED; \
393+
} while (0)
394+
346395
typedef struct _zend_jit_globals {
347396
zend_jit_trace_stack_frame *current_frame;
348397

ext/opcache/jit/zend_jit_trace.c

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ static int find_call_num_args(zend_jit_trace_rec *p)
734734
|| p->opline->opcode == ZEND_NEW
735735
|| p->opline->opcode == ZEND_INIT_METHOD_CALL
736736
|| p->opline->opcode == ZEND_INIT_STATIC_METHOD_CALL) {
737-
if (p->opline->extended_value <= 127) {
737+
if (p->opline->extended_value <= TRACE_FRAME_MAX_NUM_ARGS) {
738738
return p->opline->extended_value;
739739
} else {
740740
return -1;
@@ -1147,10 +1147,8 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
11471147

11481148
frame = JIT_G(current_frame);
11491149
top = zend_jit_trace_call_frame(frame, op_array);
1150-
frame->call = NULL;
1151-
frame->prev = NULL;
1152-
frame->func = (const zend_function*)op_array;
1153-
frame->return_ssa_var = -1;
1150+
TRACE_FRAME_INIT(frame, op_array, 0, 0);
1151+
TRACE_FRAME_SET_RETURN_SSA_VAR(frame, -1);
11541152
for (i = 0; i < op_array->last_var + op_array->T; i++) {
11551153
frame->stack[i] = -1;
11561154
}
@@ -1444,9 +1442,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
14441442
if (!call) {
14451443
/* Trace missed INIT_FCALL opcode */
14461444
call = top;
1447-
call->call = NULL;
1448-
call->prev = NULL;
1449-
call->func = (const zend_function*)op_array;
1445+
TRACE_FRAME_INIT(call, op_array, 0, 0);
14501446
top = zend_jit_trace_call_frame(top, op_array);
14511447
for (i = 0; i < op_array->last_var + op_array->T; i++) {
14521448
call->stack[i] = -1;
@@ -1456,7 +1452,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
14561452
}
14571453
frame->call = call->prev;
14581454
call->prev = frame;
1459-
call->return_ssa_var = find_return_ssa_var(p - 1, ssa_ops + (idx - 1));
1455+
TRACE_FRAME_SET_RETURN_SSA_VAR(call, find_return_ssa_var(p - 1, ssa_ops + (idx - 1)));
14601456
frame = call;
14611457

14621458
level++;
@@ -1534,8 +1530,8 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
15341530
if ((p+1)->op == ZEND_JIT_TRACE_VM) {
15351531
const zend_op *opline = (p+1)->opline - 1;
15361532
if (opline->result_type != IS_UNUSED) {
1537-
if (frame->return_ssa_var >= 0) {
1538-
ssa_var_info[frame->return_ssa_var] = return_value_info;
1533+
if (TRACE_FRAME_RETURN_SSA_VAR(frame) >= 0) {
1534+
ssa_var_info[TRACE_FRAME_RETURN_SSA_VAR(frame)] = return_value_info;
15391535
}
15401536
}
15411537
}
@@ -1549,20 +1545,17 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
15491545
ZEND_ASSERT(&frame->func->op_array == op_array);
15501546
} else {
15511547
frame = zend_jit_trace_ret_frame(frame, op_array);
1552-
frame->call = NULL;
1553-
frame->prev = NULL;
1554-
frame->func = (const zend_function*)op_array;
1555-
frame->return_ssa_var = -1;
1548+
TRACE_FRAME_INIT(frame, op_array, 0, 0);
1549+
TRACE_FRAME_SET_RETURN_SSA_VAR(frame, -1);
15561550
for (i = 0; i < op_array->last_var + op_array->T; i++) {
15571551
frame->stack[i] = -1;
15581552
}
15591553
}
15601554

15611555
} else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
15621556
call = top;
1563-
call->call = NULL;
1557+
TRACE_FRAME_INIT(call, p->func, 0, 0);
15641558
call->prev = frame->call;
1565-
call->func = p->func;
15661559
frame->call = call;
15671560
top = zend_jit_trace_call_frame(top, p->op_array);
15681561
if (p->func->type == ZEND_USER_FUNCTION) {
@@ -1662,13 +1655,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
16621655
op_array = p->op_array;
16631656
frame = JIT_G(current_frame);
16641657
top = zend_jit_trace_call_frame(frame, op_array);
1665-
frame->call = NULL;
1666-
frame->prev = NULL;
1667-
frame->func = (const zend_function*)op_array;
1668-
frame->return_value_used = -1;
1669-
frame->nested = 0;
1670-
frame->num_args = -1;
1671-
frame->last_send_by_ref = -1;
1658+
TRACE_FRAME_INIT(frame, op_array, 0, -1);
16721659
stack = frame->stack;
16731660

16741661
if (trace_buffer->start == ZEND_JIT_TRACE_START_ENTER) {
@@ -2885,12 +2872,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
28852872
if (!call) {
28862873
/* Trace missed INIT_FCALL opcode */
28872874
call = top;
2888-
call->call = NULL;
2889-
call->prev = NULL;
2890-
call->func = (const zend_function*)op_array;
2891-
call->nested = 0;
2892-
call->num_args = -1; // TODO: should be possible to get the real number ???
2893-
call->last_send_by_ref = -1;
2875+
TRACE_FRAME_INIT(call, op_array, 0, -1); // TODO: should be possible to get the real number af arguments ???
28942876
top = zend_jit_trace_call_frame(top, op_array);
28952877
i = 0;
28962878
while (i < p->op_array->num_args) {
@@ -2916,7 +2898,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
29162898
}
29172899
frame->call = call->prev;
29182900
call->prev = frame;
2919-
call->return_value_used = p->return_value_used;
2901+
if (p->return_value_used) {
2902+
TRACE_FRAME_SET_RETURN_VALUE_USED(call);
2903+
} else {
2904+
TRACE_FRAME_SET_RETURN_VALUE_UNUSED(call);
2905+
}
29202906
JIT_G(current_frame) = frame = call;
29212907
stack = frame->stack;
29222908
zend_jit_set_opline(&dasm_state, (p+1)->opline);
@@ -2932,13 +2918,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
29322918
ZEND_ASSERT(&frame->func->op_array == op_array);
29332919
} else {
29342920
frame = zend_jit_trace_ret_frame(frame, op_array);
2935-
frame->call = NULL;
2936-
frame->prev = NULL;
2937-
frame->func = (const zend_function*)op_array;
2938-
frame->return_value_used = -1;
2939-
frame->nested = 0;
2940-
frame->num_args = -1;
2941-
frame->last_send_by_ref = -1;
2921+
TRACE_FRAME_INIT(frame, op_array, 0, -1);
29422922
stack = frame->stack;
29432923
for (i = 0; i < op_array->last_var + op_array->T; i++) {
29442924
/* Initialize abstract stack using SSA */
@@ -2963,12 +2943,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
29632943
break;
29642944
} else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
29652945
call = top;
2966-
call->call = NULL;
2946+
TRACE_FRAME_INIT(call, p->func, 1, find_call_num_args(p-1));
29672947
call->prev = frame->call;
2968-
call->func = p->func;
2969-
call->nested = 1;
2970-
call->num_args = find_call_num_args(p-1);
2971-
call->last_send_by_ref = p->fake ? -1 : 0;
2948+
if (!p->fake) {
2949+
TRACE_FRAME_SET_LAST_SEND_BY_VAL(call);
2950+
}
29722951
frame->call = call;
29732952
top = zend_jit_trace_call_frame(top, p->op_array);
29742953
if (p->func->type == ZEND_USER_FUNCTION) {

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7881,8 +7881,8 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
78817881
func = trace->func;
78827882
if (JIT_G(current_frame) &&
78837883
JIT_G(current_frame)->call &&
7884-
JIT_G(current_frame)->call->num_args >= 0) {
7885-
call_num_args = JIT_G(current_frame)->call->num_args;
7884+
TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call) >= 0) {
7885+
call_num_args = TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call);
78867886
} else {
78877887
unknown_num_args = 1;
78887888
}
@@ -7893,8 +7893,8 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
78937893
func = trace->func;
78947894
if (JIT_G(current_frame) &&
78957895
JIT_G(current_frame)->call &&
7896-
JIT_G(current_frame)->call->num_args >= 0) {
7897-
call_num_args = JIT_G(current_frame)->call->num_args;
7896+
TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call) >= 0) {
7897+
call_num_args = TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call);
78987898
} else {
78997899
unknown_num_args = 1;
79007900
}
@@ -8319,7 +8319,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
83198319
if (zend_jit_trigger != ZEND_JIT_ON_HOT_TRACE ||
83208320
!JIT_G(current_frame) ||
83218321
!JIT_G(current_frame)->call ||
8322-
!JIT_G(current_frame)->call->nested) {
8322+
!TRACE_FRAME_IS_NESTED(JIT_G(current_frame)->call)) {
83238323

83248324
| // zend_vm_stack_free_call_frame(call);
83258325
| test byte [RX + offsetof(zend_execute_data, This.u1.type_info) + 2], (ZEND_CALL_ALLOCATED >> 16)
@@ -8759,8 +8759,8 @@ static int zend_jit_check_func_arg(dasm_State **Dst, const zend_op *opline, cons
87598759
&& JIT_G(current_frame)->call
87608760
&& JIT_G(current_frame)->call->func) {
87618761
if (ARG_SHOULD_BE_SENT_BY_REF(JIT_G(current_frame)->call->func, arg_num)) {
8762-
if (JIT_G(current_frame)->call->last_send_by_ref != 1) {
8763-
JIT_G(current_frame)->call->last_send_by_ref = 1;
8762+
if (!TRACE_FRAME_IS_LAST_SEND_BY_REF(JIT_G(current_frame)->call)) {
8763+
TRACE_FRAME_SET_LAST_SEND_BY_REF(JIT_G(current_frame)->call);
87648764
| // ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
87658765
|| if (reuse_ip) {
87668766
| or dword [RX + offsetof(zend_execute_data, This.u1.type_info)], ZEND_CALL_SEND_ARG_BY_REF
@@ -8770,8 +8770,8 @@ static int zend_jit_check_func_arg(dasm_State **Dst, const zend_op *opline, cons
87708770
|| }
87718771
}
87728772
} else {
8773-
if (JIT_G(current_frame)->call->last_send_by_ref != 0) {
8774-
JIT_G(current_frame)->call->last_send_by_ref = 0;
8773+
if (!TRACE_FRAME_IS_LAST_SEND_BY_VAL(JIT_G(current_frame)->call)) {
8774+
TRACE_FRAME_SET_LAST_SEND_BY_VAL(JIT_G(current_frame)->call);
87758775
| // ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
87768776
|| if (reuse_ip) {
87778777
| and dword [RX + offsetof(zend_execute_data, This.u1.type_info)], ~ZEND_CALL_SEND_ARG_BY_REF
@@ -9269,7 +9269,7 @@ static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const ze
92699269

92709270
if (zend_jit_trigger != ZEND_JIT_ON_HOT_TRACE ||
92719271
!JIT_G(current_frame) ||
9272-
!JIT_G(current_frame)->nested) {
9272+
!TRACE_FRAME_IS_NESTED(JIT_G(current_frame))) {
92739273
// TODO: try to avoid this check ???
92749274
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
92759275
| cmp IP, zend_jit_halt_op
@@ -9411,7 +9411,13 @@ static int zend_jit_return(dasm_State **Dst, const zend_op *opline, const zend_o
94119411
ZEND_ASSERT(!(op1_info & MAY_BE_UNDEF));
94129412

94139413
if (zend_jit_trigger == ZEND_JIT_ON_HOT_TRACE && JIT_G(current_frame)) {
9414-
return_value_used = JIT_G(current_frame)->return_value_used;
9414+
if (TRACE_FRAME_IS_RETURN_VALUE_USED(JIT_G(current_frame))) {
9415+
return_value_used = 1;
9416+
} else if (TRACE_FRAME_IS_RETURN_VALUE_UNUSED(JIT_G(current_frame))) {
9417+
return_value_used = 0;
9418+
} else {
9419+
return_value_used = -1;
9420+
}
94159421
} else {
94169422
return_value_used = -1;
94179423
}

0 commit comments

Comments
 (0)