Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit eeaa02f

Browse filesBrowse files
Merge pull request #24 from JuliaPoo/types_metainterpreter
Implemented type propagation
2 parents e1a5b61 + 808c9eb commit eeaa02f
Copy full SHA for eeaa02f

File tree

Expand file treeCollapse file tree

11 files changed

+1846
-191
lines changed
Filter options
Expand file treeCollapse file tree

11 files changed

+1846
-191
lines changed

‎.gitattributes

Copy file name to clipboardExpand all lines: .gitattributes
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Parser/token.c generated
8383
Programs/test_frozenmain.h generated
8484
Python/Python-ast.c generated
8585
Python/generated_cases.c.h generated
86+
Python/tier2_typepropagator.c.h generated
8687
Python/opcode_targets.h generated
8788
Python/stdlib_module_names.h generated
8889
Tools/peg_generator/pegen/grammar_parser.py generated

‎Include/cpython/code.h

Copy file name to clipboardExpand all lines: Include/cpython/code.h
+18-6Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,24 @@ typedef struct {
5656
PyObject *_co_freevars;
5757
} _PyCoCached;
5858

59+
// Tier 2 types meta interpreter
60+
typedef struct _PyTier2TypeContext {
61+
// points into type_stack, points to one element after the stack
62+
PyTypeObject** type_stack_ptr;
63+
int type_locals_len;
64+
int type_stack_len;
65+
PyTypeObject** type_stack;
66+
PyTypeObject** type_locals;
67+
} _PyTier2TypeContext;
68+
5969
// Tier 2 interpreter information
6070
typedef struct _PyTier2BBMetadata {
6171
// Index into _PyTier2Info->bb_data
6272
int id;
63-
// Array of types. This corresponds to the fast locals array.
64-
int type_context_len;
65-
PyTypeObject **type_context;
73+
_PyTier2TypeContext *type_context;
6674
_Py_CODEUNIT *tier2_start;
6775
// Note, this is the first tier 1 instruction to execute AFTER the BB ends.
6876
_Py_CODEUNIT *tier1_end;
69-
// Type stack state
70-
PyTypeObject **types_stack;
7177
} _PyTier2BBMetadata;
7278

7379
// Bump allocator for basic blocks (overallocated)
@@ -97,13 +103,19 @@ typedef struct _PyTier2Info {
97103
// will have [[BB_ID1, BB_ID2], [BB_ID3,], [], []]
98104
// etc.
99105
int **backward_jump_target_bb_ids;
100-
PyTypeObject **types_stack;
101106
// Max len of bb_data
102107
int bb_data_len;
103108
// Current index to write into in bb_data. Incremented after each write.
104109
// This also assigns the BB ID.
105110
int bb_data_curr;
106111
_PyTier2BBMetadata **bb_data;
112+
113+
// @TODO:
114+
// Potentially optimise _PyTier2TypeContext by allocating the stacksize
115+
// to the size needed for the snapshot, and the type propagation is performed
116+
// on type_metainterpreter_stack_scratch which is allocated only once per
117+
// code object.
118+
// PyTypeObject** type_metainterpreter_stack_scratch;
107119
} _PyTier2Info;
108120

109121
// To avoid repeating ourselves in deepfreeze.py, all PyCodeObject members are

‎Include/internal/pycore_code.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_code.h
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ extern _Py_CODEUNIT *_PyCode_Tier2Warmup(struct _PyInterpreterFrame *,
259259
_Py_CODEUNIT *);
260260
extern _Py_CODEUNIT *_PyTier2_GenerateNextBB(
261261
struct _PyInterpreterFrame *frame, uint16_t bb_id, int jumpby,
262-
_Py_CODEUNIT **tier1_fallback);
262+
_Py_CODEUNIT **tier1_fallback, char gen_bb_requires_pop);
263263
extern _Py_CODEUNIT *_PyTier2_LocateJumpBackwardsBB(
264264
struct _PyInterpreterFrame *frame, uint16_t bb_id, int jumpby,
265265
_Py_CODEUNIT **tier1_fallback);

‎Objects/codeobject.c

