Skip to content

Commit 2a71cb3

Browse files
committed
Improved trace selection rules
1 parent 2f601d8 commit 2a71cb3

File tree

2 files changed

+88
-8
lines changed

2 files changed

+88
-8
lines changed

ext/opcache/jit/zend_jit_trace.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6251,6 +6251,28 @@ int ZEND_FASTCALL zend_jit_trace_hot_root(zend_execute_data *execute_data, const
62516251
}
62526252
stop &= ~ZEND_JIT_TRACE_HALT;
62536253

6254+
if (UNEXPECTED(trace_buffer[1].opline != orig_opline)) {
6255+
orig_opline = trace_buffer[1].opline;
6256+
op_array = (zend_op_array*)trace_buffer[0].op_array;
6257+
jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
6258+
offset = jit_extension->offset;
6259+
if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_START) {
6260+
const zend_op_array *op_array = trace_buffer[0].op_array;
6261+
const zend_op *opline = trace_buffer[1].opline;
6262+
zend_jit_op_array_trace_extension *jit_extension =
6263+
(zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
6264+
size_t offset = jit_extension->offset;
6265+
6266+
fprintf(stderr, "---- TRACE %d start (%s) %s() %s:%d\n",
6267+
trace_num,
6268+
zend_jit_trace_star_desc(ZEND_OP_TRACE_INFO(opline, offset)->trace_flags),
6269+
op_array->function_name ?
6270+
ZSTR_VAL(op_array->function_name) : "$main",
6271+
ZSTR_VAL(op_array->filename),
6272+
opline->lineno);
6273+
}
6274+
}
6275+
62546276
if (UNEXPECTED(JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_BYTECODE)) {
62556277
zend_jit_dump_trace(trace_buffer, NULL);
62566278
}
@@ -6539,6 +6561,24 @@ int ZEND_FASTCALL zend_jit_trace_hot_side(zend_execute_data *execute_data, uint3
65396561
}
65406562
stop &= ~ZEND_JIT_TRACE_HALT;
65416563

6564+
if (UNEXPECTED(trace_buffer->start != ZEND_JIT_TRACE_START_SIDE)) {
6565+
if (JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_START) {
6566+
const zend_op_array *op_array = trace_buffer[0].op_array;
6567+
const zend_op *opline = trace_buffer[1].opline;
6568+
zend_jit_op_array_trace_extension *jit_extension =
6569+
(zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
6570+
size_t offset = jit_extension->offset;
6571+
6572+
fprintf(stderr, "---- TRACE %d start (%s) %s() %s:%d\n",
6573+
trace_num,
6574+
zend_jit_trace_star_desc(ZEND_OP_TRACE_INFO(opline, offset)->trace_flags),
6575+
op_array->function_name ?
6576+
ZSTR_VAL(op_array->function_name) : "$main",
6577+
ZSTR_VAL(op_array->filename),
6578+
opline->lineno);
6579+
}
6580+
}
6581+
65426582
if (UNEXPECTED(JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_BYTECODE)) {
65436583
zend_jit_dump_trace(trace_buffer, NULL);
65446584
}
@@ -6557,7 +6597,7 @@ int ZEND_FASTCALL zend_jit_trace_hot_side(zend_execute_data *execute_data, uint3
65576597
zend_jit_trace_stop_description[stop]);
65586598
}
65596599
}
6560-
if (EXPECTED(stop != ZEND_JIT_TRACE_STOP_LOOP)) {
6600+
if (EXPECTED(trace_buffer->start == ZEND_JIT_TRACE_START_SIDE)) {
65616601
stop = zend_jit_compile_side_trace(trace_buffer, parent_num, exit_num, polymorphism);
65626602
} else {
65636603
const zend_op_array *op_array = trace_buffer[0].op_array;
@@ -6591,6 +6631,10 @@ int ZEND_FASTCALL zend_jit_trace_hot_side(zend_execute_data *execute_data, uint3
65916631
parent_num, exit_num);
65926632
}
65936633
}
6634+
if (ZEND_JIT_TRACE_STOP_REPEAT(stop)) {
6635+
execute_data = EG(current_execute_data);
6636+
return zend_jit_trace_hot_root(execute_data, EX(opline));
6637+
}
65946638
}
65956639

65966640
if (JIT_G(debug) & (ZEND_JIT_DEBUG_TRACE_STOP|ZEND_JIT_DEBUG_TRACE_ABORT|ZEND_JIT_DEBUG_TRACE_COMPILED|ZEND_JIT_DEBUG_TRACE_BLACKLIST)) {

ext/opcache/jit/zend_jit_vm_helpers.c

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,15 @@ static int zend_jit_trace_call_level(const zend_execute_data *call)
503503
return call_level;
504504
}
505505

