mirror of https://github.com/python/cpython
gh-99955: use SUCCESS/ERROR return values in optimizer and assembler. Use RETURN_IF_ERROR where appropriate. Fix a couple of bugs. (#101412)
This commit is contained in:
parent
e867c1b753
commit
af7b2db384
331
Python/compile.c
331
Python/compile.c
|
@ -176,13 +176,11 @@ static struct jump_target_label_ NO_LABEL = {-1};
|
|||
#define NEW_JUMP_TARGET_LABEL(C, NAME) \
|
||||
jump_target_label NAME = cfg_new_label(CFG_BUILDER(C)); \
|
||||
if (!IS_LABEL(NAME)) { \
|
||||
return 0; \
|
||||
return ERROR; \
|
||||
}
|
||||
|
||||
#define USE_LABEL(C, LBL) \
|
||||
if (cfg_builder_use_label(CFG_BUILDER(C), LBL) < 0) { \
|
||||
return 0; \
|
||||
}
|
||||
RETURN_IF_ERROR(cfg_builder_use_label(CFG_BUILDER(C), LBL))
|
||||
|
||||
struct instr {
|
||||
int i_opcode;
|
||||
|
@ -619,8 +617,9 @@ _Py_Mangle(PyObject *privateobj, PyObject *ident)
|
|||
maxchar = PyUnicode_MAX_CHAR_VALUE(privateobj);
|
||||
|
||||
result = PyUnicode_New(1 + nlen + plen, maxchar);
|
||||
if (!result)
|
||||
return 0;
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
/* ident = "_" + priv[ipriv:] + ident # i.e. 1+plen+nlen bytes */
|
||||
PyUnicode_WRITE(PyUnicode_KIND(result), PyUnicode_DATA(result), 0, '_');
|
||||
if (PyUnicode_CopyCharacters(result, 1, privateobj, ipriv, plen) < 0) {
|
||||
|
@ -991,11 +990,11 @@ basicblock_append_instructions(basicblock *target, basicblock *source)
|
|||
for (int i = 0; i < source->b_iused; i++) {
|
||||
int n = basicblock_next_instr(target);
|
||||
if (n < 0) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
target->b_instr[n] = source->b_instr[i];
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static basicblock *
|
||||
|
@ -1029,7 +1028,7 @@ basicblock_next_instr(basicblock *b)
|
|||
DEFAULT_BLOCK_SIZE, sizeof(struct instr));
|
||||
if (b->b_instr == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
b->b_ialloc = DEFAULT_BLOCK_SIZE;
|
||||
}
|
||||
|
@ -1041,19 +1040,19 @@ basicblock_next_instr(basicblock *b)
|
|||
|
||||
if (oldsize > (SIZE_MAX >> 1)) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (newsize == 0) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
b->b_ialloc <<= 1;
|
||||
tmp = (struct instr *)PyObject_Realloc(
|
||||
(void *)b->b_instr, newsize);
|
||||
if (tmp == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
b->b_instr = tmp;
|
||||
memset((char *)b->b_instr + oldsize, 0, newsize - oldsize);
|
||||
|
@ -1371,21 +1370,19 @@ cfg_builder_maybe_start_new_block(cfg_builder *g)
|
|||
if (cfg_builder_current_block_is_terminated(g)) {
|
||||
basicblock *b = cfg_builder_new_block(g);
|
||||
if (b == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
b->b_label = g->g_current_label.id;
|
||||
g->g_current_label = NO_LABEL;
|
||||
cfg_builder_use_next_block(g, b);
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
cfg_builder_addop(cfg_builder *g, int opcode, int oparg, location loc)
|
||||
{
|
||||
if (cfg_builder_maybe_start_new_block(g) != 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(cfg_builder_maybe_start_new_block(g));
|
||||
return basicblock_addop(g->g_curblock, opcode, oparg, loc);
|
||||
}
|
||||
|
||||
|
@ -1405,16 +1402,16 @@ dict_add_o(PyObject *dict, PyObject *o)
|
|||
v = PyDict_GetItemWithError(dict, o);
|
||||
if (!v) {
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
arg = PyDict_GET_SIZE(dict);
|
||||
v = PyLong_FromSsize_t(arg);
|
||||
if (!v) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
if (PyDict_SetItem(dict, o, v) < 0) {
|
||||
Py_DECREF(v);
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
Py_DECREF(v);
|
||||
}
|
||||
|
@ -1536,7 +1533,7 @@ compiler_add_const(struct compiler *c, PyObject *o)
|
|||
{
|
||||
PyObject *key = merge_consts_recursive(c->c_const_cache, o);
|
||||
if (key == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
Py_ssize_t arg = dict_add_o(c->u->u_consts, key);
|
||||
|
@ -1622,7 +1619,7 @@ cfg_builder_addop_j(cfg_builder *g, location loc,
|
|||
#define ADDOP_IN_SCOPE(C, LOC, OP) { \
|
||||
if (cfg_builder_addop_noarg(CFG_BUILDER(C), (OP), (LOC)) < 0) { \
|
||||
compiler_exit_scope(C); \
|
||||
return -1; \
|
||||
return ERROR; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -1697,8 +1694,7 @@ cfg_builder_addop_j(cfg_builder *g, location loc,
|
|||
asdl_ ## TYPE ## _seq *seq = (SEQ); /* avoid variable capture */ \
|
||||
for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \
|
||||
TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \
|
||||
if (compiler_visit_ ## TYPE((C), elt) < 0) \
|
||||
return ERROR; \
|
||||
RETURN_IF_ERROR(compiler_visit_ ## TYPE((C), elt)); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -2232,7 +2228,7 @@ get_ref_type(struct compiler *c, PyObject *name)
|
|||
name,
|
||||
c->u->u_name, c->u->u_ste->ste_id,
|
||||
c->u->u_ste->ste_symbols, c->u->u_varnames, c->u->u_names);
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
@ -2240,10 +2236,10 @@ get_ref_type(struct compiler *c, PyObject *name)
|
|||
static int
|
||||
compiler_lookup_arg(PyObject *dict, PyObject *name)
|
||||
{
|
||||
PyObject *v;
|
||||
v = PyDict_GetItemWithError(dict, name);
|
||||
if (v == NULL)
|
||||
return -1;
|
||||
PyObject *v = PyDict_GetItemWithError(dict, name);
|
||||
if (v == NULL) {
|
||||
return ERROR;
|
||||
}
|
||||
return PyLong_AS_LONG(v);
|
||||
}
|
||||
|
||||
|
@ -3022,7 +3018,7 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
|||
location loc = LOC(e);
|
||||
funcflags = compiler_default_arguments(c, loc, args);
|
||||
if (funcflags == -1) {
|
||||
return 0;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
_Py_DECLARE_STR(anon_lambda, "<lambda>");
|
||||
|
@ -5083,9 +5079,9 @@ ex_call:
|
|||
if (n ==0 && nelts == 1 && ((expr_ty)asdl_seq_GET(args, 0))->kind == Starred_kind) {
|
||||
VISIT(c, expr, ((expr_ty)asdl_seq_GET(args, 0))->v.Starred.value);
|
||||
}
|
||||
else if (starunpack_helper(c, loc, args, n, BUILD_LIST,
|
||||
LIST_APPEND, LIST_EXTEND, 1) < 0) {
|
||||
return ERROR;
|
||||
else {
|
||||
RETURN_IF_ERROR(starunpack_helper(c, loc, args, n, BUILD_LIST,
|
||||
LIST_APPEND, LIST_EXTEND, 1));
|
||||
}
|
||||
/* Then keyword arguments */
|
||||
if (nkwelts) {
|
||||
|
@ -7115,7 +7111,7 @@ stackdepth(basicblock *entryblock, int code_flags)
|
|||
}
|
||||
basicblock **stack = make_cfg_traversal_stack(entryblock);
|
||||
if (!stack) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
int maxdepth = 0;
|
||||
|
@ -7138,7 +7134,7 @@ stackdepth(basicblock *entryblock, int code_flags)
|
|||
PyErr_Format(PyExc_SystemError,
|
||||
"compiler stack_effect(opcode=%d, arg=%i) failed",
|
||||
instr->i_opcode, instr->i_oparg);
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
int new_depth = depth + effect;
|
||||
assert(new_depth >= 0); /* invalid code or bug in stackdepth() */
|
||||
|
@ -7194,12 +7190,12 @@ assemble_init(struct assembler *a, int firstlineno)
|
|||
if (a->a_except_table == NULL) {
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
error:
|
||||
Py_XDECREF(a->a_bytecode);
|
||||
Py_XDECREF(a->a_linetable);
|
||||
Py_XDECREF(a->a_except_table);
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -7270,13 +7266,13 @@ static int
|
|||
label_exception_targets(basicblock *entryblock) {
|
||||
basicblock **todo_stack = make_cfg_traversal_stack(entryblock);
|
||||
if (todo_stack == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
ExceptStack *except_stack = make_except_stack();
|
||||
if (except_stack == NULL) {
|
||||
PyMem_Free(todo_stack);
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
except_stack->depth = 0;
|
||||
todo_stack[0] = entryblock;
|
||||
|
@ -7354,11 +7350,11 @@ label_exception_targets(basicblock *entryblock) {
|
|||
}
|
||||
#endif
|
||||
PyMem_Free(todo_stack);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
error:
|
||||
PyMem_Free(todo_stack);
|
||||
PyMem_Free(except_stack);
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
@ -7377,14 +7373,14 @@ mark_except_handlers(basicblock *entryblock) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
mark_warm(basicblock *entryblock) {
|
||||
basicblock **stack = make_cfg_traversal_stack(entryblock);
|
||||
if (stack == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
basicblock **sp = stack;
|
||||
|
||||
|
@ -7408,7 +7404,7 @@ mark_warm(basicblock *entryblock) {
|
|||
}
|
||||
}
|
||||
PyMem_Free(stack);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -7417,12 +7413,12 @@ mark_cold(basicblock *entryblock) {
|
|||
assert(!b->b_cold && !b->b_warm);
|
||||
}
|
||||
if (mark_warm(entryblock) < 0) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
basicblock **stack = make_cfg_traversal_stack(entryblock);
|
||||
if (stack == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
basicblock **sp = stack;
|
||||
|
@ -7457,7 +7453,7 @@ mark_cold(basicblock *entryblock) {
|
|||
}
|
||||
}
|
||||
PyMem_Free(stack);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -7468,11 +7464,9 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) {
|
|||
basicblock *entryblock = g->g_entryblock;
|
||||
if (entryblock->b_next == NULL) {
|
||||
/* single basicblock, no need to reorder */
|
||||
return 0;
|
||||
}
|
||||
if (mark_cold(entryblock) < 0) {
|
||||
return -1;
|
||||
return SUCCESS;
|
||||
}
|
||||
RETURN_IF_ERROR(mark_cold(entryblock));
|
||||
|
||||
/* If we have a cold block with fallthrough to a warm block, add */
|
||||
/* an explicit jump instead of fallthrough */
|
||||
|
@ -7480,7 +7474,7 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) {
|
|||
if (b->b_cold && BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_next->b_warm) {
|
||||
basicblock *explicit_jump = cfg_builder_new_block(g);
|
||||
if (explicit_jump == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
basicblock_addop(explicit_jump, JUMP, b->b_next->b_label, NO_LOCATION);
|
||||
explicit_jump->b_cold = 1;
|
||||
|
@ -7534,11 +7528,9 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) {
|
|||
b->b_next = cold_blocks;
|
||||
|
||||
if (cold_blocks != NULL) {
|
||||
if (remove_redundant_jumps(g) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(remove_redundant_jumps(g));
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -7596,9 +7588,7 @@ assemble_emit_exception_table_entry(struct assembler *a, int start, int end, bas
|
|||
{
|
||||
Py_ssize_t len = PyBytes_GET_SIZE(a->a_except_table);
|
||||
if (a->a_except_table_off + MAX_SIZE_OF_ENTRY >= len) {
|
||||
if (_PyBytes_Resize(&a->a_except_table, len * 2) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(_PyBytes_Resize(&a->a_except_table, len * 2));
|
||||
}
|
||||
int size = end-start;
|
||||
assert(end > start);
|
||||
|
@ -7613,7 +7603,7 @@ assemble_emit_exception_table_entry(struct assembler *a, int start, int end, bas
|
|||
assemble_emit_exception_table_item(a, size, 0);
|
||||
assemble_emit_exception_table_item(a, target, 0);
|
||||
assemble_emit_exception_table_item(a, depth_lasti, 0);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -7629,9 +7619,8 @@ assemble_exception_table(struct assembler *a, basicblock *entryblock)
|
|||
struct instr *instr = &b->b_instr[i];
|
||||
if (instr->i_except != handler) {
|
||||
if (handler != NULL) {
|
||||
if (assemble_emit_exception_table_entry(a, start, ioffset, handler) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(
|
||||
assemble_emit_exception_table_entry(a, start, ioffset, handler));
|
||||
}
|
||||
start = ioffset;
|
||||
handler = instr->i_except;
|
||||
|
@ -7640,11 +7629,9 @@ assemble_exception_table(struct assembler *a, basicblock *entryblock)
|
|||
}
|
||||
}
|
||||
if (handler != NULL) {
|
||||
if (assemble_emit_exception_table_entry(a, start, ioffset, handler) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(assemble_emit_exception_table_entry(a, start, ioffset, handler));
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* Code location emitting code. See locations.md for a description of the format. */
|
||||
|
@ -7746,13 +7733,11 @@ write_location_info_entry(struct assembler* a, location loc, int isize)
|
|||
Py_ssize_t len = PyBytes_GET_SIZE(a->a_linetable);
|
||||
if (a->a_location_off + THEORETICAL_MAX_ENTRY_SIZE >= len) {
|
||||
assert(len > THEORETICAL_MAX_ENTRY_SIZE);
|
||||
if (_PyBytes_Resize(&a->a_linetable, len*2) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, len*2));
|
||||
}
|
||||
if (loc.lineno < 0) {
|
||||
write_location_info_none(a, isize);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
int line_delta = loc.lineno - a->a_lineno;
|
||||
int column = loc.col_offset;
|
||||
|
@ -7763,35 +7748,33 @@ write_location_info_entry(struct assembler* a, location loc, int isize)
|
|||
if (loc.end_lineno == loc.lineno || loc.end_lineno == -1) {
|
||||
write_location_info_no_column(a, isize, line_delta);
|
||||
a->a_lineno = loc.lineno;
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
else if (loc.end_lineno == loc.lineno) {
|
||||
if (line_delta == 0 && column < 80 && end_column - column < 16 && end_column >= column) {
|
||||
write_location_info_short_form(a, isize, column, end_column);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
if (line_delta >= 0 && line_delta < 3 && column < 128 && end_column < 128) {
|
||||
write_location_info_oneline_form(a, isize, line_delta, column, end_column);
|
||||
a->a_lineno = loc.lineno;
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
write_location_info_long_form(a, loc, isize);
|
||||
a->a_lineno = loc.lineno;
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
assemble_emit_location(struct assembler* a, location loc, int isize)
|
||||
{
|
||||
if (isize == 0) {
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
while (isize > 8) {
|
||||
if (write_location_info_entry(a, loc, 8)) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(write_location_info_entry(a, loc, 8));
|
||||
isize -= 8;
|
||||
}
|
||||
return write_location_info_entry(a, loc, isize);
|
||||
|
@ -7811,34 +7794,32 @@ assemble_emit(struct assembler *a, struct instr *i)
|
|||
int size = instr_size(i);
|
||||
if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) {
|
||||
if (len > PY_SSIZE_T_MAX / 2) {
|
||||
return -1;
|
||||
}
|
||||
if (_PyBytes_Resize(&a->a_bytecode, len * 2) < 0) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, len * 2));
|
||||
}
|
||||
code = (_Py_CODEUNIT *)PyBytes_AS_STRING(a->a_bytecode) + a->a_offset;
|
||||
a->a_offset += size;
|
||||
write_instr(code, i, size);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
|
||||
struct instr *last = basicblock_last_instr(b);
|
||||
if (last == NULL || !is_jump(last)) {
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
|
||||
bool is_forward = last->i_target->b_visited == 0;
|
||||
switch(last->i_opcode) {
|
||||
case JUMP:
|
||||
last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
case JUMP_NO_INTERRUPT:
|
||||
last->i_opcode = is_forward ?
|
||||
JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
int reversed_opcode = 0;
|
||||
switch(last->i_opcode) {
|
||||
|
@ -7868,10 +7849,10 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
|
|||
last->i_opcode == JUMP_IF_TRUE_OR_POP ?
|
||||
"JUMP_IF_TRUE_OR_POP" : "JUMP_IF_FALSE_OR_POP");
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
if (is_forward) {
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* transform 'conditional jump T' to
|
||||
|
@ -7881,7 +7862,7 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
|
|||
basicblock *target = last->i_target;
|
||||
basicblock *backwards_jump = cfg_builder_new_block(g);
|
||||
if (backwards_jump == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
basicblock_addop(backwards_jump, JUMP, target->b_label, NO_LOCATION);
|
||||
backwards_jump->b_instr[0].i_target = target;
|
||||
|
@ -7891,7 +7872,7 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
|
|||
backwards_jump->b_cold = b->b_cold;
|
||||
backwards_jump->b_next = b->b_next;
|
||||
b->b_next = backwards_jump;
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -7903,11 +7884,9 @@ normalize_jumps(cfg_builder *g)
|
|||
}
|
||||
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
|
||||
b->b_visited = 1;
|
||||
if (normalize_jumps_in_block(g, b) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(normalize_jumps_in_block(g, b));
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -8047,7 +8026,7 @@ fast_scan_many_locals(basicblock *entryblock, int nlocals)
|
|||
Py_ssize_t *states = PyMem_Calloc(nlocals - 64, sizeof(Py_ssize_t));
|
||||
if (states == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
Py_ssize_t blocknum = 0;
|
||||
// state[i - 64] == blocknum if local i is guaranteed to
|
||||
|
@ -8083,7 +8062,7 @@ fast_scan_many_locals(basicblock *entryblock, int nlocals)
|
|||
}
|
||||
}
|
||||
PyMem_Free(states);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -8092,20 +8071,20 @@ add_checks_for_loads_of_uninitialized_variables(basicblock *entryblock,
|
|||
{
|
||||
int nlocals = (int)PyDict_GET_SIZE(c->u->u_varnames);
|
||||
if (nlocals == 0) {
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
if (nlocals > 64) {
|
||||
// To avoid O(nlocals**2) compilation, locals beyond the first
|
||||
// 64 are only analyzed one basicblock at a time: initialization
|
||||
// info is not passed between basicblocks.
|
||||
if (fast_scan_many_locals(entryblock, nlocals) < 0) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
nlocals = 64;
|
||||
}
|
||||
basicblock **stack = make_cfg_traversal_stack(entryblock);
|
||||
if (stack == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
basicblock **sp = stack;
|
||||
|
||||
|
@ -8134,7 +8113,7 @@ add_checks_for_loads_of_uninitialized_variables(basicblock *entryblock,
|
|||
scan_block_for_locals(b, &sp);
|
||||
}
|
||||
PyMem_Free(stack);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
@ -8220,17 +8199,17 @@ merge_const_one(PyObject *const_cache, PyObject **obj)
|
|||
PyDict_CheckExact(const_cache);
|
||||
PyObject *key = _PyCode_ConstantKey(*obj);
|
||||
if (key == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// t is borrowed reference
|
||||
PyObject *t = PyDict_SetDefault(const_cache, key, key);
|
||||
Py_DECREF(key);
|
||||
if (t == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
if (t == key) { // obj is new constant.
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (PyTuple_CheckExact(t)) {
|
||||
|
@ -8239,7 +8218,7 @@ merge_const_one(PyObject *const_cache, PyObject **obj)
|
|||
}
|
||||
|
||||
Py_SETREF(*obj, Py_NewRef(t));
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// This is in codeobject.c.
|
||||
|
@ -8482,18 +8461,14 @@ insert_prefix_instructions(struct compiler *c, basicblock *entryblock,
|
|||
.i_loc = LOCATION(c->u->u_firstlineno, c->u->u_firstlineno, -1, -1),
|
||||
.i_target = NULL,
|
||||
};
|
||||
if (insert_instruction(entryblock, 0, &make_gen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(insert_instruction(entryblock, 0, &make_gen));
|
||||
struct instr pop_top = {
|
||||
.i_opcode = POP_TOP,
|
||||
.i_oparg = 0,
|
||||
.i_loc = NO_LOCATION,
|
||||
.i_target = NULL,
|
||||
};
|
||||
if (insert_instruction(entryblock, 1, &pop_top) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(insert_instruction(entryblock, 1, &pop_top));
|
||||
}
|
||||
|
||||
/* Set up cells for any variable that escapes, to be put in a closure. */
|
||||
|
@ -8506,7 +8481,7 @@ insert_prefix_instructions(struct compiler *c, basicblock *entryblock,
|
|||
int *sorted = PyMem_RawCalloc(nvars, sizeof(int));
|
||||
if (sorted == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
for (int i = 0; i < ncellvars; i++) {
|
||||
sorted[fixed[i]] = i + 1;
|
||||
|
@ -8523,9 +8498,7 @@ insert_prefix_instructions(struct compiler *c, basicblock *entryblock,
|
|||
.i_loc = NO_LOCATION,
|
||||
.i_target = NULL,
|
||||
};
|
||||
if (insert_instruction(entryblock, ncellsused, &make_cell) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(insert_instruction(entryblock, ncellsused, &make_cell));
|
||||
ncellsused += 1;
|
||||
}
|
||||
PyMem_RawFree(sorted);
|
||||
|
@ -8538,13 +8511,10 @@ insert_prefix_instructions(struct compiler *c, basicblock *entryblock,
|
|||
.i_loc = NO_LOCATION,
|
||||
.i_target = NULL,
|
||||
};
|
||||
if (insert_instruction(entryblock, 0, ©_frees) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(insert_instruction(entryblock, 0, ©_frees));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* Make sure that all returns have a line number, even if early passes
|
||||
|
@ -8704,7 +8674,7 @@ remove_redundant_jumps(cfg_builder *g) {
|
|||
if (IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
|
||||
if (last->i_target == NULL) {
|
||||
PyErr_SetString(PyExc_SystemError, "jump with NULL target");
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
if (last->i_target == b->b_next) {
|
||||
assert(b->b_next->b_iused);
|
||||
|
@ -8712,7 +8682,7 @@ remove_redundant_jumps(cfg_builder *g) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -8729,7 +8699,7 @@ prepare_localsplus(struct compiler* c, int code_flags)
|
|||
int nlocalsplus = nlocals + ncellvars + nfreevars;
|
||||
int* cellfixedoffsets = build_cellfixedoffsets(c);
|
||||
if (cellfixedoffsets == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
cfg_builder* g = CFG_BUILDER(c);
|
||||
|
@ -8737,14 +8707,14 @@ prepare_localsplus(struct compiler* c, int code_flags)
|
|||
// This must be called before fix_cell_offsets().
|
||||
if (insert_prefix_instructions(c, g->g_entryblock, cellfixedoffsets, nfreevars, code_flags)) {
|
||||
PyMem_Free(cellfixedoffsets);
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
int numdropped = fix_cell_offsets(c, g->g_entryblock, cellfixedoffsets);
|
||||
PyMem_Free(cellfixedoffsets); // At this point we're done with it.
|
||||
cellfixedoffsets = NULL;
|
||||
if (numdropped < 0) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
nlocalsplus -= numdropped;
|
||||
return nlocalsplus;
|
||||
|
@ -8825,7 +8795,7 @@ assemble(struct compiler *c, int addNone)
|
|||
if (add_checks_for_loads_of_uninitialized_variables(g->g_entryblock, c) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (remove_unused_consts(g->g_entryblock, consts)) {
|
||||
if (remove_unused_consts(g->g_entryblock, consts) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -8967,27 +8937,27 @@ fold_tuple_on_constants(PyObject *const_cache,
|
|||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!HAS_CONST(inst[i].i_opcode)) {
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Buildup new tuple of constants */
|
||||
PyObject *newconst = PyTuple_New(n);
|
||||
if (newconst == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
int op = inst[i].i_opcode;
|
||||
int arg = inst[i].i_oparg;
|
||||
PyObject *constant = get_const_value(op, arg, consts);
|
||||
if (constant == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
PyTuple_SET_ITEM(newconst, i, constant);
|
||||
}
|
||||
if (merge_const_one(const_cache, &newconst) < 0) {
|
||||
Py_DECREF(newconst);
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
Py_ssize_t index;
|
||||
|
@ -9000,11 +8970,11 @@ fold_tuple_on_constants(PyObject *const_cache,
|
|||
if ((size_t)index >= (size_t)INT_MAX - 1) {
|
||||
Py_DECREF(newconst);
|
||||
PyErr_SetString(PyExc_OverflowError, "too many constants");
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
if (PyList_Append(consts, newconst)) {
|
||||
Py_DECREF(newconst);
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
Py_DECREF(newconst);
|
||||
|
@ -9012,7 +8982,7 @@ fold_tuple_on_constants(PyObject *const_cache,
|
|||
INSTR_SET_OP0(&inst[i], NOP);
|
||||
}
|
||||
INSTR_SET_OP1(&inst[n], LOAD_CONST, (int)index);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
#define VISITED (-1)
|
||||
|
@ -9045,13 +9015,13 @@ swaptimize(basicblock *block, int *ix)
|
|||
}
|
||||
// It's already optimal if there's only one SWAP:
|
||||
if (!more) {
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
// Create an array with elements {0, 1, 2, ..., depth - 1}:
|
||||
int *stack = PyMem_Malloc(depth * sizeof(int));
|
||||
if (stack == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
for (int i = 0; i < depth; i++) {
|
||||
stack[i] = i;
|
||||
|
@ -9112,7 +9082,7 @@ swaptimize(basicblock *block, int *ix)
|
|||
}
|
||||
PyMem_Free(stack);
|
||||
*ix += len - 1;
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// This list is pretty small, since it's only okay to reorder opcodes that:
|
||||
|
@ -9418,7 +9388,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
|
|||
INSTR_SET_OP0(inst, NOP);
|
||||
break;
|
||||
}
|
||||
if (swaptimize(bb, &i)) {
|
||||
if (swaptimize(bb, &i) < 0) {
|
||||
goto error;
|
||||
}
|
||||
apply_static_swaps(bb, i);
|
||||
|
@ -9436,9 +9406,9 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
|
|||
assert (!HAS_CONST(inst->i_opcode));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
error:
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* If this block ends with an unconditional jump to a small exit block, then
|
||||
|
@ -9457,9 +9427,7 @@ inline_small_exit_blocks(basicblock *bb) {
|
|||
basicblock *target = last->i_target;
|
||||
if (basicblock_exits_scope(target) && target->b_iused <= MAX_COPY_SIZE) {
|
||||
INSTR_SET_OP0(last, NOP);
|
||||
if (basicblock_append_instructions(bb, target) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(basicblock_append_instructions(bb, target));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -9528,19 +9496,19 @@ check_cfg(cfg_builder *g) {
|
|||
if (IS_TERMINATOR_OPCODE(opcode)) {
|
||||
if (i != b->b_iused - 1) {
|
||||
PyErr_SetString(PyExc_SystemError, "malformed control flow graph.");
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
mark_reachable(basicblock *entryblock) {
|
||||
basicblock **stack = make_cfg_traversal_stack(entryblock);
|
||||
if (stack == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
basicblock **sp = stack;
|
||||
entryblock->b_predecessors = 1;
|
||||
|
@ -9569,7 +9537,7 @@ mark_reachable(basicblock *entryblock) {
|
|||
}
|
||||
}
|
||||
PyMem_Free(stack);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -9658,7 +9626,7 @@ translate_jump_labels_to_targets(basicblock *entryblock)
|
|||
basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize);
|
||||
if (!label2block) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
memset(label2block, 0, mapsize);
|
||||
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
|
||||
|
@ -9680,7 +9648,7 @@ translate_jump_labels_to_targets(basicblock *entryblock)
|
|||
}
|
||||
}
|
||||
PyMem_Free(label2block);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* Perform optimizations on a control flow graph.
|
||||
|
@ -9695,31 +9663,22 @@ static int
|
|||
optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
|
||||
{
|
||||
assert(PyDict_CheckExact(const_cache));
|
||||
if (check_cfg(g) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(check_cfg(g));
|
||||
eliminate_empty_basic_blocks(g);
|
||||
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
|
||||
if (inline_small_exit_blocks(b) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(inline_small_exit_blocks(b));
|
||||
}
|
||||
assert(no_empty_basic_blocks(g));
|
||||
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
|
||||
if (optimize_basic_block(const_cache, b, consts)) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts));
|
||||
remove_redundant_nops(b);
|
||||
assert(b->b_predecessors == 0);
|
||||
}
|
||||
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
|
||||
if (inline_small_exit_blocks(b) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (mark_reachable(g->g_entryblock)) {
|
||||
return -1;
|
||||
RETURN_IF_ERROR(inline_small_exit_blocks(b));
|
||||
}
|
||||
RETURN_IF_ERROR(mark_reachable(g->g_entryblock));
|
||||
|
||||
/* Delete unreachable instructions */
|
||||
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
|
||||
if (b->b_predecessors == 0) {
|
||||
|
@ -9731,10 +9690,8 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
|
|||
}
|
||||
eliminate_empty_basic_blocks(g);
|
||||
assert(no_redundant_nops(g));
|
||||
if (remove_redundant_jumps(g) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
RETURN_IF_ERROR(remove_redundant_jumps(g));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -9744,12 +9701,12 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
|
|||
assert(PyList_CheckExact(consts));
|
||||
Py_ssize_t nconsts = PyList_GET_SIZE(consts);
|
||||
if (nconsts == 0) {
|
||||
return 0; /* nothing to do */
|
||||
return SUCCESS; /* nothing to do */
|
||||
}
|
||||
|
||||
Py_ssize_t *index_map = NULL;
|
||||
Py_ssize_t *reverse_index_map = NULL;
|
||||
int err = 1;
|
||||
int err = ERROR;
|
||||
|
||||
index_map = PyMem_Malloc(nconsts * sizeof(Py_ssize_t));
|
||||
if (index_map == NULL) {
|
||||
|
@ -9784,7 +9741,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
|
|||
}
|
||||
if (n_used_consts == nconsts) {
|
||||
/* nothing to do */
|
||||
err = 0;
|
||||
err = SUCCESS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -9832,7 +9789,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
|
|||
}
|
||||
}
|
||||
|
||||
err = 0;
|
||||
err = SUCCESS;
|
||||
end:
|
||||
PyMem_Free(index_map);
|
||||
PyMem_Free(reverse_index_map);
|
||||
|
@ -9876,7 +9833,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
|
|||
if (is_exit_without_lineno(target) && target->b_predecessors > 1) {
|
||||
basicblock *new_target = copy_basicblock(g, target);
|
||||
if (new_target == NULL) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
new_target->b_instr[0].i_loc = last->i_loc;
|
||||
last->i_target = new_target;
|
||||
|
@ -9899,7 +9856,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
|
|||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -9928,54 +9885,50 @@ instructions_to_cfg(PyObject *instructions, cfg_builder *g)
|
|||
if (PyLong_Check(item)) {
|
||||
int lbl_id = PyLong_AsLong(item);
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
if (lbl_id <= 0 || lbl_id > instr_size) {
|
||||
/* expect label in a reasonable range */
|
||||
PyErr_SetString(PyExc_ValueError, "label out of range");
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
jump_target_label lbl = {lbl_id};
|
||||
if (cfg_builder_use_label(g, lbl) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_ERROR(cfg_builder_use_label(g, lbl));
|
||||
}
|
||||
else {
|
||||
if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 6) {
|
||||
PyErr_SetString(PyExc_ValueError, "expected a 6-tuple");
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
int opcode = PyLong_AsLong(PyTuple_GET_ITEM(item, 0));
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
int oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1));
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
location loc;
|
||||
loc.lineno = PyLong_AsLong(PyTuple_GET_ITEM(item, 2));
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
loc.end_lineno = PyLong_AsLong(PyTuple_GET_ITEM(item, 3));
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
loc.col_offset = PyLong_AsLong(PyTuple_GET_ITEM(item, 4));
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
loc.end_col_offset = PyLong_AsLong(PyTuple_GET_ITEM(item, 5));
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
if (cfg_builder_addop(g, opcode, oparg, loc) < 0) {
|
||||
return -1;
|
||||
return ERROR;
|
||||
}
|
||||
RETURN_IF_ERROR(cfg_builder_addop(g, opcode, oparg, loc));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
|
Loading…
Reference in New Issue