Skip to content

Commit 62423c9

Browse files
authored
pythonGH-141794: Limit size of generated machine code. (pythonGH-142228)
* Factor out bodies of the largest uops, to reduce jit code size. * Factor out common assert, also reducing jit code size. * Limit size of jitted code for a single executor to 1MB.
1 parent aea5531 commit 62423c9

File tree

14 files changed

+1410
-1735
lines changed

14 files changed

+1410
-1735
lines changed

Include/internal/pycore_ceval.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,64 @@ _PyForIter_VirtualIteratorNext(PyThreadState* tstate, struct _PyInterpreterFrame
408408

409409
PyAPI_DATA(const _Py_CODEUNIT *) _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR;
410410

411+
/* Helper functions for large uops */
412+
413+
PyAPI_FUNC(PyObject *)
414+
_Py_VectorCall_StackRefSteal(
415+
_PyStackRef callable,
416+
_PyStackRef *arguments,
417+
int total_args,
418+
_PyStackRef kwnames);
419+
420+
PyAPI_FUNC(PyObject *)
421+
_Py_BuiltinCallFast_StackRefSteal(
422+
_PyStackRef callable,
423+
_PyStackRef *arguments,
424+
int total_args);
425+
426+
PyAPI_FUNC(PyObject *)
427+
_Py_BuiltinCallFastWithKeywords_StackRefSteal(
428+
_PyStackRef callable,
429+
_PyStackRef *arguments,
430+
int total_args);
431+
432+
PyAPI_FUNC(PyObject *)
433+
_PyCallMethodDescriptorFast_StackRefSteal(
434+
_PyStackRef callable,
435+
PyMethodDef *meth,
436+
PyObject *self,
437+
_PyStackRef *arguments,
438+
int total_args);
439+
440+
PyAPI_FUNC(PyObject *)
441+
_PyCallMethodDescriptorFastWithKeywords_StackRefSteal(
442+
_PyStackRef callable,
443+
PyMethodDef *meth,
444+
PyObject *self,
445+
_PyStackRef *arguments,
446+
int total_args);
447+
448+
PyAPI_FUNC(PyObject *)
449+
_Py_CallBuiltinClass_StackRefSteal(
450+
_PyStackRef callable,
451+
_PyStackRef *arguments,
452+
int total_args);
453+
454+
PyAPI_FUNC(PyObject *)
455+
_Py_BuildString_StackRefSteal(
456+
_PyStackRef *arguments,
457+
int total_args);
458+
459+
PyAPI_FUNC(PyObject *)
460+
_Py_BuildMap_StackRefSteal(
461+
_PyStackRef *arguments,
462+
int half_args);
463+
464+
PyAPI_FUNC(void)
465+
_Py_assert_within_stack_bounds(
466+
_PyInterpreterFrame *frame, _PyStackRef *stack_pointer,
467+
const char *filename, int lineno);
468+
411469
#ifdef __cplusplus
412470
}
413471
#endif

