Skip to content

Commit 4a0db15

Browse files
committed
optimize code struct
1 parent e771fd0 commit 4a0db15

File tree

6 files changed

+47
-32
lines changed

6 files changed

+47
-32
lines changed

Include/internal/pycore_optimizer_types.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,7 @@ typedef struct _JitOptContext {
129129
JitOptRef *limit;
130130
JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
131131

132-
// buffer to save optimized result
133-
int out_len;
134-
_PyUOpInstruction out_buffer[UOP_MAX_TRACE_LENGTH];
132+
struct _PyJitTracerState *tracer;
135133
} JitOptContext;
136134

137135

Include/internal/pycore_tstate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ typedef struct _PyJitTracerState {
5959
_PyJitTracerTranslatorState translator_state;
6060
JitOptContext opt_context;
6161
_PyUOpInstruction code_buffer[UOP_MAX_TRACE_LENGTH];
62+
_PyUOpInstruction out_buffer[UOP_MAX_TRACE_LENGTH];
63+
int out_len;
6264
} _PyJitTracerState;
6365

6466
#endif

Python/optimizer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1509,7 +1509,7 @@ uop_optimize(
15091509
if (length <= 0) {
15101510
return length;
15111511
}
1512-
buffer = _tstate->jit_tracer_state->opt_context.out_buffer;
1512+
buffer = _tstate->jit_tracer_state->out_buffer;
15131513
}
15141514
assert(length < UOP_MAX_TRACE_LENGTH/2);
15151515
assert(length >= 1);

Python/optimizer_analysis.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,18 @@ incorrect_keys(PyObject *obj, uint32_t version)
143143
#define STACK_LEVEL() ((int)(stack_pointer - ctx->frame->stack))
144144
#define STACK_SIZE() ((int)(ctx->frame->stack_len))
145145

146+
static inline int
147+
is_terminator_uop(const _PyUOpInstruction *uop)
148+
{
149+
int opcode = uop->opcode;
150+
return (
151+
opcode == _EXIT_TRACE ||
152+
opcode == _JUMP_TO_TOP ||
153+
opcode == _DYNAMIC_EXIT ||
154+
opcode == _DEOPT
155+
);
156+
}
157+
146158
#define CURRENT_FRAME_IS_INIT_SHIM() (ctx->frame->code == ((PyCodeObject *)&_Py_InitCleanup))
147159

148160
#define GETLOCAL(idx) ((ctx->frame->locals[idx]))
@@ -152,15 +164,21 @@ incorrect_keys(PyObject *obj, uint32_t version)
152164
(INST)->oparg = ARG; \
153165
(INST)->operand0 = OPERAND;
154166

155-
#define ADD_OP(OP, ARG, OPERAND) ( \
156-
ctx->out_buffer[ctx->out_len].opcode = (OP), \
157-
ctx->out_buffer[ctx->out_len].format = this_instr->format, \
158-
ctx->out_buffer[ctx->out_len].oparg = (ARG), \
159-
ctx->out_buffer[ctx->out_len].target = this_instr->target, \
160-
ctx->out_buffer[ctx->out_len].operand0 = (OPERAND), \
161-
ctx->out_buffer[ctx->out_len].operand1 = this_instr->operand1, \
162-
ctx->out_len++ \
163-
)
167+
#define ADD_OP(OP, ARG, OPERAND) add_op(ctx, this_instr, (OP), (ARG), (OPERAND))
168+
169+
static inline void
170+
add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr,
171+
uint16_t opcode, uint16_t oparg, uintptr_t operand0)
172+
{
173+
_PyUOpInstruction *out = &ctx->tracer->out_buffer[ctx->tracer->out_len];
174+
out->opcode = (opcode);
175+
out->format = this_instr->format;
176+
out->oparg = (oparg);
177+
out->target = this_instr->target;
178+
out->operand0 = (operand0);
179+
out->operand1 = this_instr->operand1;
180+
ctx->tracer->out_len++;
181+
}
164182

