Skip to content

Commit 6a828d7

Browse files
committed
support track escape
1 parent 5b4bd5f commit 6a828d7

6 files changed

Lines changed: 41 additions & 30 deletions

File tree

Include/internal/pycore_optimizer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ typedef struct _JitOptContext {
4444
JitOptRef *limit;
4545
JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
4646
_PyJitUopBuffer out_buffer;
47+
// Index of the last escaped uop in out_buffer.
48+
int last_escape_index;
4749
} JitOptContext;
4850

4951

Include/internal/pycore_optimizer_types.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,14 @@ typedef struct {
9797
typedef struct {
9898
uint16_t slot_index;
9999
uint16_t symbol;
100-
} JitOptSlotMapping;
100+
} JitOptDescrMapping;
101101

102102
typedef struct _jit_opt_slots {
103103
uint8_t tag;
104104
uint8_t num_slots;
105+
uint16_t last_modified_index; // Index in out_buffer when this object was last modified
105106
uint32_t type_version;
106-
JitOptSlotMapping *slots;
107+
JitOptDescrMapping *slots;
107108
} JitOptSlotsObject;
108109

109110
typedef union _jit_opt_symbol {
@@ -147,7 +148,7 @@ typedef struct ty_arena {
147148
typedef struct slots_arena {
148149
int slots_curr_number;
149150
int slots_max_number;
150-
JitOptSlotMapping arena[SLOTS_ARENA_SIZE];
151+
JitOptDescrMapping arena[SLOTS_ARENA_SIZE];
151152
} slots_arena;
152153

153154
#ifdef __cplusplus

Python/optimizer_analysis.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,10 @@ optimize_uops(
509509
if (ctx->out_buffer.next == out_ptr) {
510510
*(ctx->out_buffer.next++) = *this_instr;
511511
}
512+
// Track escapes
513+
if (_PyUop_Flags[opcode] & HAS_ESCAPES_FLAG) {
514+
ctx->last_escape_index = uop_buffer_length(&ctx->out_buffer);
515+
}
512516
assert(ctx->frame != NULL);
513517
if (!CURRENT_FRAME_IS_INIT_SHIM()) {
514518
DPRINTF(3, " stack_level %d\n", STACK_LEVEL());

Python/optimizer_bytecodes.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -896,10 +896,14 @@ dummy_func(void) {
896896
}
897897

898898
op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
899-
(void)type_version;
900899
(void)args;
901900
callable = sym_new_not_null(ctx);
902-
self_or_null = sym_new_not_null(ctx);
901+
PyTypeObject *tp = _PyType_LookupByVersion(type_version);
902+
if (tp->tp_basicsize > sizeof(PyObject) && !(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
903+
self_or_null = sym_new_slots_object(ctx, type_version);
904+
} else {
905+
self_or_null = sym_new_not_null(ctx);
906+
}
903907
}
904908

905909
op(_CREATE_INIT_FRAME, (init, self, args[oparg] -- init_frame)) {

Python/optimizer_cases.c.h

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer_symbols.c

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,7 @@ _Py_uop_sym_new_slots_object(JitOptContext *ctx, unsigned int type_version)
974974
res->slots.num_slots = 0;
975975
res->slots.slots = NULL;
976976
res->slots.type_version = type_version;
977+
res->slots.last_modified_index = uop_buffer_length(&ctx->out_buffer);
977978
return PyJitRef_Wrap(res);
978979
}
979980

@@ -982,7 +983,13 @@ _Py_uop_sym_slots_getattr(JitOptContext *ctx, JitOptRef ref, uint16_t slot_index
982983
{
983984
JitOptSymbol *sym = PyJitRef_Unwrap(ref);
984985

985-
if (sym->tag == JIT_SYM_SLOTS_TAG && sym->slots.slots != NULL) {
986+
// Only return tracked slot values if:
987+
// 1. Symbol is a slots object with mappings allocated
988+
// 2. No escape has occurred since last modification (state is fresh)
989+
if (sym->tag == JIT_SYM_SLOTS_TAG &&
990+
sym->slots.slots != NULL &&
991+
sym->slots.last_modified_index >= ctx->last_escape_index)
992+
{
986993
for (int i = 0; i < sym->slots.num_slots; i++) {
987994
if (sym->slots.slots[i].slot_index == slot_index) {
988995
return PyJitRef_Wrap(allocation_base(ctx) + sym->slots.slots[i].symbol);
@@ -993,13 +1000,13 @@ _Py_uop_sym_slots_getattr(JitOptContext *ctx, JitOptRef ref, uint16_t slot_index
9931000
return _Py_uop_sym_new_not_null(ctx);
9941001
}
9951002

996-
static JitOptSlotMapping *
1003+
static JitOptDescrMapping *
9971004
slots_arena_alloc(JitOptContext *ctx)
9981005
{
9991006
if (ctx->s_arena.slots_curr_number + MAX_SYMBOLIC_SLOTS_SIZE > ctx->s_arena.slots_max_number) {
10001007
return NULL;
10011008
}
1002-
JitOptSlotMapping *slots = &ctx->s_arena.arena[ctx->s_arena.slots_curr_number];
1009+
JitOptDescrMapping *slots = &ctx->s_arena.arena[ctx->s_arena.slots_curr_number];
10031010
ctx->s_arena.slots_curr_number += MAX_SYMBOLIC_SLOTS_SIZE;
10041011
return slots;
10051012
}
@@ -1008,30 +1015,18 @@ void
10081015
_Py_uop_sym_slots_setattr(JitOptContext *ctx, JitOptRef ref, uint16_t slot_index, JitOptRef value)
10091016
{
10101017
JitOptSymbol *sym = PyJitRef_Unwrap(ref);
1018+
int curr_index = uop_buffer_length(&ctx->out_buffer);
10111019

1012-
if (sym->tag == JIT_SYM_TYPE_VERSION_TAG) {
1013-
uint32_t version = sym->version.version;
1014-
sym->tag = JIT_SYM_SLOTS_TAG;
1015-
sym->slots.type_version = version;
1016-
sym->slots.num_slots = 0;
1017-
sym->slots.slots = slots_arena_alloc(ctx);
1018-
if (sym->slots.slots == NULL) {
1019-
return;
1020-
}
1020+
if (sym->tag != JIT_SYM_SLOTS_TAG) {
1021+
return;
10211022
}
1022-
else if (sym->tag == JIT_SYM_KNOWN_CLASS_TAG) {
1023-
uint32_t version = sym->cls.version;
1024-
sym->tag = JIT_SYM_SLOTS_TAG;
1025-
sym->slots.type_version = version;
1023+
1024+
// Check escape
1025+
if (sym->slots.last_modified_index < ctx->last_escape_index) {
10261026
sym->slots.num_slots = 0;
1027-
sym->slots.slots = slots_arena_alloc(ctx);
1028-
if (sym->slots.slots == NULL) {
1029-
return;
1030-
}
1031-
}
1032-
else if (sym->tag != JIT_SYM_SLOTS_TAG) {
1033-
return;
10341027
}
1028+
// Update the last modified timestamp
1029+
sym->slots.last_modified_index = curr_index;
10351030
// Check if have arena space allocated
10361031
if (sym->slots.slots == NULL) {
10371032
sym->slots.slots = slots_arena_alloc(ctx);
@@ -1157,6 +1152,7 @@ _Py_uop_abstractcontext_init(JitOptContext *ctx)
11571152
ctx->out_of_space = false;
11581153
ctx->contradiction = false;
11591154
ctx->builtins_watched = false;
1155+
ctx->last_escape_index = 0;
11601156
}
11611157

11621158
int

0 commit comments

Comments
 (0)