@@ -987,6 +987,7 @@ static int is_checked_guard(const zend_ssa *tssa, const zend_op **ssa_opcodes, u
987
987
typedef struct _zend_tssa {
988
988
zend_ssa ssa ;
989
989
const zend_op * * tssa_opcodes ;
990
+ int used_stack ;
990
991
} zend_tssa ;
991
992
992
993
static const zend_op _nop_opcode = {0 };
@@ -1005,7 +1006,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1005
1006
zend_jit_trace_stack * stack ;
1006
1007
uint32_t build_flags = ZEND_SSA_RC_INFERENCE | ZEND_SSA_USE_CV_RESULTS ;
1007
1008
uint32_t optimization_level = 0 ;
1008
- int call_level , level , num_op_arrays ;
1009
+ int call_level , level , num_op_arrays , used_stack , max_used_stack ;
1009
1010
size_t frame_size , stack_top , stack_size , stack_bottom ;
1010
1011
zend_jit_op_array_trace_extension * jit_extension ;
1011
1012
zend_ssa * ssa ;
@@ -1172,6 +1173,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1172
1173
tssa -> cfg .blocks [0 ].successors_count = 0 ;
1173
1174
tssa -> cfg .blocks [0 ].predecessors_count = 0 ;
1174
1175
}
1176
+ ((zend_tssa * )tssa )-> used_stack = -1 ;
1175
1177
1176
1178
if (JIT_G (opt_level ) < ZEND_JIT_LEVEL_INLINE ) {
1177
1179
return tssa ;
@@ -1440,11 +1442,18 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1440
1442
top = zend_jit_trace_call_frame (frame , op_array );
1441
1443
TRACE_FRAME_INIT (frame , op_array , 0 , 0 );
1442
1444
TRACE_FRAME_SET_RETURN_SSA_VAR (frame , -1 );
1445
+ frame -> used_stack = 0 ;
1443
1446
for (i = 0 ; i < op_array -> last_var + op_array -> T ; i ++ ) {
1444
1447
SET_STACK_TYPE (frame -> stack , i , IS_UNKNOWN , 1 );
1445
1448
}
1446
1449
memset (& return_value_info , 0 , sizeof (return_value_info ));
1447
1450
1451
+ if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
1452
+ max_used_stack = used_stack = 0 ;
1453
+ } else {
1454
+ max_used_stack = used_stack = -1 ;
1455
+ }
1456
+
1448
1457
p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE ;
1449
1458
idx = 0 ;
1450
1459
level = 0 ;
@@ -1817,6 +1826,11 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1817
1826
ADD_OP2_TRACE_GUARD ();
1818
1827
}
1819
1828
break ;
1829
+ case ZEND_SEND_ARRAY :
1830
+ case ZEND_SEND_UNPACK :
1831
+ case ZEND_CHECK_UNDEF_ARGS :
1832
+ case ZEND_INCLUDE_OR_EVAL :
1833
+ max_used_stack = used_stack = -1 ;
1820
1834
default :
1821
1835
break ;
1822
1836
}
@@ -1961,6 +1975,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1961
1975
/* Trace missed INIT_FCALL opcode */
1962
1976
call = top ;
1963
1977
TRACE_FRAME_INIT (call , op_array , 0 , 0 );
1978
+ call -> used_stack = 0 ;
1964
1979
top = zend_jit_trace_call_frame (top , op_array );
1965
1980
for (i = 0 ; i < op_array -> last_var + op_array -> T ; i ++ ) {
1966
1981
SET_STACK_TYPE (call -> stack , i , IS_UNKNOWN , 1 );
@@ -2077,12 +2092,17 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
2077
2092
2078
2093
top = frame ;
2079
2094
if (frame -> prev ) {
2095
+ if (used_stack > 0 ) {
2096
+ used_stack -= frame -> used_stack ;
2097
+ }
2080
2098
frame = frame -> prev ;
2081
2099
ZEND_ASSERT (& frame -> func -> op_array == op_array );
2082
2100
} else {
2101
+ max_used_stack = used_stack = -1 ;
2083
2102
frame = zend_jit_trace_ret_frame (frame , op_array );
2084
2103
TRACE_FRAME_INIT (frame , op_array , 0 , 0 );
2085
2104
TRACE_FRAME_SET_RETURN_SSA_VAR (frame , -1 );
2105
+ frame -> used_stack = 0 ;
2086
2106
for (i = 0 ; i < op_array -> last_var + op_array -> T ; i ++ ) {
2087
2107
SET_STACK_TYPE (frame -> stack , i , IS_UNKNOWN , 1 );
2088
2108
}
@@ -2092,13 +2112,41 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
2092
2112
call = top ;
2093
2113
TRACE_FRAME_INIT (call , p -> func , 0 , 0 );
2094
2114
call -> prev = frame -> call ;
2115
+ call -> used_stack = 0 ;
2095
2116
frame -> call = call ;
2096
2117
top = zend_jit_trace_call_frame (top , p -> op_array );
2097
2118
if (p -> func && p -> func -> type == ZEND_USER_FUNCTION ) {
2098
2119
for (i = 0 ; i < p -> op_array -> last_var + p -> op_array -> T ; i ++ ) {
2099
2120
SET_STACK_INFO (call -> stack , i , -1 );
2100
2121
}
2101
2122
}
2123
+ if (used_stack >= 0
2124
+ && !(p -> info & ZEND_JIT_TRACE_FAKE_INIT_CALL )) {
2125
+ if (p -> func == NULL || (p - 1 )-> op != ZEND_JIT_TRACE_VM ) {
2126
+ max_used_stack = used_stack = -1 ;
2127
+ } else {
2128
+ const zend_op * opline = (p - 1 )-> opline ;
2129
+
2130
+ switch (opline -> opcode ) {
2131
+ case ZEND_INIT_FCALL :
2132
+ case ZEND_INIT_FCALL_BY_NAME :
2133
+ case ZEND_INIT_NS_FCALL_BY_NAME :
2134
+ case ZEND_INIT_METHOD_CALL :
2135
+ case ZEND_INIT_DYNAMIC_CALL :
2136
+ //case ZEND_INIT_STATIC_METHOD_CALL:
2137
+ //case ZEND_INIT_USER_CALL:
2138
+ //case ZEND_NEW:
2139
+ frame -> used_stack = zend_vm_calc_used_stack (opline -> extended_value , (zend_function * )p -> func );
2140
+ used_stack += frame -> used_stack ;
2141
+ if (used_stack > max_used_stack ) {
2142
+ max_used_stack = used_stack ;
2143
+ }
2144
+ break ;
2145
+ default :
2146
+ max_used_stack = used_stack = -1 ;
2147
+ }
2148
+ }
2149
+ }
2102
2150
} else if (p -> op == ZEND_JIT_TRACE_DO_ICALL ) {
2103
2151
call = frame -> call ;
2104
2152
if (call ) {
@@ -2110,6 +2158,8 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
2110
2158
}
2111
2159
}
2112
2160
2161
+ ((zend_tssa * )tssa )-> used_stack = max_used_stack ;
2162
+
2113
2163
if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
2114
2164
|| trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
2115
2165
|| trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
@@ -3379,6 +3429,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
3379
3429
zend_uchar res_type = IS_UNKNOWN ;
3380
3430
const zend_op * opline , * orig_opline ;
3381
3431
const zend_ssa_op * ssa_op , * orig_ssa_op ;
3432
+ int used_stack ;
3382
3433
3383
3434
JIT_G (current_trace ) = trace_buffer ;
3384
3435
@@ -3391,6 +3442,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
3391
3442
}
3392
3443
3393
3444
ssa_opcodes = ((zend_tssa * )ssa )-> tssa_opcodes ;
3445
+ used_stack = ((zend_tssa * )ssa )-> used_stack ;
3394
3446
3395
3447
/* Register allocation */
3396
3448
if ((JIT_G (opt_flags ) & (ZEND_JIT_REG_ALLOC_LOCAL |ZEND_JIT_REG_ALLOC_GLOBAL ))
@@ -3446,6 +3498,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
3446
3498
int parent_vars_count = 0 ;
3447
3499
zend_jit_trace_stack * parent_stack = NULL ;
3448
3500
3501
+ if (used_stack > 0 ) {
3502
+ if (!zend_jit_stack_check (& dasm_state , opline , used_stack )) {
3503
+ goto jit_failure ;
3504
+ }
3505
+ }
3506
+
3449
3507
if (parent_trace ) {
3450
3508
parent_vars_count = MIN (zend_jit_traces [parent_trace ].exit_info [exit_num ].stack_size ,
3451
3509
op_array -> last_var + op_array -> T );
@@ -4424,7 +4482,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
4424
4482
case ZEND_INIT_FCALL :
4425
4483
case ZEND_INIT_FCALL_BY_NAME :
4426
4484
case ZEND_INIT_NS_FCALL_BY_NAME :
4427
- 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 )) {
4485
+ 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 )) {
4428
4486
goto jit_failure ;
4429
4487
}
4430
4488
goto done ;
@@ -5403,7 +5461,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
5403
5461
op_array_ssa -> cfg .map ? op_array_ssa -> cfg .map [opline - op_array -> opcodes ] : -1 ,
5404
5462
op_array , ssa , ssa_op , frame -> call_level ,
5405
5463
op1_info , op1_addr , ce , ce_is_instanceof , delayed_fetch_this , op1_ce ,
5406
- p + 1 )) {
5464
+ p + 1 , used_stack < 0 )) {
5407
5465
goto jit_failure ;
5408
5466
}
5409
5467
goto done ;
@@ -5413,7 +5471,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
5413
5471
}
5414
5472
op2_info = OP2_INFO ();
5415
5473
CHECK_OP2_TRACE_TYPE ();
5416
- 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 )) {
5474
+ 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 )) {
5417
5475
goto jit_failure ;
5418
5476
}
5419
5477
goto done ;
0 commit comments