165183
/* Shortened forms for convenience, used in optimizer_bytecodes.c */
166184
#define sym_is_not_null _Py_uop_sym_is_not_null
@@ -359,6 +377,8 @@ optimize_uops(
359377
JitOptContext *ctx = &tstate->jit_tracer_state->opt_context;
360378
uint32_t opcode = UINT16_MAX;
361379

380+
ctx->tracer = tstate->jit_tracer_state;
381+
362382
// Make sure that watchers are set up
363383
PyInterpreterState *interp = _PyInterpreterState_GET();
364384
if (interp->dict_state.watchers[GLOBALS_WATCHER_ID] == NULL) {
@@ -374,7 +394,7 @@ optimize_uops(
374394
frame->func = func;
375395
ctx->curr_frame_depth++;
376396
ctx->frame = frame;
377-
ctx->out_len = 0;
397+
ctx->tracer->out_len = 0;
378398

379399
_PyUOpInstruction *this_instr = NULL;
380400
JitOptRef *stack_pointer = ctx->frame->stack_pointer;
@@ -398,7 +418,7 @@ optimize_uops(
398418
}
399419
#endif
400420

401-
int out_len_before = ctx->out_len;
421+
int out_len_before = ctx->tracer->out_len;
402422
switch (opcode) {
403423

404424
#include "optimizer_cases.c.h"
@@ -408,8 +428,8 @@ optimize_uops(
408428
Py_UNREACHABLE();
409429
}
410430
// If no ADD_OP was called during this iteration, copy the original instruction
411-
if (ctx->out_len == out_len_before) {
412-
ctx->out_buffer[ctx->out_len++] = *this_instr;
431+
if (ctx->tracer->out_len == out_len_before) {
432+
ctx->tracer->out_buffer[ctx->tracer->out_len++] = *this_instr;
413433
}
414434
assert(ctx->frame != NULL);
415435
if (!CURRENT_FRAME_IS_INIT_SHIM()) {
@@ -440,17 +460,13 @@ optimize_uops(
440460
* would be no benefit in retrying later */
441461
_Py_uop_abstractcontext_fini(ctx);
442462
// Check that the trace ends with a proper terminator
443-
if (ctx->out_len > 0) {
444-
int last_opcode = ctx->out_buffer[ctx->out_len - 1].opcode;
445-
if (last_opcode != _EXIT_TRACE &&
446-
last_opcode != _JUMP_TO_TOP &&
447-
last_opcode != _DYNAMIC_EXIT &&
448-
last_opcode != _DEOPT) {
463+
if (ctx->tracer->out_len > 0) {
464+
if (!is_terminator_uop(&ctx->tracer->out_buffer[ctx->tracer->out_len - 1])) {
449465
return 0;
450466
}
451467
}
452468

453-
return ctx->out_len;
469+
return ctx->tracer->out_len;
454470

455471
error:
456472
DPRINTF(3, "\n");
@@ -611,7 +627,6 @@ _Py_uop_analyze_and_optimize(
611627
)
612628
{
613629
OPT_STAT_INC(optimizer_attempts);
614-
JitOptContext *ctx = &tstate->jit_tracer_state->opt_context;
615630

616631
length = optimize_uops(
617632
tstate, buffer,
@@ -623,7 +638,7 @@ _Py_uop_analyze_and_optimize(
623638

624639
assert(length > 0);
625640

626-
length = remove_unneeded_uops(ctx->out_buffer, length);
641+
length = remove_unneeded_uops(tstate->jit_tracer_state->out_buffer, length);
627642
assert(length > 0);
628643

629644
OPT_STAT_INC(optimizer_successes);

Python/optimizer_bytecodes.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ dummy_func(void) {
759759
if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyFunction_Type)) {
760760
assert(PyFunction_Check(sym_get_const(ctx, callable)));
761761
ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version);
762-
ctx->out_buffer[ctx->out_len - 1].operand1 = (uintptr_t)sym_get_const(ctx, callable);
762+
ctx->tracer->out_buffer[ctx->tracer->out_len - 1].operand1 = (uintptr_t)sym_get_const(ctx, callable);
763763
}
764764
sym_set_type(callable, &PyFunction_Type);
765765
}
@@ -769,7 +769,7 @@ dummy_func(void) {
769769
PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable);
770770
assert(PyMethod_Check(method));
771771
ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version);
772-
ctx->out_buffer[ctx->out_len - 1].operand1 = (uintptr_t)method->im_func;
772+
ctx->tracer->out_buffer[ctx->tracer->out_len - 1].operand1 = (uintptr_t)method->im_func;
773773
}
774774
sym_set_type(callable, &PyMethod_Type);
775775
}
@@ -1509,7 +1509,7 @@ dummy_func(void) {
15091509
ctx->frame->globals_watched = true;
15101510
}
15111511
if (ctx->frame->globals_checked_version != version && this_instr[-1].opcode == _NOP) {
1512-
REPLACE_OP(&ctx->out_buffer[ctx->out_len - 1], _GUARD_GLOBALS_VERSION, 0, version);
1512+
REPLACE_OP(&ctx->tracer->out_buffer[ctx->tracer->out_len - 1], _GUARD_GLOBALS_VERSION, 0, version);
15131513
ctx->frame->globals_checked_version = version;
15141514
}
15151515
if (ctx->frame->globals_checked_version == version) {

Python/optimizer_cases.c.h

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

0 commit comments

Comments
 (0)