Include/internal/pycore_jit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ extern "C" {
1313
# error "this header requires Py_BUILD_CORE define"
1414
#endif
1515

16+
/* To be able to reason about code layout and branches, keep code size below 1 MB */
17+
#define PY_MAX_JIT_CODE_SIZE ((1 << 20)-1)
18+
1619
#ifdef _Py_JIT
1720

1821
typedef _Py_CODEUNIT *(*jit_func)(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate);

Include/internal/pycore_uop.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ typedef struct _PyUOpInstruction{
3636
} _PyUOpInstruction;
3737

3838
// This is the length of the trace we translate initially.
39+
#ifdef Py_DEBUG
40+
// With asserts, the stencils are a lot larger
41+
#define UOP_MAX_TRACE_LENGTH 1000
42+
#else
3943
#define UOP_MAX_TRACE_LENGTH 3000
44+
#endif
4045
#define UOP_BUFFER_SIZE (UOP_MAX_TRACE_LENGTH * sizeof(_PyUOpInstruction))
4146

4247
/* Bloom filter with m = 256

Lib/test/test_generated_cases.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def test_inst_one_pop(self):
165165
value = stack_pointer[-1];
166166
SPAM(value);
167167
stack_pointer += -1;
168-
assert(WITHIN_STACK_BOUNDS());
168+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
169169
DISPATCH();
170170
}
171171
"""
@@ -190,7 +190,7 @@ def test_inst_one_push(self):
190190
res = SPAM();
191191
stack_pointer[0] = res;
192192
stack_pointer += 1;
193-
assert(WITHIN_STACK_BOUNDS());
193+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
194194
DISPATCH();
195195
}
196196
"""
@@ -247,7 +247,7 @@ def test_binary_op(self):
247247
res = SPAM(left, right);
248248
stack_pointer[-2] = res;
249249
stack_pointer += -1;
250-
assert(WITHIN_STACK_BOUNDS());
250+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
251251
DISPATCH();
252252
}
253253
"""
@@ -366,14 +366,14 @@ def test_sync_sp(self):
366366
_PyStackRef res;
367367
arg = stack_pointer[-1];
368368
stack_pointer += -1;
369-
assert(WITHIN_STACK_BOUNDS());
369+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
370370
_PyFrame_SetStackPointer(frame, stack_pointer);
371371
escaping_call();
372372
stack_pointer = _PyFrame_GetStackPointer(frame);
373373
res = Py_None;
374374
stack_pointer[0] = res;
375375
stack_pointer += 1;
376-
assert(WITHIN_STACK_BOUNDS());
376+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
377377
DISPATCH();
378378
}
379379
@@ -489,7 +489,7 @@ def test_error_if_pop(self):
489489
res = 0;
490490
stack_pointer[-2] = res;
491491
stack_pointer += -1;
492-
assert(WITHIN_STACK_BOUNDS());
492+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
493493
DISPATCH();
494494
}
495495
"""
@@ -523,7 +523,7 @@ def test_error_if_pop_with_result(self):
523523
}
524524
stack_pointer[-2] = res;
525525
stack_pointer += -1;
526-
assert(WITHIN_STACK_BOUNDS());
526+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
527527
DISPATCH();
528528
}
529529
"""
@@ -553,7 +553,7 @@ def test_cache_effect(self):
553553
uint32_t extra = read_u32(&this_instr[2].cache);
554554
(void)extra;
555555
stack_pointer += -1;
556-
assert(WITHIN_STACK_BOUNDS());
556+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
557557
DISPATCH();
558558
}
559559
"""
@@ -640,7 +640,7 @@ def test_macro_instruction(self):
640640
}
641641
stack_pointer[-3] = res;
642642
stack_pointer += -2;
643-
assert(WITHIN_STACK_BOUNDS());
643+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
644644
DISPATCH();
645645
}
646646
@@ -688,7 +688,7 @@ def test_macro_instruction(self):
688688
stack_pointer = _PyFrame_GetStackPointer(frame);
689689
stack_pointer[-3] = res;
690690
stack_pointer += -2;
691-
assert(WITHIN_STACK_BOUNDS());
691+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
692692
DISPATCH();
693693
}
694694
"""
@@ -827,7 +827,7 @@ def test_array_input(self):
827827
below = stack_pointer[-2 - oparg*2];
828828
SPAM(values, oparg);
829829
stack_pointer += -2 - oparg*2;
830-
assert(WITHIN_STACK_BOUNDS());
830+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
831831
DISPATCH();
832832
}
833833
"""
@@ -860,7 +860,7 @@ def test_array_output(self):
860860
stack_pointer[-2] = below;
861861
stack_pointer[-1 + oparg*3] = above;
862862
stack_pointer += oparg*3;
863-
assert(WITHIN_STACK_BOUNDS());
863+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
864864
DISPATCH();
865865
}
866866
"""
@@ -889,7 +889,7 @@ def test_array_input_output(self):
889889
above = 0;
890890
stack_pointer[0] = above;
891891
stack_pointer += 1;
892-
assert(WITHIN_STACK_BOUNDS());
892+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
893893
DISPATCH();
894894
}
895895
"""
@@ -918,11 +918,11 @@ def test_array_error_if(self):
918918
extra = stack_pointer[-1 - oparg];
919919
if (oparg == 0) {
920920
stack_pointer += -1 - oparg;
921-
assert(WITHIN_STACK_BOUNDS());
921+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
922922
JUMP_TO_LABEL(error);
923923
}
924924
stack_pointer += -1 - oparg;
925-
assert(WITHIN_STACK_BOUNDS());
925+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
926926
DISPATCH();
927927
}
928928
"""
@@ -960,7 +960,7 @@ def test_macro_push_push(self):
960960
stack_pointer[0] = val1;
961961
stack_pointer[1] = val2;
962962
stack_pointer += 2;
963-
assert(WITHIN_STACK_BOUNDS());
963+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
964964
DISPATCH();
965965
}
966966
"""
@@ -1263,13 +1263,13 @@ def test_flush(self):
12631263
stack_pointer[0] = a;
12641264
stack_pointer[1] = b;
12651265
stack_pointer += 2;
1266-
assert(WITHIN_STACK_BOUNDS());
1266+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
12671267
// SECOND
12681268
{
12691269
USE(a, b);
12701270
}
12711271
stack_pointer += -2;
1272-
assert(WITHIN_STACK_BOUNDS());
1272+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
12731273
DISPATCH();
12741274
}
12751275
"""
@@ -1325,7 +1325,7 @@ def test_pop_on_error_peeks(self):
13251325
}
13261326
}
13271327
stack_pointer += -2;
1328-
assert(WITHIN_STACK_BOUNDS());
1328+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
13291329
DISPATCH();
13301330
}
13311331
"""
@@ -1368,14 +1368,14 @@ def test_push_then_error(self):
13681368
stack_pointer[0] = a;
13691369
stack_pointer[1] = b;
13701370
stack_pointer += 2;
1371-
assert(WITHIN_STACK_BOUNDS());
1371+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
13721372
JUMP_TO_LABEL(error);
13731373
}
13741374
}
13751375
stack_pointer[0] = a;
13761376
stack_pointer[1] = b;
13771377
stack_pointer += 2;
1378-
assert(WITHIN_STACK_BOUNDS());
1378+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
13791379
DISPATCH();
13801380
}
13811381
"""
@@ -1661,7 +1661,7 @@ def test_pystackref_frompyobject_new_next_to_cmacro(self):
16611661
stack_pointer[0] = out1;
16621662
stack_pointer[1] = out2;
16631663
stack_pointer += 2;
1664-
assert(WITHIN_STACK_BOUNDS());
1664+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
16651665
DISPATCH();
16661666
}
16671667
"""
@@ -1881,7 +1881,7 @@ def test_reassigning_dead_inputs(self):
18811881
stack_pointer = _PyFrame_GetStackPointer(frame);
18821882
in = temp;
18831883
stack_pointer += -1;
1884-
assert(WITHIN_STACK_BOUNDS());
1884+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
18851885
_PyFrame_SetStackPointer(frame, stack_pointer);
18861886
PyStackRef_CLOSE(in);
18871887
stack_pointer = _PyFrame_GetStackPointer(frame);
@@ -2116,7 +2116,7 @@ def test_validate_uop_unused_input(self):
21162116
output = """
21172117
case OP: {
21182118
stack_pointer += -1;
2119-
assert(WITHIN_STACK_BOUNDS());
2119+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
21202120
break;
21212121
}
21222122
"""
@@ -2133,7 +2133,7 @@ def test_validate_uop_unused_input(self):
21332133
output = """
21342134
case OP: {
21352135
stack_pointer += -1;
2136-
assert(WITHIN_STACK_BOUNDS());
2136+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
21372137
break;
21382138
}
21392139
"""
@@ -2155,7 +2155,7 @@ def test_validate_uop_unused_output(self):
21552155
foo = NULL;
21562156
stack_pointer[0] = foo;
21572157
stack_pointer += 1;
2158-
assert(WITHIN_STACK_BOUNDS());
2158+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
21592159
break;
21602160
}
21612161
"""
@@ -2173,7 +2173,7 @@ def test_validate_uop_unused_output(self):
21732173
output = """
21742174
case OP: {
21752175
stack_pointer += 1;
2176-
assert(WITHIN_STACK_BOUNDS());
2176+
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
21772177
break;
21782178
}
21792179
"""

0 commit comments

Comments
 (0)