Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Include/internal/pycore_optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ PyAPI_FUNC(void) _Py_Executors_InvalidateCold(PyInterpreterState *interp);
#define JIT_CLEANUP_THRESHOLD 100000

// This is the length of the trace we project initially.
#define UOP_MAX_TRACE_LENGTH 800
#define UOP_MAX_TRACE_LENGTH 1200

#define TRACE_STACK_SIZE 5

Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_sys_settrace.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ class TraceTestCase(unittest.TestCase):
# Disable gc collection when tracing, otherwise the
# deallocators may be traced as well.
def setUp(self):
if os.environ.get('PYTHON_UOPS_OPTIMIZE') == '0':
self.skipTest("Line tracing behavior differs when JIT optimizer is disabled")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, why/how does the behavior differ? Sounds like a bug.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should open another issue for this.

self.using_gc = gc.isenabled()
gc.disable()
self.addCleanup(sys.settrace, sys.gettrace())
Expand Down
6 changes: 6 additions & 0 deletions Lib/test/test_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ def test_traced_func_linear(self):

self.assertEqual(self.tracer.results().counts, expected)

@unittest.skipIf(os.environ.get('PYTHON_UOPS_OPTIMIZE') == '0',
"Line counts differ when JIT optimizer is disabled")
def test_traced_func_loop(self):
self.tracer.runfunc(traced_func_loop, 2, 3)

Expand All @@ -166,6 +168,8 @@ def test_traced_func_importing(self):

self.assertEqual(self.tracer.results().counts, expected)

@unittest.skipIf(os.environ.get('PYTHON_UOPS_OPTIMIZE') == '0',
"Line counts differ when JIT optimizer is disabled")
def test_trace_func_generator(self):
self.tracer.runfunc(traced_func_calling_generator)

Expand Down Expand Up @@ -236,6 +240,8 @@ def setUp(self):
self.my_py_filename = fix_ext_py(__file__)
self.addCleanup(sys.settrace, sys.gettrace())

@unittest.skipIf(os.environ.get('PYTHON_UOPS_OPTIMIZE') == '0',
"Line counts differ when JIT optimizer is disabled")
def test_exec_counts(self):
self.tracer = Trace(count=1, trace=0, countfuncs=0, countcallers=0)
code = r'''traced_func_loop(2, 5)'''
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix JIT trace buffer overrun by increasing possible exit stubs.
Patch by Donghee Na.
13 changes: 8 additions & 5 deletions Python/optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,8 @@ translate_bytecode_to_trace(

for (;;) {
target = INSTR_IP(instr, code);
// Need space for _DEOPT
max_length--;

// One for possible _DEOPT, one because _CHECK_VALIDITY itself might _DEOPT
max_length-=2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs comment on why 2:
// One for possible _DEOPT, one because _CHECK_VALIDITY itself might _DEOPT

uint32_t opcode = instr->op.code;
uint32_t oparg = instr->op.arg;

Expand Down Expand Up @@ -1283,15 +1282,19 @@ uop_optimize(
_Py_BloomFilter_Init(&dependencies);
_PyUOpInstruction buffer[UOP_MAX_TRACE_LENGTH];
OPT_STAT_INC(attempts);
char *env_var = Py_GETENV("PYTHON_UOPS_OPTIMIZE");
bool is_noopt = true;
if (env_var == NULL || *env_var == '\0' || *env_var > '0') {
is_noopt = false;
}
Comment on lines +1285 to +1289
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this change made? I think the previous code (without the additional variable) made more sense.

int length = translate_bytecode_to_trace(frame, instr, buffer, UOP_MAX_TRACE_LENGTH, &dependencies, progress_needed);
if (length <= 0) {
// Error or nothing translated
return length;
}
assert(length < UOP_MAX_TRACE_LENGTH);
OPT_STAT_INC(traces_created);
char *env_var = Py_GETENV("PYTHON_UOPS_OPTIMIZE");
if (env_var == NULL || *env_var == '\0' || *env_var > '0') {
if (!is_noopt) {
length = _Py_uop_analyze_and_optimize(frame, buffer,
length,
curr_stackentries, &dependencies);
Expand Down
Loading