Skip to content

Commit 0424ce0

Browse files
committed
Avoid redundand repeatable VM stack overflow checks
1 parent 5e424d2 commit 0424ce0

File tree

4 files changed

+46
-21
lines changed

4 files changed

+46
-21
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3304,7 +3304,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
33043304
case ZEND_INIT_FCALL:
33053305
case ZEND_INIT_FCALL_BY_NAME:
33063306
case ZEND_INIT_NS_FCALL_BY_NAME:
3307-
if (!zend_jit_init_fcall(&dasm_state, opline, b, op_array, ssa, ssa_op, call_level, NULL, 1)) {
3307+
if (!zend_jit_init_fcall(&dasm_state, opline, b, op_array, ssa, ssa_op, call_level, NULL, 0)) {
33083308
goto jit_failure;
33093309
}
33103310
goto done;
@@ -3895,7 +3895,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
38953895
}
38963896
if (!zend_jit_init_method_call(&dasm_state, opline, b, op_array, ssa, ssa_op, call_level,
38973897
op1_info, op1_addr, ce, ce_is_instanceof, 0, NULL,
3898-
NULL, 1, 0)) {
3898+
NULL, 0, 0)) {
38993899
goto jit_failure;
39003900
}
39013901
goto done;

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8152,15 +8152,19 @@ static int zend_jit_stack_check(dasm_State **Dst, const zend_op *opline, uint32_
81528152
return 1;
81538153
}
81548154

8155-
static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_function *func, bool is_closure, bool use_this, bool stack_check)
8155+
static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_function *func, bool is_closure, bool use_this, int checked_stack)
81568156
{
81578157
uint32_t used_stack;
8158+
bool stack_check = 1;
81588159

81598160
// REG0 -> zend_function
81608161
// FCARG1 -> used_stack
81618162

81628163
if (func) {
81638164
used_stack = zend_vm_calc_used_stack(opline->extended_value, func);
8165+
if ((int)used_stack <= checked_stack) {
8166+
stack_check = 0;
8167+
}
81648168
} else {
81658169
used_stack = (ZEND_CALL_FRAME_SLOT + opline->extended_value) * sizeof(zval);
81668170

@@ -8406,7 +8410,7 @@ static int zend_jit_init_fcall_guard(dasm_State **Dst, uint32_t level, const zen
84068410
return 1;
84078411
}
84088412

8409-
static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t b, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, int call_level, zend_jit_trace_rec *trace, bool stack_check)
8413+
static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t b, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, int call_level, zend_jit_trace_rec *trace, int checked_stack)
84108414
{
84118415
zend_func_info *info = ZEND_FUNC_INFO(op_array);
84128416
zend_call_info *call_info = NULL;
@@ -8514,7 +8518,7 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t
85148518
|3:
85158519
}
85168520

8517-
if (!zend_jit_push_call_frame(Dst, opline, op_array, func, 0, 0, stack_check)) {
8521+
if (!zend_jit_push_call_frame(Dst, opline, op_array, func, 0, 0, checked_stack)) {
85188522
return 0;
85198523
}
85208524

@@ -8544,7 +8548,7 @@ static int zend_jit_init_method_call(dasm_State **Dst,
85448548
bool use_this,
85458549
zend_class_entry *trace_ce,
85468550
zend_jit_trace_rec *trace,
8547-
bool stack_check,
8551+
int checked_stack,
85488552
bool polymorphic_side_trace)
85498553
{
85508554
zend_func_info *info = ZEND_FUNC_INFO(op_array);
@@ -8728,7 +8732,7 @@ static int zend_jit_init_method_call(dasm_State **Dst,
87288732
}
87298733

87308734
if (!func || (func->common.fn_flags & ZEND_ACC_STATIC) == 0) {
8731-
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 0, use_this, stack_check)) {
8735+
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 0, use_this, checked_stack)) {
87328736
return 0;
87338737
}
87348738
}
@@ -8758,7 +8762,7 @@ static int zend_jit_init_closure_call(dasm_State **Dst,
87588762
const zend_ssa_op *ssa_op,
87598763
int call_level,
87608764
zend_jit_trace_rec *trace,
8761-
bool stack_check)
8765+
int checked_stack)
87628766
{
87638767
zend_function *func = NULL;
87648768
zend_jit_addr op2_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
@@ -8813,7 +8817,7 @@ static int zend_jit_init_closure_call(dasm_State **Dst,
88138817
}
88148818
}
88158819

