gh-121404: remove some accesses to compiler internals from codegen functions (#121538)

This commit is contained in:
Irit Katriel 2024-07-10 17:09:45 +01:00 committed by GitHub
parent af9f6de6ea
commit 0177a34335
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -71,11 +71,24 @@
((C)->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \ ((C)->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \
&& ((C)->u->u_ste->ste_type == ModuleBlock)) && ((C)->u->u_ste->ste_type == ModuleBlock))
struct compiler;
typedef _PyInstruction instruction;
typedef _PyInstructionSequence instr_sequence;
static instr_sequence *compiler_instr_sequence(struct compiler *c);
static int compiler_future_features(struct compiler *c);
static struct symtable *compiler_symtable(struct compiler *c);
static PySTEntryObject *compiler_symtable_entry(struct compiler *c);
#define INSTR_SEQUENCE(C) compiler_instr_sequence(C)
#define FUTURE_FEATURES(C) compiler_future_features(C)
#define SYMTABLE(C) compiler_symtable(C)
#define SYMTABLE_ENTRY(C) compiler_symtable_entry(C)
typedef _Py_SourceLocation location; typedef _Py_SourceLocation location;
typedef struct _PyCfgBuilder cfg_builder; typedef struct _PyCfgBuilder cfg_builder;
struct compiler;
static PyObject *compiler_maybe_mangle(struct compiler *c, PyObject *name); static PyObject *compiler_maybe_mangle(struct compiler *c, PyObject *name);
#define LOCATION(LNO, END_LNO, COL, END_COL) \ #define LOCATION(LNO, END_LNO, COL, END_COL) \
@ -133,12 +146,6 @@ enum {
}; };
typedef _PyInstruction instruction;
typedef _PyInstructionSequence instr_sequence;
#define INITIAL_INSTR_SEQUENCE_SIZE 100
#define INITIAL_INSTR_SEQUENCE_LABELS_MAP_SIZE 10
static const int compare_masks[] = { static const int compare_masks[] = {
[Py_LT] = COMPARISON_LESS_THAN, [Py_LT] = COMPARISON_LESS_THAN,
[Py_LE] = COMPARISON_LESS_THAN | COMPARISON_EQUALS, [Py_LE] = COMPARISON_LESS_THAN | COMPARISON_EQUALS,
@ -258,8 +265,6 @@ struct compiler {
*/ */
}; };
#define INSTR_SEQUENCE(C) ((C)->u->u_instr_sequence)
typedef struct { typedef struct {
// A list of strings corresponding to name captures. It is used to track: // A list of strings corresponding to name captures. It is used to track:
@ -317,7 +322,6 @@ static int compiler_call_helper(struct compiler *c, location loc,
asdl_keyword_seq *keywords); asdl_keyword_seq *keywords);
static int compiler_try_except(struct compiler *, stmt_ty); static int compiler_try_except(struct compiler *, stmt_ty);
static int compiler_try_star_except(struct compiler *, stmt_ty); static int compiler_try_star_except(struct compiler *, stmt_ty);
static int compiler_set_qualname(struct compiler *);
static int compiler_sync_comprehension_generator( static int compiler_sync_comprehension_generator(
struct compiler *c, location loc, struct compiler *c, location loc,
@ -558,8 +562,8 @@ compiler_unit_free(struct compiler_unit *u)
PyMem_Free(u); PyMem_Free(u);
} }
static struct compiler_unit * static int
get_class_compiler_unit(struct compiler *c) compiler_add_static_attribute_to_class(struct compiler *c, PyObject *attr)
{ {
Py_ssize_t stack_size = PyList_GET_SIZE(c->c_stack); Py_ssize_t stack_size = PyList_GET_SIZE(c->c_stack);
for (Py_ssize_t i = stack_size - 1; i >= 0; i--) { for (Py_ssize_t i = stack_size - 1; i >= 0; i--) {
@ -568,10 +572,12 @@ get_class_compiler_unit(struct compiler *c)
capsule, CAPSULE_NAME); capsule, CAPSULE_NAME);
assert(u); assert(u);
if (u->u_scope_type == COMPILER_SCOPE_CLASS) { if (u->u_scope_type == COMPILER_SCOPE_CLASS) {
return u; assert(u->u_static_attributes);
RETURN_IF_ERROR(PySet_Add(u->u_static_attributes, attr));
break;
} }
} }
return NULL; return SUCCESS;
} }
static int static int
@ -863,38 +869,37 @@ merge_consts_recursive(PyObject *const_cache, PyObject *o)
} }
static Py_ssize_t static Py_ssize_t
compiler_add_const(PyObject *const_cache, struct compiler_unit *u, PyObject *o) compiler_add_const(struct compiler *c, PyObject *o)
{ {
assert(PyDict_CheckExact(const_cache)); PyObject *key = merge_consts_recursive(c->c_const_cache, o);
PyObject *key = merge_consts_recursive(const_cache, o);
if (key == NULL) { if (key == NULL) {
return ERROR; return ERROR;
} }
Py_ssize_t arg = dict_add_o(u->u_metadata.u_consts, key); Py_ssize_t arg = dict_add_o(c->u->u_metadata.u_consts, key);
Py_DECREF(key); Py_DECREF(key);
return arg; return arg;
} }
static int static int
compiler_addop_load_const(PyObject *const_cache, struct compiler_unit *u, location loc, PyObject *o) compiler_addop_load_const(struct compiler *c, location loc, PyObject *o)
{ {
Py_ssize_t arg = compiler_add_const(const_cache, u, o); Py_ssize_t arg = compiler_add_const(c, o);
if (arg < 0) { if (arg < 0) {
return ERROR; return ERROR;
} }
return codegen_addop_i(u->u_instr_sequence, LOAD_CONST, arg, loc); return codegen_addop_i(INSTR_SEQUENCE(c), LOAD_CONST, arg, loc);
} }
static int static int
compiler_addop_o(struct compiler_unit *u, location loc, compiler_addop_o(struct compiler *c, location loc,
int opcode, PyObject *dict, PyObject *o) int opcode, PyObject *dict, PyObject *o)
{ {
Py_ssize_t arg = dict_add_o(dict, o); Py_ssize_t arg = dict_add_o(dict, o);
if (arg < 0) { if (arg < 0) {
return ERROR; return ERROR;
} }
return codegen_addop_i(u->u_instr_sequence, opcode, arg, loc); return codegen_addop_i(INSTR_SEQUENCE(c), opcode, arg, loc);
} }
#define LOAD_METHOD -1 #define LOAD_METHOD -1
@ -984,7 +989,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
#define ADDOP_IN_SCOPE(C, LOC, OP) RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC))) #define ADDOP_IN_SCOPE(C, LOC, OP) RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))
#define ADDOP_LOAD_CONST(C, LOC, O) \ #define ADDOP_LOAD_CONST(C, LOC, O) \
RETURN_IF_ERROR(compiler_addop_load_const((C)->c_const_cache, (C)->u, (LOC), (O))) RETURN_IF_ERROR(compiler_addop_load_const((C), (LOC), (O)))
/* Same as ADDOP_LOAD_CONST, but steals a reference. */ /* Same as ADDOP_LOAD_CONST, but steals a reference. */
#define ADDOP_LOAD_CONST_NEW(C, LOC, O) { \ #define ADDOP_LOAD_CONST_NEW(C, LOC, O) { \
@ -992,7 +997,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
if (__new_const == NULL) { \ if (__new_const == NULL) { \
return ERROR; \ return ERROR; \
} \ } \
if (compiler_addop_load_const((C)->c_const_cache, (C)->u, (LOC), __new_const) < 0) { \ if (compiler_addop_load_const((C), (LOC), __new_const) < 0) { \
Py_DECREF(__new_const); \ Py_DECREF(__new_const); \
return ERROR; \ return ERROR; \
} \ } \
@ -1001,7 +1006,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
#define ADDOP_N(C, LOC, OP, O, TYPE) { \ #define ADDOP_N(C, LOC, OP, O, TYPE) { \
assert(!OPCODE_HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \ assert(!OPCODE_HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
if (compiler_addop_o((C)->u, (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)) < 0) { \ if (compiler_addop_o((C), (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)) < 0) { \
Py_DECREF((O)); \ Py_DECREF((O)); \
return ERROR; \ return ERROR; \
} \ } \
@ -1514,7 +1519,7 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
/* If from __future__ import annotations is active, /* If from __future__ import annotations is active,
* every annotated class and module should have __annotations__. * every annotated class and module should have __annotations__.
* Else __annotate__ is created when necessary. */ * Else __annotate__ is created when necessary. */
if ((c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) && c->u->u_ste->ste_annotations_used) { if ((FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) && SYMTABLE_ENTRY(c)->ste_annotations_used) {
ADDOP(c, loc, SETUP_ANNOTATIONS); ADDOP(c, loc, SETUP_ANNOTATIONS);
} }
if (!asdl_seq_LEN(stmts)) { if (!asdl_seq_LEN(stmts)) {
@ -1546,7 +1551,7 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
// If there are annotations and the future import is not on, we // If there are annotations and the future import is not on, we
// collect the annotations in a separate pass and generate an // collect the annotations in a separate pass and generate an
// __annotate__ function. See PEP 649. // __annotate__ function. See PEP 649.
if (!(c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) && if (!(FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) &&
c->u->u_deferred_annotations != NULL) { c->u->u_deferred_annotations != NULL) {
// It's possible that ste_annotations_block is set but // It's possible that ste_annotations_block is set but
@ -1554,11 +1559,12 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
// set if there are only non-simple annotations (i.e., annotations // set if there are only non-simple annotations (i.e., annotations
// for attributes, subscripts, or parenthesized names). However, the // for attributes, subscripts, or parenthesized names). However, the
// reverse should not be possible. // reverse should not be possible.
assert(c->u->u_ste->ste_annotation_block != NULL); PySTEntryObject *ste = SYMTABLE_ENTRY(c);
assert(ste->ste_annotation_block != NULL);
PyObject *deferred_anno = Py_NewRef(c->u->u_deferred_annotations); PyObject *deferred_anno = Py_NewRef(c->u->u_deferred_annotations);
void *key = (void *)((uintptr_t)c->u->u_ste->ste_id + 1); void *key = (void *)((uintptr_t)ste->ste_id + 1);
if (compiler_setup_annotations_scope(c, loc, key, if (compiler_setup_annotations_scope(c, loc, key,
c->u->u_ste->ste_annotation_block->ste_name) == -1) { ste->ste_annotation_block->ste_name) == -1) {
Py_DECREF(deferred_anno); Py_DECREF(deferred_anno);
return ERROR; return ERROR;
} }
@ -1642,13 +1648,8 @@ finally:
return co; return co;
} }
/* The test for LOCAL must come before the test for FREE in order to
handle classes where name is both local and free. The local var is
a method and the free var is a free var referenced within a method.
*/
static int static int
get_ref_type(struct compiler *c, PyObject *name) compiler_get_ref_type(struct compiler *c, PyObject *name)
{ {
int scope; int scope;
if (c->u->u_scope_type == COMPILER_SCOPE_CLASS && if (c->u->u_scope_type == COMPILER_SCOPE_CLASS &&
@ -1656,15 +1657,16 @@ get_ref_type(struct compiler *c, PyObject *name)
_PyUnicode_EqualToASCIIString(name, "__classdict__"))) { _PyUnicode_EqualToASCIIString(name, "__classdict__"))) {
return CELL; return CELL;
} }
scope = _PyST_GetScope(c->u->u_ste, name); PySTEntryObject *ste = SYMTABLE_ENTRY(c);
scope = _PyST_GetScope(ste, name);
if (scope == 0) { if (scope == 0) {
PyErr_Format(PyExc_SystemError, PyErr_Format(PyExc_SystemError,
"_PyST_GetScope(name=%R) failed: " "_PyST_GetScope(name=%R) failed: "
"unknown scope in unit %S (%R); " "unknown scope in unit %S (%R); "
"symbols: %R; locals: %R; globals: %R", "symbols: %R; locals: %R; globals: %R",
name, name,
c->u->u_metadata.u_name, c->u->u_ste->ste_id, c->u->u_metadata.u_name, ste->ste_id,
c->u->u_ste->ste_symbols, c->u->u_metadata.u_varnames, c->u->u_metadata.u_names); ste->ste_symbols, c->u->u_metadata.u_varnames, c->u->u_metadata.u_names);
return ERROR; return ERROR;
} }
return scope; return scope;
@ -1698,7 +1700,7 @@ compiler_make_closure(struct compiler *c, location loc,
class. It should be handled by the closure, as class. It should be handled by the closure, as
well as by the normal name lookup logic. well as by the normal name lookup logic.
*/ */
int reftype = get_ref_type(c, name); int reftype = compiler_get_ref_type(c, name);
if (reftype == -1) { if (reftype == -1) {
return ERROR; return ERROR;
} }
@ -1858,7 +1860,7 @@ compiler_argannotation(struct compiler *c, identifier id,
ADDOP_LOAD_CONST(c, loc, mangled); ADDOP_LOAD_CONST(c, loc, mangled);
Py_DECREF(mangled); Py_DECREF(mangled);
if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) { if (FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) {
VISIT(c, annexpr, annotation); VISIT(c, annexpr, annotation);
} }
else { else {
@ -1940,7 +1942,7 @@ compiler_annotations(struct compiler *c, location loc,
Py_ssize_t annotations_len = 0; Py_ssize_t annotations_len = 0;
PySTEntryObject *ste; PySTEntryObject *ste;
if (_PySymtable_LookupOptional(c->c_st, args, &ste) < 0) { if (_PySymtable_LookupOptional(SYMTABLE(c), args, &ste) < 0) {
return ERROR; return ERROR;
} }
assert(ste != NULL); assert(ste != NULL);
@ -2239,7 +2241,7 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
docstring = NULL; docstring = NULL;
} }
} }
if (compiler_add_const(c->c_const_cache, c->u, docstring ? docstring : Py_None) < 0) { if (compiler_add_const(c, docstring ? docstring : Py_None) < 0) {
Py_XDECREF(docstring); Py_XDECREF(docstring);
compiler_exit_scope(c); compiler_exit_scope(c);
return ERROR; return ERROR;
@ -2252,7 +2254,8 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
NEW_JUMP_TARGET_LABEL(c, start); NEW_JUMP_TARGET_LABEL(c, start);
USE_LABEL(c, start); USE_LABEL(c, start);
bool add_stopiteration_handler = c->u->u_ste->ste_coroutine || c->u->u_ste->ste_generator; PySTEntryObject *ste = SYMTABLE_ENTRY(c);
bool add_stopiteration_handler = ste->ste_coroutine || ste->ste_generator;
if (add_stopiteration_handler) { if (add_stopiteration_handler) {
/* wrap_in_stopiteration_handler will push a block, so we need to account for that */ /* wrap_in_stopiteration_handler will push a block, so we need to account for that */
RETURN_IF_ERROR( RETURN_IF_ERROR(
@ -2463,14 +2466,14 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
return ERROR; return ERROR;
} }
} }
if (c->u->u_ste->ste_needs_classdict) { if (SYMTABLE_ENTRY(c)->ste_needs_classdict) {
ADDOP(c, loc, LOAD_LOCALS); ADDOP(c, loc, LOAD_LOCALS);
// We can't use compiler_nameop here because we need to generate a // We can't use compiler_nameop here because we need to generate a
// STORE_DEREF in a class namespace, and compiler_nameop() won't do // STORE_DEREF in a class namespace, and compiler_nameop() won't do
// that by default. // that by default.
PyObject *cellvars = c->u->u_metadata.u_cellvars; PyObject *cellvars = c->u->u_metadata.u_cellvars;
if (compiler_addop_o(c->u, loc, STORE_DEREF, cellvars, if (compiler_addop_o(c, loc, STORE_DEREF, cellvars,
&_Py_ID(__classdict__)) < 0) { &_Py_ID(__classdict__)) < 0) {
compiler_exit_scope(c); compiler_exit_scope(c);
return ERROR; return ERROR;
@ -2495,7 +2498,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
} }
/* The following code is artificial */ /* The following code is artificial */
/* Set __classdictcell__ if necessary */ /* Set __classdictcell__ if necessary */
if (c->u->u_ste->ste_needs_classdict) { if (SYMTABLE_ENTRY(c)->ste_needs_classdict) {
/* Store __classdictcell__ into class namespace */ /* Store __classdictcell__ into class namespace */
int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__classdict__)); int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__classdict__));
if (i < 0) { if (i < 0) {
@ -2509,7 +2512,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
} }
} }
/* Return __classcell__ if it is referenced, otherwise return None */ /* Return __classcell__ if it is referenced, otherwise return None */
if (c->u->u_ste->ste_needs_class_closure) { if (SYMTABLE_ENTRY(c)->ste_needs_class_closure) {
/* Store __classcell__ into class namespace & return it */ /* Store __classcell__ into class namespace & return it */
int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__)); int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__));
if (i < 0) { if (i < 0) {
@ -2667,7 +2670,7 @@ compiler_typealias_body(struct compiler *c, stmt_ty s)
compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, s, loc.lineno, NULL)); compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, s, loc.lineno, NULL));
/* Make None the first constant, so the evaluate function can't have a /* Make None the first constant, so the evaluate function can't have a
docstring. */ docstring. */
RETURN_IF_ERROR(compiler_add_const(c->c_const_cache, c->u, Py_None)); RETURN_IF_ERROR(compiler_add_const(c, Py_None));
VISIT_IN_SCOPE(c, expr, s->v.TypeAlias.value); VISIT_IN_SCOPE(c, expr, s->v.TypeAlias.value);
ADDOP_IN_SCOPE(c, loc, RETURN_VALUE); ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);
PyCodeObject *co = optimize_and_assemble(c, 0); PyCodeObject *co = optimize_and_assemble(c, 0);
@ -2705,7 +2708,7 @@ compiler_typealias(struct compiler *c, stmt_ty s)
} }
Py_DECREF(type_params_name); Py_DECREF(type_params_name);
RETURN_IF_ERROR_IN_SCOPE( RETURN_IF_ERROR_IN_SCOPE(
c, compiler_addop_load_const(c->c_const_cache, c->u, loc, name) c, compiler_addop_load_const(c, loc, name)
); );
RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params)); RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params));
} }
@ -2972,13 +2975,13 @@ compiler_lambda(struct compiler *c, expr_ty e)
/* Make None the first constant, so the lambda can't have a /* Make None the first constant, so the lambda can't have a
docstring. */ docstring. */
RETURN_IF_ERROR(compiler_add_const(c->c_const_cache, c->u, Py_None)); RETURN_IF_ERROR(compiler_add_const(c, Py_None));
c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args); c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args);
c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs); c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);
if (c->u->u_ste->ste_generator) { if (SYMTABLE_ENTRY(c)->ste_generator) {
co = optimize_and_assemble(c, 0); co = optimize_and_assemble(c, 0);
} }
else { else {
@ -3154,12 +3157,12 @@ compiler_return(struct compiler *c, stmt_ty s)
location loc = LOC(s); location loc = LOC(s);
int preserve_tos = ((s->v.Return.value != NULL) && int preserve_tos = ((s->v.Return.value != NULL) &&
(s->v.Return.value->kind != Constant_kind)); (s->v.Return.value->kind != Constant_kind));
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
PySTEntryObject *ste = SYMTABLE_ENTRY(c);
if (!_PyST_IsFunctionLike(ste)) {
return compiler_error(c, loc, "'return' outside function"); return compiler_error(c, loc, "'return' outside function");
} }
if (s->v.Return.value != NULL && if (s->v.Return.value != NULL && ste->ste_coroutine && ste->ste_generator) {
c->u->u_ste->ste_coroutine && c->u->u_ste->ste_generator)
{
return compiler_error(c, loc, "'return' with value in async generator"); return compiler_error(c, loc, "'return' with value in async generator");
} }
@ -4109,7 +4112,8 @@ addop_binary(struct compiler *c, location loc, operator_ty binop,
static int static int
addop_yield(struct compiler *c, location loc) { addop_yield(struct compiler *c, location loc) {
if (c->u->u_ste->ste_generator && c->u->u_ste->ste_coroutine) { PySTEntryObject *ste = SYMTABLE_ENTRY(c);
if (ste->ste_generator && ste->ste_coroutine) {
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_ASYNC_GEN_WRAP); ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_ASYNC_GEN_WRAP);
} }
ADDOP_I(c, loc, YIELD_VALUE, 0); ADDOP_I(c, loc, YIELD_VALUE, 0);
@ -4143,7 +4147,7 @@ compiler_nameop(struct compiler *c, location loc,
op = 0; op = 0;
optype = OP_NAME; optype = OP_NAME;
scope = _PyST_GetScope(c->u->u_ste, mangled); scope = _PyST_GetScope(SYMTABLE_ENTRY(c), mangled);
switch (scope) { switch (scope) {
case FREE: case FREE:
dict = c->u->u_metadata.u_freevars; dict = c->u->u_metadata.u_freevars;
@ -4154,7 +4158,7 @@ compiler_nameop(struct compiler *c, location loc,
optype = OP_DEREF; optype = OP_DEREF;
break; break;
case LOCAL: case LOCAL:
if (_PyST_IsFunctionLike(c->u->u_ste)) { if (_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
optype = OP_FAST; optype = OP_FAST;
} }
else { else {
@ -4170,7 +4174,7 @@ compiler_nameop(struct compiler *c, location loc,
} }
break; break;
case GLOBAL_IMPLICIT: case GLOBAL_IMPLICIT:
if (_PyST_IsFunctionLike(c->u->u_ste)) if (_PyST_IsFunctionLike(SYMTABLE_ENTRY(c)))
optype = OP_GLOBAL; optype = OP_GLOBAL;
break; break;
case GLOBAL_EXPLICIT: case GLOBAL_EXPLICIT:
@ -4188,17 +4192,17 @@ compiler_nameop(struct compiler *c, location loc,
case OP_DEREF: case OP_DEREF:
switch (ctx) { switch (ctx) {
case Load: case Load:
if (c->u->u_ste->ste_type == ClassBlock && !c->u->u_in_inlined_comp) { if (SYMTABLE_ENTRY(c)->ste_type == ClassBlock && !c->u->u_in_inlined_comp) {
op = LOAD_FROM_DICT_OR_DEREF; op = LOAD_FROM_DICT_OR_DEREF;
// First load the locals // First load the locals
if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) { if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) {
goto error; goto error;
} }
} }
else if (c->u->u_ste->ste_can_see_class_scope) { else if (SYMTABLE_ENTRY(c)->ste_can_see_class_scope) {
op = LOAD_FROM_DICT_OR_DEREF; op = LOAD_FROM_DICT_OR_DEREF;
// First load the classdict // First load the classdict
if (compiler_addop_o(c->u, loc, LOAD_DEREF, if (compiler_addop_o(c, loc, LOAD_DEREF,
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) { c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
goto error; goto error;
} }
@ -4222,10 +4226,10 @@ compiler_nameop(struct compiler *c, location loc,
case OP_GLOBAL: case OP_GLOBAL:
switch (ctx) { switch (ctx) {
case Load: case Load:
if (c->u->u_ste->ste_can_see_class_scope && scope == GLOBAL_IMPLICIT) { if (SYMTABLE_ENTRY(c)->ste_can_see_class_scope && scope == GLOBAL_IMPLICIT) {
op = LOAD_FROM_DICT_OR_GLOBALS; op = LOAD_FROM_DICT_OR_GLOBALS;
// First load the classdict // First load the classdict
if (compiler_addop_o(c->u, loc, LOAD_DEREF, if (compiler_addop_o(c, loc, LOAD_DEREF,
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) { c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
goto error; goto error;
} }
@ -4240,7 +4244,7 @@ compiler_nameop(struct compiler *c, location loc,
case OP_NAME: case OP_NAME:
switch (ctx) { switch (ctx) {
case Load: case Load:
op = (c->u->u_ste->ste_type == ClassBlock op = (SYMTABLE_ENTRY(c)->ste_type == ClassBlock
&& c->u->u_in_inlined_comp) && c->u->u_in_inlined_comp)
? LOAD_GLOBAL ? LOAD_GLOBAL
: LOAD_NAME; : LOAD_NAME;
@ -4745,7 +4749,7 @@ is_import_originated(struct compiler *c, expr_ty e)
return 0; return 0;
} }
long flags = _PyST_GetSymbol(c->c_st->st_top, e->v.Name.id); long flags = _PyST_GetSymbol(SYMTABLE(c)->st_top, e->v.Name.id);
return flags & DEF_IMPORT; return flags & DEF_IMPORT;
} }
@ -4764,11 +4768,11 @@ can_optimize_super_call(struct compiler *c, expr_ty attr)
PyObject *super_name = e->v.Call.func->v.Name.id; PyObject *super_name = e->v.Call.func->v.Name.id;
// detect statically-visible shadowing of 'super' name // detect statically-visible shadowing of 'super' name
int scope = _PyST_GetScope(c->u->u_ste, super_name); int scope = _PyST_GetScope(SYMTABLE_ENTRY(c), super_name);
if (scope != GLOBAL_IMPLICIT) { if (scope != GLOBAL_IMPLICIT) {
return 0; return 0;
} }
scope = _PyST_GetScope(c->c_st->st_top, super_name); scope = _PyST_GetScope(SYMTABLE(c)->st_top, super_name);
if (scope != 0) { if (scope != 0) {
return 0; return 0;
} }
@ -4796,7 +4800,7 @@ can_optimize_super_call(struct compiler *c, expr_ty attr)
return 0; return 0;
} }
// __class__ cell should be available // __class__ cell should be available
if (get_ref_type(c, &_Py_ID(__class__)) == FREE) { if (compiler_get_ref_type(c, &_Py_ID(__class__)) == FREE) {
return 1; return 1;
} }
return 0; return 0;
@ -4818,7 +4822,7 @@ load_args_for_super(struct compiler *c, expr_ty e) {
// load __class__ cell // load __class__ cell
PyObject *name = &_Py_ID(__class__); PyObject *name = &_Py_ID(__class__);
assert(get_ref_type(c, name) == FREE); assert(compiler_get_ref_type(c, name) == FREE);
RETURN_IF_ERROR(compiler_nameop(c, loc, name, Load)); RETURN_IF_ERROR(compiler_nameop(c, loc, name, Load));
// load self (first argument) // load self (first argument)
@ -5490,7 +5494,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
PySTEntryObject *entry, PySTEntryObject *entry,
inlined_comprehension_state *state) inlined_comprehension_state *state)
{ {
int in_class_block = (c->u->u_ste->ste_type == ClassBlock) && !c->u->u_in_inlined_comp; int in_class_block = (SYMTABLE_ENTRY(c)->ste_type == ClassBlock) && !c->u->u_in_inlined_comp;
c->u->u_in_inlined_comp++; c->u->u_in_inlined_comp++;
// iterate over names bound in the comprehension and ensure we isolate // iterate over names bound in the comprehension and ensure we isolate
// them from the outer scope as needed // them from the outer scope as needed
@ -5500,7 +5504,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
assert(PyLong_Check(v)); assert(PyLong_Check(v));
long symbol = PyLong_AS_LONG(v); long symbol = PyLong_AS_LONG(v);
long scope = (symbol >> SCOPE_OFFSET) & SCOPE_MASK; long scope = (symbol >> SCOPE_OFFSET) & SCOPE_MASK;
PyObject *outv = PyDict_GetItemWithError(c->u->u_ste->ste_symbols, k); PyObject *outv = PyDict_GetItemWithError(SYMTABLE_ENTRY(c)->ste_symbols, k);
if (outv == NULL) { if (outv == NULL) {
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
return ERROR; return ERROR;
@ -5529,7 +5533,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
// the outer version; we'll restore it after running the // the outer version; we'll restore it after running the
// comprehension // comprehension
Py_INCREF(outv); Py_INCREF(outv);
if (PyDict_SetItem(c->u->u_ste->ste_symbols, k, v) < 0) { if (PyDict_SetItem(SYMTABLE_ENTRY(c)->ste_symbols, k, v) < 0) {
Py_DECREF(outv); Py_DECREF(outv);
return ERROR; return ERROR;
} }
@ -5542,7 +5546,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
// locals handling for names bound in comprehension (DEF_LOCAL | // locals handling for names bound in comprehension (DEF_LOCAL |
// DEF_NONLOCAL occurs in assignment expression to nonlocal) // DEF_NONLOCAL occurs in assignment expression to nonlocal)
if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) { if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) {
if (!_PyST_IsFunctionLike(c->u->u_ste)) { if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
// non-function scope: override this name to use fast locals // non-function scope: override this name to use fast locals
PyObject *orig; PyObject *orig;
if (PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, k, &orig) < 0) { if (PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, k, &orig) < 0) {
@ -5644,7 +5648,7 @@ pop_inlined_comprehension_state(struct compiler *c, location loc,
Py_ssize_t pos = 0; Py_ssize_t pos = 0;
if (state.temp_symbols) { if (state.temp_symbols) {
while (PyDict_Next(state.temp_symbols, &pos, &k, &v)) { while (PyDict_Next(state.temp_symbols, &pos, &k, &v)) {
if (PyDict_SetItem(c->u->u_ste->ste_symbols, k, v)) { if (PyDict_SetItem(SYMTABLE_ENTRY(c)->ste_symbols, k, v)) {
return ERROR; return ERROR;
} }
} }
@ -5713,7 +5717,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
comprehension_ty outermost; comprehension_ty outermost;
int scope_type = c->u->u_scope_type; int scope_type = c->u->u_scope_type;
int is_top_level_await = IS_TOP_LEVEL_AWAIT(c); int is_top_level_await = IS_TOP_LEVEL_AWAIT(c);
PySTEntryObject *entry = _PySymtable_Lookup(c->c_st, (void *)e); PySTEntryObject *entry = _PySymtable_Lookup(SYMTABLE(c), (void *)e);
if (entry == NULL) { if (entry == NULL) {
goto error; goto error;
} }
@ -6150,7 +6154,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
case DictComp_kind: case DictComp_kind:
return compiler_dictcomp(c, e); return compiler_dictcomp(c, e);
case Yield_kind: case Yield_kind:
if (!_PyST_IsFunctionLike(c->u->u_ste)) { if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
return compiler_error(c, loc, "'yield' outside function"); return compiler_error(c, loc, "'yield' outside function");
} }
if (e->v.Yield.value) { if (e->v.Yield.value) {
@ -6162,7 +6166,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
ADDOP_YIELD(c, loc); ADDOP_YIELD(c, loc);
break; break;
case YieldFrom_kind: case YieldFrom_kind:
if (!_PyST_IsFunctionLike(c->u->u_ste)) { if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
return compiler_error(c, loc, "'yield' outside function"); return compiler_error(c, loc, "'yield' outside function");
} }
if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) { if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) {
@ -6175,7 +6179,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
break; break;
case Await_kind: case Await_kind:
if (!IS_TOP_LEVEL_AWAIT(c)){ if (!IS_TOP_LEVEL_AWAIT(c)){
if (!_PyST_IsFunctionLike(c->u->u_ste)) { if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
return compiler_error(c, loc, "'await' outside function"); return compiler_error(c, loc, "'await' outside function");
} }
@ -6215,13 +6219,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
if (e->v.Attribute.value->kind == Name_kind && if (e->v.Attribute.value->kind == Name_kind &&
_PyUnicode_EqualToASCIIString(e->v.Attribute.value->v.Name.id, "self")) _PyUnicode_EqualToASCIIString(e->v.Attribute.value->v.Name.id, "self"))
{ {
struct compiler_unit *class_u = get_class_compiler_unit(c); RETURN_IF_ERROR(compiler_add_static_attribute_to_class(c, e->v.Attribute.attr));
if (class_u != NULL) {
assert(class_u->u_scope_type == COMPILER_SCOPE_CLASS);
assert(class_u->u_static_attributes);
RETURN_IF_ERROR(
PySet_Add(class_u->u_static_attributes, e->v.Attribute.attr));
}
} }
VISIT(c, expr, e->v.Attribute.value); VISIT(c, expr, e->v.Attribute.value);
loc = LOC(e); loc = LOC(e);
@ -6368,7 +6366,7 @@ check_annotation(struct compiler *c, stmt_ty s)
{ {
/* Annotations of complex targets does not produce anything /* Annotations of complex targets does not produce anything
under annotations future */ under annotations future */
if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) { if (FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) {
return SUCCESS; return SUCCESS;
} }
@ -6415,7 +6413,7 @@ compiler_annassign(struct compiler *c, stmt_ty s)
{ {
location loc = LOC(s); location loc = LOC(s);
expr_ty targ = s->v.AnnAssign.target; expr_ty targ = s->v.AnnAssign.target;
bool future_annotations = c->c_future.ff_features & CO_FUTURE_ANNOTATIONS; bool future_annotations = FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS;
PyObject *mangled; PyObject *mangled;
assert(s->kind == AnnAssign_kind); assert(s->kind == AnnAssign_kind);
@ -7485,19 +7483,41 @@ compiler_maybe_mangle(struct compiler *c, PyObject *name)
return _Py_MaybeMangle(c->u->u_private, c->u->u_ste, name); return _Py_MaybeMangle(c->u->u_private, c->u->u_ste, name);
} }
static instr_sequence *
compiler_instr_sequence(struct compiler *c)
{
return c->u->u_instr_sequence;
}
static int
compiler_future_features(struct compiler *c)
{
return c->c_future.ff_features;
}
static struct symtable *
compiler_symtable(struct compiler *c)
{
return c->c_st;
}
static PySTEntryObject *
compiler_symtable_entry(struct compiler *c)
{
return c->u->u_ste;
}
static int static int
compute_code_flags(struct compiler *c) compute_code_flags(struct compiler *c)
{ {
PySTEntryObject *ste = c->u->u_ste; PySTEntryObject *ste = SYMTABLE_ENTRY(c);
int flags = 0; int flags = 0;
if (_PyST_IsFunctionLike(c->u->u_ste)) { if (_PyST_IsFunctionLike(ste)) {
flags |= CO_NEWLOCALS | CO_OPTIMIZED; flags |= CO_NEWLOCALS | CO_OPTIMIZED;
if (ste->ste_nested) if (ste->ste_nested)
flags |= CO_NESTED; flags |= CO_NESTED;
if (ste->ste_generator && !ste->ste_coroutine) if (ste->ste_generator && !ste->ste_coroutine)
flags |= CO_GENERATOR; flags |= CO_GENERATOR;
if (!ste->ste_generator && ste->ste_coroutine)
flags |= CO_COROUTINE;
if (ste->ste_generator && ste->ste_coroutine) if (ste->ste_generator && ste->ste_coroutine)
flags |= CO_ASYNC_GENERATOR; flags |= CO_ASYNC_GENERATOR;
if (ste->ste_varargs) if (ste->ste_varargs)
@ -7506,15 +7526,14 @@ compute_code_flags(struct compiler *c)
flags |= CO_VARKEYWORDS; flags |= CO_VARKEYWORDS;
} }
/* (Only) inherit compilerflags in PyCF_MASK */ if (ste->ste_coroutine && !ste->ste_generator) {
flags |= (c->c_flags.cf_flags & PyCF_MASK); assert (IS_TOP_LEVEL_AWAIT(c) || _PyST_IsFunctionLike(ste));
if ((IS_TOP_LEVEL_AWAIT(c)) &&
ste->ste_coroutine &&
!ste->ste_generator) {
flags |= CO_COROUTINE; flags |= CO_COROUTINE;
} }
/* (Only) inherit compilerflags in PyCF_MASK */
flags |= (c->c_flags.cf_flags & PyCF_MASK);
return flags; return flags;
} }