Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
3 changes: 3 additions & 0 deletions Include/internal/pycore_optimizer_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ extern "C" {

#include "pycore_uop.h" // UOP_MAX_TRACE_LENGTH

typedef struct _PyJitTracerState _PyJitTracerState;

// Holds locals, stack, locals, stack ... (in that order)
#define MAX_ABSTRACT_INTERP_SIZE 512

Expand Down Expand Up @@ -128,6 +130,7 @@ typedef struct _JitOptContext {
JitOptRef *n_consumed;
JitOptRef *limit;
JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
_PyJitTracerState *tracer;
Comment thread
cocolato marked this conversation as resolved.
Outdated
} JitOptContext;


Expand Down
2 changes: 2 additions & 0 deletions Include/internal/pycore_tstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ typedef struct _PyJitTracerState {
_PyJitTracerTranslatorState translator_state;
JitOptContext opt_context;
_PyUOpInstruction code_buffer[UOP_MAX_TRACE_LENGTH];
_PyUOpInstruction out_buffer[UOP_MAX_TRACE_LENGTH];
int out_len;
Comment thread
cocolato marked this conversation as resolved.
Outdated
} _PyJitTracerState;

#endif
Expand Down
1 change: 1 addition & 0 deletions Python/optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1509,6 +1509,7 @@ uop_optimize(
if (length <= 0) {
return length;
}
buffer = _tstate->jit_tracer_state->out_buffer;
}
assert(length < UOP_MAX_TRACE_LENGTH/2);
assert(length >= 1);
Expand Down
63 changes: 56 additions & 7 deletions Python/optimizer_analysis.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ incorrect_keys(PyObject *obj, uint32_t version)
#define STACK_LEVEL() ((int)(stack_pointer - ctx->frame->stack))
#define STACK_SIZE() ((int)(ctx->frame->stack_len))

static inline int
is_terminator_uop(const _PyUOpInstruction *uop)
{
int opcode = uop->opcode;
return (
opcode == _EXIT_TRACE ||
opcode == _JUMP_TO_TOP ||
opcode == _DYNAMIC_EXIT ||
opcode == _DEOPT
);
}

#define CURRENT_FRAME_IS_INIT_SHIM() (ctx->frame->code == ((PyCodeObject *)&_Py_InitCleanup))

#define GETLOCAL(idx) ((ctx->frame->locals[idx]))
Expand All @@ -152,6 +164,22 @@ incorrect_keys(PyObject *obj, uint32_t version)
(INST)->oparg = ARG; \
(INST)->operand0 = OPERAND;

#define ADD_OP(OP, ARG, OPERAND) add_op(ctx, this_instr, (OP), (ARG), (OPERAND))

static inline void
add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr,
uint16_t opcode, uint16_t oparg, uintptr_t operand0)
{
_PyUOpInstruction *out = &ctx->tracer->out_buffer[ctx->tracer->out_len];
out->opcode = (opcode);
out->format = this_instr->format;
out->oparg = (oparg);
out->target = this_instr->target;
out->operand0 = (operand0);
out->operand1 = this_instr->operand1;
ctx->tracer->out_len++;
}

/* Shortened forms for convenience, used in optimizer_bytecodes.c */
#define sym_is_not_null _Py_uop_sym_is_not_null
#define sym_is_const _Py_uop_sym_is_const
Expand Down Expand Up @@ -219,7 +247,7 @@ optimize_to_bool(
bool insert_mode)
{
if (sym_matches_type(value, &PyBool_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
Comment thread
cocolato marked this conversation as resolved.
ADD_OP(_NOP, 0, 0);
*result_ptr = value;
return 1;
}
Expand All @@ -229,17 +257,17 @@ optimize_to_bool(
int opcode = insert_mode ?
_INSERT_1_LOAD_CONST_INLINE_BORROW :
_POP_TOP_LOAD_CONST_INLINE_BORROW;
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)load);
ADD_OP(opcode, 0, (uintptr_t)load);
*result_ptr = sym_new_const(ctx, load);
return 1;
}
return 0;
}

static void
eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit)
eliminate_pop_guard(_PyUOpInstruction *this_instr, JitOptContext *ctx, bool exit)
{
REPLACE_OP(this_instr, _POP_TOP, 0, 0);
ADD_OP(_POP_TOP, 0, 0);
if (exit) {
REPLACE_OP((this_instr+1), _EXIT_TRACE, 0, 0);
this_instr[1].target = this_instr->target;
Expand All @@ -256,7 +284,7 @@ lookup_attr(JitOptContext *ctx, _PyBloomFilter *dependencies, _PyUOpInstruction
PyObject *lookup = _PyType_Lookup(type, name);
if (lookup) {
int opcode = _Py_IsImmortal(lookup) ? immortal : mortal;
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)lookup);
ADD_OP(opcode, 0, (uintptr_t)lookup);
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
_Py_BloomFilter_Add(dependencies, type);
return sym_new_const(ctx, lookup);
Expand Down Expand Up @@ -349,6 +377,8 @@ optimize_uops(
JitOptContext *ctx = &tstate->jit_tracer_state->opt_context;
uint32_t opcode = UINT16_MAX;

ctx->tracer = tstate->jit_tracer_state;

// Make sure that watchers are set up
PyInterpreterState *interp = _PyInterpreterState_GET();
if (interp->dict_state.watchers[GLOBALS_WATCHER_ID] == NULL) {
Expand All @@ -364,6 +394,7 @@ optimize_uops(
frame->func = func;
ctx->curr_frame_depth++;
ctx->frame = frame;
ctx->tracer->out_len = 0;

_PyUOpInstruction *this_instr = NULL;
JitOptRef *stack_pointer = ctx->frame->stack_pointer;
Expand Down Expand Up @@ -395,6 +426,10 @@ optimize_uops(
DPRINTF(1, "\nUnknown opcode in abstract interpreter\n");
Py_UNREACHABLE();
}
// If no ADD_OP was called during this iteration, copy the original instruction
if (ctx->tracer->out_len == i) {
ctx->tracer->out_buffer[ctx->tracer->out_len++] = *this_instr;
}
assert(ctx->frame != NULL);
if (!CURRENT_FRAME_IS_INIT_SHIM()) {
DPRINTF(3, " stack_level %d\n", STACK_LEVEL());
Expand Down Expand Up @@ -423,7 +458,21 @@ optimize_uops(
/* Either reached the end or cannot optimize further, but there
* would be no benefit in retrying later */
_Py_uop_abstractcontext_fini(ctx);
return trace_len;
// Check that the trace ends with a proper terminator
if (ctx->tracer->out_len > 0) {
_PyUOpInstruction *last_uop = &ctx->tracer->out_buffer[ctx->tracer->out_len - 1];
if (!is_terminator_uop(last_uop)) {
// Copy remaining uops from original trace until we find a terminator
for (int i = ctx->tracer->out_len; i < trace_len; i++) {
ctx->tracer->out_buffer[ctx->tracer->out_len++] = trace[i];
if (is_terminator_uop(&trace[i])) {
break;
}
}
}
}

return ctx->tracer->out_len;

error:
DPRINTF(3, "\n");
Expand Down Expand Up @@ -595,7 +644,7 @@ _Py_uop_analyze_and_optimize(

assert(length > 0);

length = remove_unneeded_uops(buffer, length);
length = remove_unneeded_uops(tstate->jit_tracer_state->out_buffer, length);
assert(length > 0);

OPT_STAT_INC(optimizer_successes);
Expand Down
Loading