8816-
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 1, 0, stack_check)) {
8820+
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 1, 0, checked_stack)) {
88178821
return 0;
88188822
}
88198823

ext/opcache/jit/zend_jit_trace.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3756,7 +3756,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
37563756
zend_uchar res_type = IS_UNKNOWN;
37573757
const zend_op *opline, *orig_opline;
37583758
const zend_ssa_op *ssa_op, *orig_ssa_op;
3759-
int used_stack;
3759+
int checked_stack;
3760+
int peek_checked_stack;
37603761
uint32_t frame_flags = 0;
37613762

37623763
JIT_G(current_trace) = trace_buffer;
@@ -3770,7 +3771,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
37703771
}
37713772

37723773
ssa_opcodes = ((zend_tssa*)ssa)->tssa_opcodes;
3773-
used_stack = ((zend_tssa*)ssa)->used_stack;
37743774

37753775
/* Register allocation */
37763776
if ((JIT_G(opt_flags) & (ZEND_JIT_REG_ALLOC_LOCAL|ZEND_JIT_REG_ALLOC_GLOBAL))
@@ -3784,6 +3784,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
37843784
frame = JIT_G(current_frame);
37853785
top = zend_jit_trace_call_frame(frame, op_array);
37863786
TRACE_FRAME_INIT(frame, op_array, TRACE_FRAME_MASK_UNKNOWN_RETURN, -1);
3787+
frame->used_stack = checked_stack = peek_checked_stack = 0;
37873788
stack = frame->stack;
37883789
for (i = 0; i < op_array->last_var + op_array->T; i++) {
37893790
SET_STACK_TYPE(stack, i, IS_UNKNOWN, 1);
@@ -3826,8 +3827,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
38263827
int last_var;
38273828
int parent_vars_count = 0;
38283829
zend_jit_trace_stack *parent_stack = NULL;
3830+
int used_stack = ((zend_tssa*)ssa)->used_stack;
38293831

38303832
if (used_stack > 0) {
3833+
peek_checked_stack = used_stack;
38313834
if (!zend_jit_stack_check(&dasm_state, opline, used_stack)) {
38323835
goto jit_failure;
38333836
}
@@ -4703,7 +4706,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
47034706
case ZEND_INIT_FCALL_BY_NAME:
47044707
case ZEND_INIT_NS_FCALL_BY_NAME:
47054708
frame_flags = TRACE_FRAME_MASK_NESTED;
4706-
if (!zend_jit_init_fcall(&dasm_state, opline, op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1, op_array, ssa, ssa_op, frame->call_level, p + 1, used_stack < 0)) {
4709+
if (!zend_jit_init_fcall(&dasm_state, opline, op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1, op_array, ssa, ssa_op, frame->call_level, p + 1, peek_checked_stack - checked_stack)) {
47074710
goto jit_failure;
47084711
}
47094712
goto done;
@@ -5740,7 +5743,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
57405743
op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1,
57415744
op_array, ssa, ssa_op, frame->call_level,
57425745
op1_info, op1_addr, ce, ce_is_instanceof, delayed_fetch_this, op1_ce,
5743-
p + 1, used_stack < 0, polymorphic_side_trace)) {
5746+
p + 1, peek_checked_stack - checked_stack, polymorphic_side_trace)) {
57445747
goto jit_failure;
57455748
}
57465749
goto done;
@@ -5751,7 +5754,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
57515754
op2_info = OP2_INFO();
57525755
CHECK_OP2_TRACE_TYPE();
57535756
frame_flags = TRACE_FRAME_MASK_NESTED;
5754-
if (!zend_jit_init_closure_call(&dasm_state, opline, op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1, op_array, ssa, ssa_op, frame->call_level, p + 1, used_stack < 0)) {
5757+
if (!zend_jit_init_closure_call(&dasm_state, opline, op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1, op_array, ssa, ssa_op, frame->call_level, p + 1, peek_checked_stack - checked_stack)) {
57555758
goto jit_failure;
57565759
}
57575760
goto done;
@@ -6183,12 +6186,14 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
61836186
op_array_ssa = &jit_extension->func_info.ssa;
61846187
top = frame;
61856188
if (frame->prev) {
6189+
checked_stack -= frame->used_stack;
61866190
frame = frame->prev;
61876191
stack = frame->stack;
61886192
ZEND_ASSERT(&frame->func->op_array == op_array);
61896193
} else {
61906194
frame = zend_jit_trace_ret_frame(frame, op_array);
61916195
TRACE_FRAME_INIT(frame, op_array, TRACE_FRAME_MASK_UNKNOWN_RETURN, -1);
6196+
frame->used_stack = checked_stack = peek_checked_stack = 0;
61926197
stack = frame->stack;
61936198
if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_INLINE) {
61946199
uint32_t j = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
@@ -6337,10 +6342,22 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
63376342
}
63386343
if (p->info & ZEND_JIT_TRACE_FAKE_INIT_CALL) {
63396344
frame->call_level++;
6345+
call->used_stack = 0;
6346+
} else {
6347+
if (p->func) {
6348+
call->used_stack = zend_vm_calc_used_stack(init_opline->extended_value, (zend_function*)p->func);
6349+
} else {
6350+
call->used_stack = (ZEND_CALL_FRAME_SLOT + init_opline->extended_value) * sizeof(zval);
6351+
}
6352+
checked_stack += call->used_stack;
6353+
if (checked_stack > peek_checked_stack) {
6354+
peek_checked_stack = checked_stack;
6355+
}
63406356
}
63416357
} else if (p->op == ZEND_JIT_TRACE_DO_ICALL) {
63426358
call = frame->call;
63436359
if (call) {
6360+
checked_stack -= call->used_stack;
63446361
top = call;
63456362
frame->call = call->prev;
63466363
}

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8701,12 +8701,16 @@ static int zend_jit_stack_check(dasm_State **Dst, const zend_op *opline, uint32_
87018701
return 1;
87028702
}
87038703

8704-
static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_function *func, bool is_closure, bool use_this, bool stack_check)
8704+
static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_function *func, bool is_closure, bool use_this, int checked_stack)
87058705
{
87068706
uint32_t used_stack;
8707+
bool stack_check = 1;
87078708

87088709
if (func) {
87098710
used_stack = zend_vm_calc_used_stack(opline->extended_value, func);
8711+
if ((int)used_stack <= checked_stack) {
8712+
stack_check = 0;
8713+
}
87108714
} else {
87118715
used_stack = (ZEND_CALL_FRAME_SLOT + opline->extended_value) * sizeof(zval);
87128716

@@ -8959,7 +8963,7 @@ static int zend_jit_init_fcall_guard(dasm_State **Dst, uint32_t level, const zen
89598963
return 1;
89608964
}
89618965

8962-
static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t b, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, int call_level, zend_jit_trace_rec *trace, bool stack_check)
8966+
static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t b, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, int call_level, zend_jit_trace_rec *trace, int checked_stack)
89638967
{
89648968
zend_func_info *info = ZEND_FUNC_INFO(op_array);
89658969
zend_call_info *call_info = NULL;
@@ -9095,7 +9099,7 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t
90959099
|3:
90969100
}
90979101