Copy file name to clipboardExpand all lines: Objects/codeobject.c
+6-4Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,6 +1672,11 @@ code_tier2_fini(PyCodeObject *co)
16721672
if (co->_tier2_info == NULL) {
16731673
return;
16741674
}
1675+
// @TODO:
1676+
// Write a proper destructor for _PyTier2Info
1677+
// and it's children structures.
1678+
// Current implementation e.g., doesn't clear
1679+
// bb_data
16751680
_PyTier2Info *t2_info = co->_tier2_info;
16761681
t2_info->_entry_bb = NULL;
16771682
if (t2_info->_bb_space != NULL) {
@@ -1690,10 +1695,7 @@ code_tier2_fini(PyCodeObject *co)
16901695
PyMem_Free(t2_info->backward_jump_offsets);
16911696
t2_info->backward_jump_offsets = NULL;
16921697
}
1693-
if (t2_info->types_stack != NULL) {
1694-
PyMem_Free(t2_info->types_stack);
1695-
t2_info->types_stack = NULL;
1696-
}
1698+
16971699
t2_info->backward_jump_count = 0;
16981700
if (t2_info->bb_data != NULL && t2_info->bb_data_len > 0) {
16991701
PyMem_Free(t2_info->bb_data);

‎Python/bytecodes.c

Copy file name to clipboardExpand all lines: Python/bytecodes.c
+26-12Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,31 +102,31 @@ dummy_func(
102102
}
103103
}
104104