506+
static int zend_jit_trace_subtrace(zend_jit_trace_rec *trace_buffer, int start, int end, uint8_t event, const zend_op_array *op_array, const zend_op *opline)
507+
{
508+
int idx;
509+
510+
TRACE_START(ZEND_JIT_TRACE_START, event, op_array, opline);
511+
memmove(trace_buffer + idx, trace_buffer + start, (end - start) * sizeof(zend_jit_trace_rec));
512+
return idx + (end - start);
513+
}
514+
506515
/*
507516
* Trace Linking Rules
508517
* ===================
@@ -559,6 +568,9 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
559568
int backtrack_ret_recursion = -1;
560569
int backtrack_ret_recursion_level = 0;
561570
int loop_unroll_limit = 0;
571+
int last_loop = -1;
572+
int last_loop_level = -1;
573+
const zend_op *last_loop_opline = NULL;
562574
uint32_t megamorphic = 0;
563575
const zend_op_array *unrolled_calls[ZEND_JIT_TRACE_MAX_CALL_DEPTH + ZEND_JIT_TRACE_MAX_RET_DEPTH];
564576
#ifdef HAVE_GCC_GLOBAL_REGS
@@ -832,6 +844,7 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
832844

833845
unrolled_calls[ret_level] = &EX(func)->op_array;
834846
ret_level++;
847+
last_loop_opline = NULL;
835848

836849
if (prev_call) {
837850
int ret = zend_jit_trace_record_fake_init_call(prev_call, trace_buffer, idx, 0, &megamorphic, ret_level + level);
@@ -854,6 +867,9 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
854867
}
855868
} else {
856869
level--;
870+
if (level < last_loop_level) {
871+
last_loop_opline = NULL;
872+
}
857873
TRACE_RECORD(ZEND_JIT_TRACE_BACK, 0, op_array);
858874
}
859875
}
@@ -960,24 +976,44 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
960976
stop = ZEND_JIT_TRACE_STOP_BLACK_LIST;
961977
break;
962978
} else if (trace_flags & ZEND_JIT_TRACE_START_LOOP) {
963-
if (start != ZEND_JIT_TRACE_START_SIDE) {
964-
uint8_t bad_stop;
979+
uint8_t bad_stop;
965980

981+
if (start != ZEND_JIT_TRACE_START_SIDE) {
966982
if (opline == orig_opline && level + ret_level == 0) {
967983
stop = ZEND_JIT_TRACE_STOP_LOOP;
968984
break;
969985
}
970-
/* Fail to try creating a trace for inner loop first.
971-
If this doesn't work try unroling loop. */
986+
}
987+
988+
if (start != ZEND_JIT_TRACE_START_SIDE
989+
|| level + ret_level != 0) {
990+
/* First try creating a trace for inner loop.
991+
If this doesn't work try loop unroling. */
972992
bad_stop = zend_jit_trace_bad_stop_event(opline,
973993
JIT_G(blacklist_root_trace) / 2);
974994
if (bad_stop != ZEND_JIT_TRACE_STOP_INNER_LOOP
975995
&& bad_stop != ZEND_JIT_TRACE_STOP_LOOP_EXIT) {
976-
stop = ZEND_JIT_TRACE_STOP_INNER_LOOP;
977-
break;
996+
if (start == ZEND_JIT_TRACE_START_SIDE
997+
|| zend_jit_trace_bad_stop_event(orig_opline,
998+
JIT_G(blacklist_root_trace) / 2) != ZEND_JIT_TRACE_STOP_INNER_LOOP) {
999+
stop = ZEND_JIT_TRACE_STOP_INNER_LOOP;
1000+
break;
1001+
}
9781002
}
9791003
}
980-
if (loop_unroll_limit < JIT_G(max_loops_unroll)) {
1004+
1005+
if (opline == last_loop_opline
1006+
&& level == last_loop_level) {
1007+
idx = zend_jit_trace_subtrace(trace_buffer,
1008+
last_loop, idx, ZEND_JIT_TRACE_START_LOOP, op_array, opline);
1009+
start = ZEND_JIT_TRACE_START_LOOP;
1010+
stop = ZEND_JIT_TRACE_STOP_LOOP;
1011+
ret_level = 0;
1012+
break;
1013+
} else if (loop_unroll_limit < JIT_G(max_loops_unroll)) {
1014+
last_loop = idx;
1015+
last_loop_opline = opline;
1016+
last_loop_level = level;
9811017
loop_unroll_limit++;
9821018
} else {
9831019
stop = ZEND_JIT_TRACE_STOP_LOOP_UNROLL;

0 commit comments

Comments
 (0)