9098-
if (!zend_jit_push_call_frame(Dst, opline, op_array, func, 0, 0, stack_check)) {
9102+
if (!zend_jit_push_call_frame(Dst, opline, op_array, func, 0, 0, checked_stack)) {
90999103
return 0;
91009104
}
91019105

@@ -9125,7 +9129,7 @@ static int zend_jit_init_method_call(dasm_State **Dst,
91259129
bool use_this,
91269130
zend_class_entry *trace_ce,
91279131
zend_jit_trace_rec *trace,
9128-
bool stack_check,
9132+
int checked_stack,
91299133
bool polymorphic_side_trace)
91309134
{
91319135
zend_func_info *info = ZEND_FUNC_INFO(op_array);
@@ -9340,7 +9344,7 @@ static int zend_jit_init_method_call(dasm_State **Dst,
93409344
}
93419345

93429346
if (!func || (func->common.fn_flags & ZEND_ACC_STATIC) == 0) {
9343-
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 0, use_this, stack_check)) {
9347+
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 0, use_this, checked_stack)) {
93449348
return 0;
93459349
}
93469350
}
@@ -9370,7 +9374,7 @@ static int zend_jit_init_closure_call(dasm_State **Dst,
93709374
const zend_ssa_op *ssa_op,
93719375
int call_level,
93729376
zend_jit_trace_rec *trace,
9373-
bool stack_check)
9377+
int checked_stack)
93749378
{
93759379
zend_function *func = NULL;
93769380
zend_jit_addr op2_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
@@ -9439,7 +9443,7 @@ static int zend_jit_init_closure_call(dasm_State **Dst,
94399443
}
94409444
}
94419445

9442-
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 1, 0, stack_check)) {
9446+
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 1, 0, checked_stack)) {
94439447
return 0;
94449448
}
94459449

0 commit comments

Comments
 (0)