mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	gh-121404: remove some accesses to compiler internals from codegen functions (#121538)
This commit is contained in:
		
							parent
							
								
									af9f6de6ea
								
							
						
					
					
						commit
						0177a34335
					
				
					 1 changed files with 120 additions and 101 deletions
				
			
		
							
								
								
									
										221
									
								
								Python/compile.c
									
										
									
									
									
								
							
							
						
						
									
										221
									
								
								Python/compile.c
									
										
									
									
									
								
							|  | @ -71,11 +71,24 @@ | |||
|         ((C)->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \ | ||||
|         && ((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 struct _PyCfgBuilder cfg_builder; | ||||
| 
 | ||||
| struct compiler; | ||||
| 
 | ||||
| static PyObject *compiler_maybe_mangle(struct compiler *c, PyObject *name); | ||||
| 
 | ||||
| #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[] = { | ||||
|     [Py_LT] = COMPARISON_LESS_THAN, | ||||
|     [Py_LE] = COMPARISON_LESS_THAN | COMPARISON_EQUALS, | ||||
|  | @ -258,8 +265,6 @@ struct compiler { | |||
|                                   */ | ||||
| }; | ||||
| 
 | ||||
| #define INSTR_SEQUENCE(C) ((C)->u->u_instr_sequence) | ||||
| 
 | ||||
| 
 | ||||
| typedef struct { | ||||
|     // 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); | ||||
| static int compiler_try_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( | ||||
|                                       struct compiler *c, location loc, | ||||
|  | @ -558,8 +562,8 @@ compiler_unit_free(struct compiler_unit *u) | |||
|     PyMem_Free(u); | ||||
| } | ||||
| 
 | ||||
| static struct compiler_unit * | ||||
| get_class_compiler_unit(struct compiler *c) | ||||
| static int | ||||
| compiler_add_static_attribute_to_class(struct compiler *c, PyObject *attr) | ||||
| { | ||||
|     Py_ssize_t stack_size = PyList_GET_SIZE(c->c_stack); | ||||
|     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); | ||||
|         assert(u); | ||||
|         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 | ||||
|  | @ -863,38 +869,37 @@ merge_consts_recursive(PyObject *const_cache, PyObject *o) | |||
| } | ||||
| 
 | ||||
| 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(const_cache, o); | ||||
|     PyObject *key = merge_consts_recursive(c->c_const_cache, o); | ||||
|     if (key == NULL) { | ||||
|         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); | ||||
|     return arg; | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|         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 | ||||
| compiler_addop_o(struct compiler_unit *u, location loc, | ||||
| compiler_addop_o(struct compiler *c, location loc, | ||||
|                  int opcode, PyObject *dict, PyObject *o) | ||||
| { | ||||
|     Py_ssize_t arg = dict_add_o(dict, o); | ||||
|     if (arg < 0) { | ||||
|         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 | ||||
|  | @ -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_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. */ | ||||
| #define ADDOP_LOAD_CONST_NEW(C, LOC, O) { \ | ||||
|  | @ -992,7 +997,7 @@ codegen_addop_j(instr_sequence *seq, location loc, | |||
|     if (__new_const == NULL) { \ | ||||
|         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); \ | ||||
|         return ERROR; \ | ||||
|     } \ | ||||
|  | @ -1001,7 +1006,7 @@ codegen_addop_j(instr_sequence *seq, location loc, | |||
| 
 | ||||
| #define ADDOP_N(C, LOC, OP, O, TYPE) { \ | ||||
|     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)); \ | ||||
|         return ERROR; \ | ||||
|     } \ | ||||
|  | @ -1514,7 +1519,7 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts) | |||
|     /* If from __future__ import annotations is active,
 | ||||
|      * every annotated class and module should have __annotations__. | ||||
|      * 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); | ||||
|     } | ||||
|     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
 | ||||
|     // collect the annotations in a separate pass and generate an
 | ||||
|     // __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) { | ||||
| 
 | ||||
|         // 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
 | ||||
|         // for attributes, subscripts, or parenthesized names). However, the
 | ||||
|         // 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); | ||||
|         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, | ||||
|                                              c->u->u_ste->ste_annotation_block->ste_name) == -1) { | ||||
|                                              ste->ste_annotation_block->ste_name) == -1) { | ||||
|             Py_DECREF(deferred_anno); | ||||
|             return ERROR; | ||||
|         } | ||||
|  | @ -1642,13 +1648,8 @@ compiler_mod(struct compiler *c, mod_ty mod) | |||
|     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 | ||||
| get_ref_type(struct compiler *c, PyObject *name) | ||||
| compiler_get_ref_type(struct compiler *c, PyObject *name) | ||||
| { | ||||
|     int scope; | ||||
|     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__"))) { | ||||
|         return CELL; | ||||
|     } | ||||
|     scope = _PyST_GetScope(c->u->u_ste, name); | ||||
|     PySTEntryObject *ste = SYMTABLE_ENTRY(c); | ||||
|     scope = _PyST_GetScope(ste, name); | ||||
|     if (scope == 0) { | ||||
|         PyErr_Format(PyExc_SystemError, | ||||
|                      "_PyST_GetScope(name=%R) failed: " | ||||
|                      "unknown scope in unit %S (%R); " | ||||
|                      "symbols: %R; locals: %R; globals: %R", | ||||
|                      name, | ||||
|                      c->u->u_metadata.u_name, c->u->u_ste->ste_id, | ||||
|                      c->u->u_ste->ste_symbols, c->u->u_metadata.u_varnames, c->u->u_metadata.u_names); | ||||
|                      c->u->u_metadata.u_name, ste->ste_id, | ||||
|                      ste->ste_symbols, c->u->u_metadata.u_varnames, c->u->u_metadata.u_names); | ||||
|         return ERROR; | ||||
|     } | ||||
|     return scope; | ||||
|  | @ -1698,7 +1700,7 @@ compiler_make_closure(struct compiler *c, location loc, | |||
|                class.  It should be handled by the closure, as | ||||
|                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) { | ||||
|                 return ERROR; | ||||
|             } | ||||
|  | @ -1858,7 +1860,7 @@ compiler_argannotation(struct compiler *c, identifier id, | |||
|     ADDOP_LOAD_CONST(c, loc, mangled); | ||||
|     Py_DECREF(mangled); | ||||
| 
 | ||||
|     if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) { | ||||
|     if (FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) { | ||||
|         VISIT(c, annexpr, annotation); | ||||
|     } | ||||
|     else { | ||||
|  | @ -1940,7 +1942,7 @@ compiler_annotations(struct compiler *c, location loc, | |||
|     Py_ssize_t annotations_len = 0; | ||||
| 
 | ||||
|     PySTEntryObject *ste; | ||||
|     if (_PySymtable_LookupOptional(c->c_st, args, &ste) < 0) { | ||||
|     if (_PySymtable_LookupOptional(SYMTABLE(c), args, &ste) < 0) { | ||||
|         return ERROR; | ||||
|     } | ||||
|     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; | ||||
|         } | ||||
|     } | ||||
|     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); | ||||
|         compiler_exit_scope(c); | ||||
|         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); | ||||
|     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) { | ||||
|         /* wrap_in_stopiteration_handler will push a block, so we need to account for that */ | ||||
|         RETURN_IF_ERROR( | ||||
|  | @ -2463,14 +2466,14 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno) | |||
|             return ERROR; | ||||
|         } | ||||
|     } | ||||
|     if (c->u->u_ste->ste_needs_classdict) { | ||||
|     if (SYMTABLE_ENTRY(c)->ste_needs_classdict) { | ||||
|         ADDOP(c, loc, LOAD_LOCALS); | ||||
| 
 | ||||
|         // 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
 | ||||
|         // that by default.
 | ||||
|         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) { | ||||
|             compiler_exit_scope(c); | ||||
|             return ERROR; | ||||
|  | @ -2495,7 +2498,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno) | |||
|     } | ||||
|     /* The following code is artificial */ | ||||
|     /* Set __classdictcell__ if necessary */ | ||||
|     if (c->u->u_ste->ste_needs_classdict) { | ||||
|     if (SYMTABLE_ENTRY(c)->ste_needs_classdict) { | ||||
|         /* Store __classdictcell__ into class namespace */ | ||||
|         int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__classdict__)); | ||||
|         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 */ | ||||
|     if (c->u->u_ste->ste_needs_class_closure) { | ||||
|     if (SYMTABLE_ENTRY(c)->ste_needs_class_closure) { | ||||
|         /* Store __classcell__ into class namespace & return it */ | ||||
|         int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__)); | ||||
|         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)); | ||||
|     /* Make None the first constant, so the evaluate function can't have a
 | ||||
|         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); | ||||
|     ADDOP_IN_SCOPE(c, loc, RETURN_VALUE); | ||||
|     PyCodeObject *co = optimize_and_assemble(c, 0); | ||||
|  | @ -2705,7 +2708,7 @@ compiler_typealias(struct compiler *c, stmt_ty s) | |||
|         } | ||||
|         Py_DECREF(type_params_name); | ||||
|         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)); | ||||
|     } | ||||
|  | @ -2972,13 +2975,13 @@ compiler_lambda(struct compiler *c, expr_ty e) | |||
| 
 | ||||
|     /* Make None the first constant, so the lambda can't have a
 | ||||
|        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_posonlyargcount = asdl_seq_LEN(args->posonlyargs); | ||||
|     c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); | ||||
|     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); | ||||
|     } | ||||
|     else { | ||||
|  | @ -3154,12 +3157,12 @@ compiler_return(struct compiler *c, stmt_ty s) | |||
|     location loc = LOC(s); | ||||
|     int preserve_tos = ((s->v.Return.value != NULL) && | ||||
|                         (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"); | ||||
|     } | ||||
|     if (s->v.Return.value != NULL && | ||||
|         c->u->u_ste->ste_coroutine && c->u->u_ste->ste_generator) | ||||
|     { | ||||
|     if (s->v.Return.value != NULL && ste->ste_coroutine && ste->ste_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 | ||||
| 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, YIELD_VALUE, 0); | ||||
|  | @ -4143,7 +4147,7 @@ compiler_nameop(struct compiler *c, location loc, | |||
| 
 | ||||
|     op = 0; | ||||
|     optype = OP_NAME; | ||||
|     scope = _PyST_GetScope(c->u->u_ste, mangled); | ||||
|     scope = _PyST_GetScope(SYMTABLE_ENTRY(c), mangled); | ||||
|     switch (scope) { | ||||
|     case FREE: | ||||
|         dict = c->u->u_metadata.u_freevars; | ||||
|  | @ -4154,7 +4158,7 @@ compiler_nameop(struct compiler *c, location loc, | |||
|         optype = OP_DEREF; | ||||
|         break; | ||||
|     case LOCAL: | ||||
|         if (_PyST_IsFunctionLike(c->u->u_ste)) { | ||||
|         if (_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) { | ||||
|             optype = OP_FAST; | ||||
|         } | ||||
|         else { | ||||
|  | @ -4170,7 +4174,7 @@ compiler_nameop(struct compiler *c, location loc, | |||
|         } | ||||
|         break; | ||||
|     case GLOBAL_IMPLICIT: | ||||
|         if (_PyST_IsFunctionLike(c->u->u_ste)) | ||||
|         if (_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) | ||||
|             optype = OP_GLOBAL; | ||||
|         break; | ||||
|     case GLOBAL_EXPLICIT: | ||||
|  | @ -4188,17 +4192,17 @@ compiler_nameop(struct compiler *c, location loc, | |||
|     case OP_DEREF: | ||||
|         switch (ctx) { | ||||
|         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; | ||||
|                 // First load the locals
 | ||||
|                 if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) { | ||||
|                     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; | ||||
|                 // 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) { | ||||
|                     goto error; | ||||
|                 } | ||||
|  | @ -4222,10 +4226,10 @@ compiler_nameop(struct compiler *c, location loc, | |||
|     case OP_GLOBAL: | ||||
|         switch (ctx) { | ||||
|         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; | ||||
|                 // 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) { | ||||
|                     goto error; | ||||
|                 } | ||||
|  | @ -4240,7 +4244,7 @@ compiler_nameop(struct compiler *c, location loc, | |||
|     case OP_NAME: | ||||
|         switch (ctx) { | ||||
|         case Load: | ||||
|             op = (c->u->u_ste->ste_type == ClassBlock | ||||
|             op = (SYMTABLE_ENTRY(c)->ste_type == ClassBlock | ||||
|                     && c->u->u_in_inlined_comp) | ||||
|                 ? LOAD_GLOBAL | ||||
|                 : LOAD_NAME; | ||||
|  | @ -4745,7 +4749,7 @@ is_import_originated(struct compiler *c, expr_ty e) | |||
|         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; | ||||
| } | ||||
| 
 | ||||
|  | @ -4764,11 +4768,11 @@ can_optimize_super_call(struct compiler *c, expr_ty attr) | |||
| 
 | ||||
|     PyObject *super_name = e->v.Call.func->v.Name.id; | ||||
|     // 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) { | ||||
|         return 0; | ||||
|     } | ||||
|     scope = _PyST_GetScope(c->c_st->st_top, super_name); | ||||
|     scope = _PyST_GetScope(SYMTABLE(c)->st_top, super_name); | ||||
|     if (scope != 0) { | ||||
|         return 0; | ||||
|     } | ||||
|  | @ -4796,7 +4800,7 @@ can_optimize_super_call(struct compiler *c, expr_ty attr) | |||
|         return 0; | ||||
|     } | ||||
|     // __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 0; | ||||
|  | @ -4818,7 +4822,7 @@ load_args_for_super(struct compiler *c, expr_ty e) { | |||
| 
 | ||||
|     // load __class__ cell
 | ||||
|     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)); | ||||
| 
 | ||||
|     // load self (first argument)
 | ||||
|  | @ -5490,7 +5494,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc, | |||
|                                  PySTEntryObject *entry, | ||||
|                                  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++; | ||||
|     // iterate over names bound in the comprehension and ensure we isolate
 | ||||
|     // them from the outer scope as needed
 | ||||
|  | @ -5500,7 +5504,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc, | |||
|         assert(PyLong_Check(v)); | ||||
|         long symbol = PyLong_AS_LONG(v); | ||||
|         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 (PyErr_Occurred()) { | ||||
|                 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
 | ||||
|             // comprehension
 | ||||
|             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); | ||||
|                 return ERROR; | ||||
|             } | ||||
|  | @ -5542,7 +5546,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc, | |||
|         // locals handling for names bound in comprehension (DEF_LOCAL |
 | ||||
|         // DEF_NONLOCAL occurs in assignment expression to nonlocal)
 | ||||
|         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
 | ||||
|                 PyObject *orig; | ||||
|                 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; | ||||
|     if (state.temp_symbols) { | ||||
|         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; | ||||
|             } | ||||
|         } | ||||
|  | @ -5713,7 +5717,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, | |||
|     comprehension_ty outermost; | ||||
|     int scope_type = c->u->u_scope_type; | ||||
|     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) { | ||||
|         goto error; | ||||
|     } | ||||
|  | @ -6150,7 +6154,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e) | |||
|     case DictComp_kind: | ||||
|         return compiler_dictcomp(c, e); | ||||
|     case Yield_kind: | ||||
|         if (!_PyST_IsFunctionLike(c->u->u_ste)) { | ||||
|         if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) { | ||||
|             return compiler_error(c, loc, "'yield' outside function"); | ||||
|         } | ||||
|         if (e->v.Yield.value) { | ||||
|  | @ -6162,7 +6166,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e) | |||
|         ADDOP_YIELD(c, loc); | ||||
|         break; | ||||
|     case YieldFrom_kind: | ||||
|         if (!_PyST_IsFunctionLike(c->u->u_ste)) { | ||||
|         if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) { | ||||
|             return compiler_error(c, loc, "'yield' outside 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; | ||||
|     case Await_kind: | ||||
|         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"); | ||||
|             } | ||||
| 
 | ||||
|  | @ -6215,13 +6219,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e) | |||
|         if (e->v.Attribute.value->kind == Name_kind && | ||||
|             _PyUnicode_EqualToASCIIString(e->v.Attribute.value->v.Name.id, "self")) | ||||
|         { | ||||
|             struct compiler_unit *class_u = get_class_compiler_unit(c); | ||||
|             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)); | ||||
|             } | ||||
|             RETURN_IF_ERROR(compiler_add_static_attribute_to_class(c, e->v.Attribute.attr)); | ||||
|         } | ||||
|         VISIT(c, expr, e->v.Attribute.value); | ||||
|         loc = LOC(e); | ||||
|  | @ -6368,7 +6366,7 @@ check_annotation(struct compiler *c, stmt_ty s) | |||
| { | ||||
|     /* Annotations of complex targets does not produce anything
 | ||||
|        under annotations future */ | ||||
|     if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) { | ||||
|     if (FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) { | ||||
|         return SUCCESS; | ||||
|     } | ||||
| 
 | ||||
|  | @ -6415,7 +6413,7 @@ compiler_annassign(struct compiler *c, stmt_ty s) | |||
| { | ||||
|     location loc = LOC(s); | ||||
|     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; | ||||
| 
 | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| compute_code_flags(struct compiler *c) | ||||
| { | ||||
|     PySTEntryObject *ste = c->u->u_ste; | ||||
|     PySTEntryObject *ste = SYMTABLE_ENTRY(c); | ||||
|     int flags = 0; | ||||
|     if (_PyST_IsFunctionLike(c->u->u_ste)) { | ||||
|     if (_PyST_IsFunctionLike(ste)) { | ||||
|         flags |= CO_NEWLOCALS | CO_OPTIMIZED; | ||||
|         if (ste->ste_nested) | ||||
|             flags |= CO_NESTED; | ||||
|         if (ste->ste_generator && !ste->ste_coroutine) | ||||
|             flags |= CO_GENERATOR; | ||||
|         if (!ste->ste_generator && ste->ste_coroutine) | ||||
|             flags |= CO_COROUTINE; | ||||
|         if (ste->ste_generator && ste->ste_coroutine) | ||||
|             flags |= CO_ASYNC_GENERATOR; | ||||
|         if (ste->ste_varargs) | ||||
|  | @ -7506,15 +7526,14 @@ compute_code_flags(struct compiler *c) | |||
|             flags |= CO_VARKEYWORDS; | ||||
|     } | ||||
| 
 | ||||
|     /* (Only) inherit compilerflags in PyCF_MASK */ | ||||
|     flags |= (c->c_flags.cf_flags & PyCF_MASK); | ||||
| 
 | ||||
|     if ((IS_TOP_LEVEL_AWAIT(c)) && | ||||
|          ste->ste_coroutine && | ||||
|          !ste->ste_generator) { | ||||
|     if (ste->ste_coroutine && !ste->ste_generator) { | ||||
|         assert (IS_TOP_LEVEL_AWAIT(c) || _PyST_IsFunctionLike(ste)); | ||||
|         flags |= CO_COROUTINE; | ||||
|     } | ||||
| 
 | ||||
|     /* (Only) inherit compilerflags in PyCF_MASK */ | ||||
|     flags |= (c->c_flags.cf_flags & PyCF_MASK); | ||||
| 
 | ||||
|     return flags; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Irit Katriel
						Irit Katriel