105-
inst(LOAD_CLOSURE, (-- value)) {
105+
inst(LOAD_CLOSURE, (-- value : locals[oparg])) {
106106
/* We keep LOAD_CLOSURE so that the bytecode stays more readable. */
107107
value = GETLOCAL(oparg);
108108
ERROR_IF(value == NULL, unbound_local_error);
109109
Py_INCREF(value);
110110
}
111111

112-
inst(LOAD_FAST_CHECK, (-- value)) {
112+
inst(LOAD_FAST_CHECK, (-- value : locals[oparg])) {
113113
value = GETLOCAL(oparg);
114114
ERROR_IF(value == NULL, unbound_local_error);
115115
Py_INCREF(value);
116116
}
117117

118-
inst(LOAD_FAST, (-- value)) {
118+
inst(LOAD_FAST, (-- value : locals[oparg])) {
119119
value = GETLOCAL(oparg);
120120
assert(value != NULL);
121121
Py_INCREF(value);
122122
}
123123

124-
inst(LOAD_CONST, (-- value)) {
124+
inst(LOAD_CONST, (-- value : consts[oparg])) {
125125
value = GETITEM(consts, oparg);
126126
Py_INCREF(value);
127127
}
128128

129-
inst(STORE_FAST, (value --)) {
129+
inst(STORE_FAST, (value --), locals[oparg] = *value) {
130130
SETLOCAL(oparg, value);
131131
}
132132

@@ -303,7 +303,7 @@ dummy_func(
303303
bb_test = PyLong_CheckExact(left) && (Py_TYPE(left) == Py_TYPE(right));
304304
}
305305

306-
u_inst(BINARY_OP_ADD_INT_REST, (left, right -- sum)) {
306+
u_inst(BINARY_OP_ADD_INT_REST, (left : PyLong_Type, right : PyLong_Type -- sum : PyLong_Type)) {
307307
STAT_INC(BINARY_OP, hit);
308308
sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
309309
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
@@ -1180,13 +1180,13 @@ dummy_func(
11801180
null = NULL;
11811181
}
11821182

1183-
inst(DELETE_FAST, (--)) {
1183+
inst(DELETE_FAST, (--), locals[oparg] = NULL) {
11841184
PyObject *v = GETLOCAL(oparg);
11851185
ERROR_IF(v == NULL, unbound_local_error);
11861186
SETLOCAL(oparg, NULL);
11871187
}
11881188

1189-
inst(MAKE_CELL, (--)) {
1189+
inst(MAKE_CELL, (--), locals[oparg] = NULL) {
11901190
// "initial" is probably NULL but not if it's an arg (or set
11911191
// via PyFrame_LocalsToFast() before MAKE_CELL has run).
11921192
PyObject *initial = GETLOCAL(oparg);
@@ -2084,6 +2084,10 @@ dummy_func(
20842084
goto error;
20852085
}
20862086
}
2087+
// This gets set so BRANCH_BB knows whether to pop
2088+
// the type stack (type propagation) when generating the
2089+
// target BB
2090+
gen_bb_requires_pop = !jump;
20872091
}
20882092

20892093
inst(JUMP_IF_TRUE_OR_POP, (cond -- cond if (jump))) {
@@ -2136,6 +2140,10 @@ dummy_func(
21362140
goto error;
21372141
}
21382142
}
2143+
// This gets set so BRANCH_BB knows whether to pop
2144+
// the type stack (type propagation) when generating the
2145+
// target BB
2146+
gen_bb_requires_pop = !jump;
21392147
}
21402148

21412149
inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) {
@@ -3284,6 +3292,7 @@ dummy_func(
32843292
}
32853293

32863294
// Tier 2 instructions
3295+
// Type propagator assumes this doesn't affect type context
32873296
inst(BB_BRANCH, (unused/1 --)) {
32883297
_Py_CODEUNIT *t2_nextinstr = NULL;
32893298
_PyBBBranchCache *cache = (_PyBBBranchCache *)next_instr;
@@ -3293,7 +3302,8 @@ dummy_func(
32933302
_py_set_opcode(next_instr - 1, BB_BRANCH_IF_FLAG_UNSET);
32943303
// Generate consequent.
32953304
t2_nextinstr = _PyTier2_GenerateNextBB(
3296-
frame, cache->bb_id, 0, &tier1_fallback);
3305+
frame, cache->bb_id, 0, &tier1_fallback, gen_bb_requires_pop);
3306+
gen_bb_requires_pop = false;
32973307
if (t2_nextinstr == NULL) {
32983308
// Fall back to tier 1.
32993309
next_instr = tier1_fallback;
@@ -3305,7 +3315,8 @@ dummy_func(
33053315
_py_set_opcode(next_instr - 1, BB_BRANCH_IF_FLAG_SET);
33063316
// Generate predicate.
33073317
t2_nextinstr = _PyTier2_GenerateNextBB(
3308-
frame, cache->bb_id, oparg, &tier1_fallback);
3318+
frame, cache->bb_id, oparg, &tier1_fallback, gen_bb_requires_pop);
3319+
gen_bb_requires_pop = false;
33093320
if (t2_nextinstr == NULL) {
33103321
// Fall back to tier 1.
33113322
next_instr = tier1_fallback + oparg;
@@ -3327,7 +3338,8 @@ dummy_func(
33273338
_Py_CODEUNIT *tier1_fallback = NULL;
33283339

33293340
t2_nextinstr = _PyTier2_GenerateNextBB(
3330-
frame, cache->bb_id, oparg, &tier1_fallback);
3341+
frame, cache->bb_id, oparg, &tier1_fallback, gen_bb_requires_pop);
3342+
gen_bb_requires_pop = false;
33313343
if (t2_nextinstr == NULL) {
33323344
// Fall back to tier 1.
33333345
next_instr = tier1_fallback;
@@ -3358,7 +3370,8 @@ dummy_func(
33583370
// @TODO: Rewrite TEST intruction above to a JUMP above..
33593371

33603372
t2_nextinstr = _PyTier2_GenerateNextBB(
3361-
frame, cache->bb_id, oparg, &tier1_fallback);
3373+
frame, cache->bb_id, oparg, &tier1_fallback, gen_bb_requires_pop);
3374+
gen_bb_requires_pop = false;
33623375
if (t2_nextinstr == NULL) {
33633376
// Fall back to tier 1.
33643377
next_instr = tier1_fallback;
@@ -3379,6 +3392,7 @@ dummy_func(
33793392
// Fall through to next instruction.
33803393
}
33813394

3395+
// Type propagator assumes this doesn't affect type context
33823396
inst(BB_JUMP_BACKWARD_LAZY, (--)) {
33833397
_Py_CODEUNIT *curr = next_instr - 1;
33843398
_Py_CODEUNIT *t2_nextinstr = NULL;

‎Python/ceval.c

Copy file name to clipboardExpand all lines: Python/ceval.c
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
729729
// true = successor
730730
// false = alternate
731731
bool bb_test = true;
732+
// For tier2 type propagation, handling of jump instructions with
733+
// runtime-dependent stack effect.
734+
// This flag is used to determine if the type context of a new bb
735+
// requires a stack element to be popped.
736+
bool gen_bb_requires_pop = false;
732737

733738
/* WARNING: Because the _PyCFrame lives on the C stack,
734739
* but can be accessed from a heap allocated object (tstate)

‎Python/generated_cases.c.h

Copy file name to clipboardExpand all lines: Python/generated_cases.c.h
+16-4Lines changed: 16 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.