mirror of
https://github.com/php/php-src.git
synced 2024-09-22 10:27:25 +00:00
Change jit_trace_stack_frame layout
This commit is contained in:
parent
7283dbba27
commit
ccc49ead68
@ -331,18 +331,67 @@ struct _zend_jit_trace_stack_frame {
|
||||
zend_jit_trace_stack_frame *call;
|
||||
zend_jit_trace_stack_frame *prev;
|
||||
const zend_function *func;
|
||||
union {
|
||||
struct {
|
||||
int8_t return_value_used;
|
||||
int8_t nested;
|
||||
int8_t num_args;
|
||||
int8_t last_send_by_ref;
|
||||
};
|
||||
int return_ssa_var;
|
||||
};
|
||||
uint32_t _info;
|
||||
zend_jit_trace_stack stack[1];
|
||||
};
|
||||
|
||||
#define TRACE_FRAME_SHIFT_NUM_ARGS 16
|
||||
#define TRACE_FRAME_MAX_NUM_ARGS 32767
|
||||
|
||||
#define TRACE_FRAME_MASK_NUM_ARGS 0xffff0000
|
||||
#define TRACE_FRAME_MASK_NESTED 0x00000001
|
||||
#define TRACE_FRAME_MASK_LAST_SEND_BY_REF 0x00000002
|
||||
#define TRACE_FRAME_MASK_LAST_SEND_BY_VAL 0x00000004
|
||||
#define TRACE_FRAME_MASK_RETURN_VALUE_USED 0x00000008
|
||||
#define TRACE_FRAME_MASK_RETURN_VALUE_UNUSED 0x00000010
|
||||
|
||||
|
||||
#define TRACE_FRAME_INIT(frame, _func, nested, num_args) do { \
|
||||
zend_jit_trace_stack_frame *_frame = (frame); \
|
||||
_frame->call = NULL; \
|
||||
_frame->prev = NULL; \
|
||||
_frame->func = (const zend_function*)_func; \
|
||||
_frame->_info = (uint32_t)((((int)(num_args)) << TRACE_FRAME_SHIFT_NUM_ARGS) & TRACE_FRAME_MASK_NUM_ARGS); \
|
||||
if (nested) { \
|
||||
_frame->_info |= TRACE_FRAME_MASK_NESTED; \
|
||||
}; \
|
||||
} while (0)
|
||||
|
||||
#define TRACE_FRAME_RETURN_SSA_VAR(frame) \
|
||||
((int)(frame)->_info)
|
||||
#define TRACE_FRAME_NUM_ARGS(frame) \
|
||||
((int)((frame)->_info) >> TRACE_FRAME_SHIFT_NUM_ARGS)
|
||||
#define TRACE_FRAME_IS_NESTED(frame) \
|
||||
((frame)->_info & TRACE_FRAME_MASK_NESTED)
|
||||
#define TRACE_FRAME_IS_LAST_SEND_BY_REF(frame) \
|
||||
((frame)->_info & TRACE_FRAME_MASK_LAST_SEND_BY_REF)
|
||||
#define TRACE_FRAME_IS_LAST_SEND_BY_VAL(frame) \
|
||||
((frame)->_info & TRACE_FRAME_MASK_LAST_SEND_BY_VAL)
|
||||
#define TRACE_FRAME_IS_RETURN_VALUE_USED(frame) \
|
||||
((frame)->_info & TRACE_FRAME_MASK_RETURN_VALUE_USED)
|
||||
#define TRACE_FRAME_IS_RETURN_VALUE_UNUSED(frame) \
|
||||
((frame)->_info & TRACE_FRAME_MASK_RETURN_VALUE_UNUSED)
|
||||
|
||||
#define TRACE_FRAME_SET_RETURN_SSA_VAR(frame, var) do { \
|
||||
(frame)->_info = var; \
|
||||
} while (0)
|
||||
#define TRACE_FRAME_SET_LAST_SEND_BY_REF(frame) do { \
|
||||
(frame)->_info |= TRACE_FRAME_MASK_LAST_SEND_BY_REF; \
|
||||
(frame)->_info &= ~TRACE_FRAME_MASK_LAST_SEND_BY_VAL; \
|
||||
} while (0)
|
||||
#define TRACE_FRAME_SET_LAST_SEND_BY_VAL(frame) do { \
|
||||
(frame)->_info |= TRACE_FRAME_MASK_LAST_SEND_BY_VAL; \
|
||||
(frame)->_info &= ~TRACE_FRAME_MASK_LAST_SEND_BY_REF; \
|
||||
} while (0)
|
||||
#define TRACE_FRAME_SET_RETURN_VALUE_USED(frame) do { \
|
||||
(frame)->_info |= TRACE_FRAME_MASK_RETURN_VALUE_USED; \
|
||||
(frame)->_info &= ~TRACE_FRAME_MASK_RETURN_VALUE_UNUSED; \
|
||||
} while (0)
|
||||
#define TRACE_FRAME_SET_RETURN_VALUE_UNUSED(frame) do { \
|
||||
(frame)->_info |= TRACE_FRAME_MASK_RETURN_VALUE_UNUSED; \
|
||||
(frame)->_info &= ~TRACE_FRAME_MASK_RETURN_VALUE_USED; \
|
||||
} while (0)
|
||||
|
||||
typedef struct _zend_jit_globals {
|
||||
zend_jit_trace_stack_frame *current_frame;
|
||||
|
||||
|
@ -734,7 +734,7 @@ static int find_call_num_args(zend_jit_trace_rec *p)
|
||||
|| p->opline->opcode == ZEND_NEW
|
||||
|| p->opline->opcode == ZEND_INIT_METHOD_CALL
|
||||
|| p->opline->opcode == ZEND_INIT_STATIC_METHOD_CALL) {
|
||||
if (p->opline->extended_value <= 127) {
|
||||
if (p->opline->extended_value <= TRACE_FRAME_MAX_NUM_ARGS) {
|
||||
return p->opline->extended_value;
|
||||
} else {
|
||||
return -1;
|
||||
@ -1147,10 +1147,8 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
|
||||
|
||||
frame = JIT_G(current_frame);
|
||||
top = zend_jit_trace_call_frame(frame, op_array);
|
||||
frame->call = NULL;
|
||||
frame->prev = NULL;
|
||||
frame->func = (const zend_function*)op_array;
|
||||
frame->return_ssa_var = -1;
|
||||
TRACE_FRAME_INIT(frame, op_array, 0, 0);
|
||||
TRACE_FRAME_SET_RETURN_SSA_VAR(frame, -1);
|
||||
for (i = 0; i < op_array->last_var + op_array->T; i++) {
|
||||
frame->stack[i] = -1;
|
||||
}
|
||||
@ -1444,9 +1442,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
|
||||
if (!call) {
|
||||
/* Trace missed INIT_FCALL opcode */
|
||||
call = top;
|
||||
call->call = NULL;
|
||||
call->prev = NULL;
|
||||
call->func = (const zend_function*)op_array;
|
||||
TRACE_FRAME_INIT(call, op_array, 0, 0);
|
||||
top = zend_jit_trace_call_frame(top, op_array);
|
||||
for (i = 0; i < op_array->last_var + op_array->T; i++) {
|
||||
call->stack[i] = -1;
|
||||
@ -1456,7 +1452,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
|
||||
}
|
||||
frame->call = call->prev;
|
||||
call->prev = frame;
|
||||
call->return_ssa_var = find_return_ssa_var(p - 1, ssa_ops + (idx - 1));
|
||||
TRACE_FRAME_SET_RETURN_SSA_VAR(call, find_return_ssa_var(p - 1, ssa_ops + (idx - 1)));
|
||||
frame = call;
|
||||
|
||||
level++;
|
||||
@ -1534,8 +1530,8 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
|
||||
if ((p+1)->op == ZEND_JIT_TRACE_VM) {
|
||||
const zend_op *opline = (p+1)->opline - 1;
|
||||
if (opline->result_type != IS_UNUSED) {
|
||||
if (frame->return_ssa_var >= 0) {
|
||||
ssa_var_info[frame->return_ssa_var] = return_value_info;
|
||||
if (TRACE_FRAME_RETURN_SSA_VAR(frame) >= 0) {
|
||||
ssa_var_info[TRACE_FRAME_RETURN_SSA_VAR(frame)] = return_value_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1549,10 +1545,8 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
|
||||
ZEND_ASSERT(&frame->func->op_array == op_array);
|
||||
} else {
|
||||
frame = zend_jit_trace_ret_frame(frame, op_array);
|
||||
frame->call = NULL;
|
||||
frame->prev = NULL;
|
||||
frame->func = (const zend_function*)op_array;
|
||||
frame->return_ssa_var = -1;
|
||||
TRACE_FRAME_INIT(frame, op_array, 0, 0);
|
||||
TRACE_FRAME_SET_RETURN_SSA_VAR(frame, -1);
|
||||
for (i = 0; i < op_array->last_var + op_array->T; i++) {
|
||||
frame->stack[i] = -1;
|
||||
}
|
||||
@ -1560,9 +1554,8 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
|
||||
|
||||
} else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
|
||||
call = top;
|
||||
call->call = NULL;
|
||||
TRACE_FRAME_INIT(call, p->func, 0, 0);
|
||||
call->prev = frame->call;
|
||||
call->func = p->func;
|
||||
frame->call = call;
|
||||
top = zend_jit_trace_call_frame(top, p->op_array);
|
||||
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
|
||||
op_array = p->op_array;
|
||||
frame = JIT_G(current_frame);
|
||||
top = zend_jit_trace_call_frame(frame, op_array);
|
||||
frame->call = NULL;
|
||||
frame->prev = NULL;
|
||||
frame->func = (const zend_function*)op_array;
|
||||
frame->return_value_used = -1;
|
||||
frame->nested = 0;
|
||||
frame->num_args = -1;
|
||||
frame->last_send_by_ref = -1;
|
||||
TRACE_FRAME_INIT(frame, op_array, 0, -1);
|
||||
stack = frame->stack;
|
||||
|
||||
if (trace_buffer->start == ZEND_JIT_TRACE_START_ENTER) {
|
||||
@ -2885,12 +2872,7 @@ done:
|
||||
if (!call) {
|
||||
/* Trace missed INIT_FCALL opcode */
|
||||
call = top;
|
||||
call->call = NULL;
|
||||
call->prev = NULL;
|
||||
call->func = (const zend_function*)op_array;
|
||||
call->nested = 0;
|
||||
call->num_args = -1; // TODO: should be possible to get the real number ???
|
||||
call->last_send_by_ref = -1;
|
||||
TRACE_FRAME_INIT(call, op_array, 0, -1); // TODO: should be possible to get the real number af arguments ???
|
||||
top = zend_jit_trace_call_frame(top, op_array);
|
||||
i = 0;
|
||||
while (i < p->op_array->num_args) {
|
||||
@ -2916,7 +2898,11 @@ done:
|
||||
}
|
||||
frame->call = call->prev;
|
||||
call->prev = frame;
|
||||
call->return_value_used = p->return_value_used;
|
||||
if (p->return_value_used) {
|
||||
TRACE_FRAME_SET_RETURN_VALUE_USED(call);
|
||||
} else {
|
||||
TRACE_FRAME_SET_RETURN_VALUE_UNUSED(call);
|
||||
}
|
||||
JIT_G(current_frame) = frame = call;
|
||||
stack = frame->stack;
|
||||
zend_jit_set_opline(&dasm_state, (p+1)->opline);
|
||||
@ -2932,13 +2918,7 @@ done:
|
||||
ZEND_ASSERT(&frame->func->op_array == op_array);
|
||||
} else {
|
||||
frame = zend_jit_trace_ret_frame(frame, op_array);
|
||||
frame->call = NULL;
|
||||
frame->prev = NULL;
|
||||
frame->func = (const zend_function*)op_array;
|
||||
frame->return_value_used = -1;
|
||||
frame->nested = 0;
|
||||
frame->num_args = -1;
|
||||
frame->last_send_by_ref = -1;
|
||||
TRACE_FRAME_INIT(frame, op_array, 0, -1);
|
||||
stack = frame->stack;
|
||||
for (i = 0; i < op_array->last_var + op_array->T; i++) {
|
||||
/* Initialize abstract stack using SSA */
|
||||
@ -2963,12 +2943,11 @@ done:
|
||||
break;
|
||||
} else if (p->op == ZEND_JIT_TRACE_INIT_CALL) {
|
||||
call = top;
|
||||
call->call = NULL;
|
||||
TRACE_FRAME_INIT(call, p->func, 1, find_call_num_args(p-1));
|
||||
call->prev = frame->call;
|
||||
call->func = p->func;
|
||||
call->nested = 1;
|
||||
call->num_args = find_call_num_args(p-1);
|
||||
call->last_send_by_ref = p->fake ? -1 : 0;
|
||||
if (!p->fake) {
|
||||
TRACE_FRAME_SET_LAST_SEND_BY_VAL(call);
|
||||
}
|
||||
frame->call = call;
|
||||
top = zend_jit_trace_call_frame(top, p->op_array);
|
||||
if (p->func->type == ZEND_USER_FUNCTION) {
|
||||
|
@ -7881,8 +7881,8 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
|
||||
func = trace->func;
|
||||
if (JIT_G(current_frame) &&
|
||||
JIT_G(current_frame)->call &&
|
||||
JIT_G(current_frame)->call->num_args >= 0) {
|
||||
call_num_args = JIT_G(current_frame)->call->num_args;
|
||||
TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call) >= 0) {
|
||||
call_num_args = TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call);
|
||||
} else {
|
||||
unknown_num_args = 1;
|
||||
}
|
||||
@ -7893,8 +7893,8 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
|
||||
func = trace->func;
|
||||
if (JIT_G(current_frame) &&
|
||||
JIT_G(current_frame)->call &&
|
||||
JIT_G(current_frame)->call->num_args >= 0) {
|
||||
call_num_args = JIT_G(current_frame)->call->num_args;
|
||||
TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call) >= 0) {
|
||||
call_num_args = TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call);
|
||||
} else {
|
||||
unknown_num_args = 1;
|
||||
}
|
||||
@ -8319,7 +8319,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
|
||||
if (zend_jit_trigger != ZEND_JIT_ON_HOT_TRACE ||
|
||||
!JIT_G(current_frame) ||
|
||||
!JIT_G(current_frame)->call ||
|
||||
!JIT_G(current_frame)->call->nested) {
|
||||
!TRACE_FRAME_IS_NESTED(JIT_G(current_frame)->call)) {
|
||||
|
||||
| // zend_vm_stack_free_call_frame(call);
|
||||
| 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
|
||||
&& JIT_G(current_frame)->call
|
||||
&& JIT_G(current_frame)->call->func) {
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(JIT_G(current_frame)->call->func, arg_num)) {
|
||||
if (JIT_G(current_frame)->call->last_send_by_ref != 1) {
|
||||
JIT_G(current_frame)->call->last_send_by_ref = 1;
|
||||
if (!TRACE_FRAME_IS_LAST_SEND_BY_REF(JIT_G(current_frame)->call)) {
|
||||
TRACE_FRAME_SET_LAST_SEND_BY_REF(JIT_G(current_frame)->call);
|
||||
| // ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
|
||||
|| if (reuse_ip) {
|
||||
| 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
|
||||
|| }
|
||||
}
|
||||
} else {
|
||||
if (JIT_G(current_frame)->call->last_send_by_ref != 0) {
|
||||
JIT_G(current_frame)->call->last_send_by_ref = 0;
|
||||
if (!TRACE_FRAME_IS_LAST_SEND_BY_VAL(JIT_G(current_frame)->call)) {
|
||||
TRACE_FRAME_SET_LAST_SEND_BY_VAL(JIT_G(current_frame)->call);
|
||||
| // ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
|
||||
|| if (reuse_ip) {
|
||||
| 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
|
||||
|
||||
if (zend_jit_trigger != ZEND_JIT_ON_HOT_TRACE ||
|
||||
!JIT_G(current_frame) ||
|
||||
!JIT_G(current_frame)->nested) {
|
||||
!TRACE_FRAME_IS_NESTED(JIT_G(current_frame))) {
|
||||
// TODO: try to avoid this check ???
|
||||
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
|
||||
| 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
|
||||
ZEND_ASSERT(!(op1_info & MAY_BE_UNDEF));
|
||||
|
||||
if (zend_jit_trigger == ZEND_JIT_ON_HOT_TRACE && JIT_G(current_frame)) {
|
||||
return_value_used = JIT_G(current_frame)->return_value_used;
|
||||
if (TRACE_FRAME_IS_RETURN_VALUE_USED(JIT_G(current_frame))) {
|
||||
return_value_used = 1;
|
||||
} else if (TRACE_FRAME_IS_RETURN_VALUE_UNUSED(JIT_G(current_frame))) {
|
||||
return_value_used = 0;
|
||||
} else {
|
||||
return_value_used = -1;
|
||||
}
|
||||
} else {
|
||||
return_value_used = -1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user