Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,26 @@ PyAPI_FUNC(void)
_PyObject_DebugTypeStats(FILE *out);
#endif /* ifndef Py_LIMITED_API */

#ifndef Py_LIMITED_API
typedef struct _Py_StaticVar {
struct _Py_StaticVar *next;
PyObject *obj;
} _Py_StaticVar;


PyAPI_FUNC(int) _PyStaticVar_Set(_Py_StaticVar *var, PyObject *obj);

#define _Py_STATICVAR(var) \
static _Py_StaticVar var = {.next = NULL, .obj = NULL}

/* Initialized the static variable 'var' once with the expression 'expr'.
Return 0 on success, return -1 on failure. */
#define _PY_STATICVAR_INIT(var, expr) \
((var)->obj == NULL ? _PyStaticVar_Set((var), (expr)) : 0)

PyAPI_DATA(_Py_StaticVar*) _Py_static_variables;
#endif

#ifdef __cplusplus
}
#endif
Expand Down
13 changes: 6 additions & 7 deletions Modules/arraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2124,20 +2124,19 @@ array_array___reduce_ex__(arrayobject *self, PyObject *value)
PyObject *array_str;
int typecode = self->ob_descr->typecode;
int mformat_code;
static PyObject *array_reconstructor = NULL;
_Py_STATICVAR(array_reconstructor);
long protocol;
_Py_IDENTIFIER(_array_reconstructor);
_Py_IDENTIFIER(__dict__);

if (array_reconstructor == NULL) {
if (array_reconstructor.obj == NULL) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_PY_STATICVAR_INIT() can be used if extract the code for getting array._array_reconstructor into a separate function.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in PR #780.

PyObject *array_module = PyImport_ImportModule("array");
if (array_module == NULL)
return NULL;
array_reconstructor = _PyObject_GetAttrId(
array_module,
&PyId__array_reconstructor);
PyObject *meth = _PyObject_GetAttrId(array_module,
&PyId__array_reconstructor);
Py_DECREF(array_module);
if (array_reconstructor == NULL)
if (_PyStaticVar_Set(&array_reconstructor, meth))
return NULL;
}

Expand Down Expand Up @@ -2191,7 +2190,7 @@ array_array___reduce_ex__(arrayobject *self, PyObject *value)
return NULL;
}
result = Py_BuildValue(
"O(OCiN)O", array_reconstructor, Py_TYPE(self), typecode,
"O(OCiN)O", array_reconstructor.obj, Py_TYPE(self), typecode,
mformat_code, array_str, dict);
Py_DECREF(dict);
return result;
Expand Down
33 changes: 33 additions & 0 deletions Objects/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -2129,3 +2129,36 @@ _Py_Dealloc(PyObject *op)
#ifdef __cplusplus
}
#endif


_Py_StaticVar* _Py_static_variables = NULL;

int
_PyStaticVar_Set(_Py_StaticVar *var, PyObject *obj)
{
assert(var->next == NULL);
assert(var->obj == NULL);

if (obj == NULL) {
return -1;
}

var->obj = obj;
var->next = _Py_static_variables;
_Py_static_variables = var;
return 0;
}

void
_PyStaticVar_Fini(void)
{
_Py_StaticVar *next, *var;

for (var = _Py_static_variables; var != NULL; var = next) {
next = var->next;

Py_CLEAR(var->obj);
var->next = NULL;
}
_Py_static_variables = NULL;
}
13 changes: 6 additions & 7 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -4419,15 +4419,14 @@ static PyObject *
object___reduce_ex___impl(PyObject *self, int protocol)
/*[clinic end generated code: output=2e157766f6b50094 input=8dd6a9602a12749e]*/
{
static PyObject *objreduce;
_Py_STATICVAR(objreduce);
PyObject *reduce, *res;
_Py_IDENTIFIER(__reduce__);

if (objreduce == NULL) {
objreduce = _PyDict_GetItemId(PyBaseObject_Type.tp_dict,
&PyId___reduce__);
if (objreduce == NULL)
return NULL;
if (_PY_STATICVAR_INIT(&objreduce,
_PyDict_GetItemId(PyBaseObject_Type.tp_dict,
&PyId___reduce__))) {
return NULL;
}

reduce = _PyObject_GetAttrId(self, &PyId___reduce__);
Expand All @@ -4443,7 +4442,7 @@ object___reduce_ex___impl(PyObject *self, int protocol)
Py_DECREF(reduce);
return NULL;
}
override = (clsreduce != objreduce);
override = (clsreduce != objreduce.obj);
Py_DECREF(clsreduce);
if (override) {
res = _PyObject_CallNoArg(reduce);
Expand Down
45 changes: 21 additions & 24 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ static int compiler_async_comprehension_generator(
expr_ty elt, expr_ty val, int type);

static PyCodeObject *assemble(struct compiler *, int addNone);
static PyObject *__doc__;
_Py_STATICVAR(__doc__);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_Py_IDENTIFIER() can be used.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I know, it was more to show how the API can be used.


#define CAPSULE_NAME "compile.c compiler unit"

Expand Down Expand Up @@ -306,10 +306,8 @@ PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags,
PyCompilerFlags local_flags;
int merged;

if (!__doc__) {
__doc__ = PyUnicode_InternFromString("__doc__");
if (!__doc__)
return NULL;
if (_PY_STATICVAR_INIT(&__doc__, PyUnicode_InternFromString("__doc__"))) {
return 0;
}

if (!compiler_init(&c))
Expand Down Expand Up @@ -1441,7 +1439,7 @@ compiler_body(struct compiler *c, asdl_seq *stmts, string docstring)
/* if not -OO mode, set docstring */
if (c->c_optimize < 2 && docstring) {
ADDOP_O(c, LOAD_CONST, docstring, consts);
ADDOP_NAME(c, STORE_NAME, __doc__, names);
ADDOP_NAME(c, STORE_NAME, __doc__.obj, names);
}
VISIT_SEQ(c, stmt, stmts);
return 1;
Expand All @@ -1452,14 +1450,14 @@ compiler_mod(struct compiler *c, mod_ty mod)
{
PyCodeObject *co;
int addNone = 1;
static PyObject *module;
if (!module) {
module = PyUnicode_InternFromString("<module>");
if (!module)
return NULL;
_Py_STATICVAR(module);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_Py_static_string() can be used.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto


if (_PY_STATICVAR_INIT(&module, PyUnicode_InternFromString("<module>"))) {
return 0;
}

/* Use 0 for firstlineno initially, will fixup in assemble(). */
if (!compiler_enter_scope(c, module, COMPILER_SCOPE_MODULE, mod, 0))
if (!compiler_enter_scope(c, module.obj, COMPILER_SCOPE_MODULE, mod, 0))
return NULL;
switch (mod->kind) {
case Module_kind:
Expand Down Expand Up @@ -2639,12 +2637,10 @@ compiler_from_import(struct compiler *c, stmt_ty s)

PyObject *names = PyTuple_New(n);
PyObject *level;
static PyObject *empty_string;
_Py_STATICVAR(empty_string);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Py_static_string() can be used.


if (!empty_string) {
empty_string = PyUnicode_FromString("");
if (!empty_string)
return 0;
if (_PY_STATICVAR_INIT(&empty_string, PyUnicode_FromString(""))) {
return 0;
}

if (!names)
Expand Down Expand Up @@ -2679,7 +2675,7 @@ compiler_from_import(struct compiler *c, stmt_ty s)
ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names);
}
else {
ADDOP_NAME(c, IMPORT_NAME, empty_string, names);
ADDOP_NAME(c, IMPORT_NAME, empty_string.obj, names);
}
for (i = 0; i < n; i++) {
alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i);
Expand Down Expand Up @@ -2709,17 +2705,18 @@ compiler_from_import(struct compiler *c, stmt_ty s)
static int
compiler_assert(struct compiler *c, stmt_ty s)
{
static PyObject *assertion_error = NULL;
_Py_STATICVAR(assertion_error);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_Py_IDENTIFIER() can be used.

basicblock *end;
PyObject* msg;

if (c->c_optimize)
return 1;
if (assertion_error == NULL) {
assertion_error = PyUnicode_InternFromString("AssertionError");
if (assertion_error == NULL)
return 0;

if (_PY_STATICVAR_INIT(&assertion_error,
PyUnicode_InternFromString("AssertionError"))) {
return 0;
}

if (s->v.Assert.test->kind == Tuple_kind &&
asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) {
msg = PyUnicode_FromString("assertion is always true, "
Expand All @@ -2739,7 +2736,7 @@ compiler_assert(struct compiler *c, stmt_ty s)
if (end == NULL)
return 0;
ADDOP_JABS(c, POP_JUMP_IF_TRUE, end);
ADDOP_O(c, LOAD_GLOBAL, assertion_error, names);
ADDOP_O(c, LOAD_GLOBAL, assertion_error.obj, names);
if (s->v.Assert.msg) {
VISIT(c, expr, s->v.Assert.msg);
ADDOP_I(c, CALL_FUNCTION, 1);
Expand Down
38 changes: 19 additions & 19 deletions Python/import.c
Original file line number Diff line number Diff line change
Expand Up @@ -1721,33 +1721,33 @@ PyImport_ReloadModule(PyObject *m)
PyObject *
PyImport_Import(PyObject *module_name)
{
static PyObject *silly_list = NULL;
static PyObject *builtins_str = NULL;
static PyObject *import_str = NULL;
_Py_STATICVAR(empty_list);
_Py_STATICVAR(builtins_str);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_Py_IDENTIFIER() can be used.

_Py_STATICVAR(import_str);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_Py_IDENTIFIER() can be used.

PyObject *globals = NULL;
PyObject *import = NULL;
PyObject *builtins = NULL;
PyObject *modules = NULL;
PyObject *r = NULL;

/* Initialize constant string objects */
if (silly_list == NULL) {
import_str = PyUnicode_InternFromString("__import__");
if (import_str == NULL)
return NULL;
builtins_str = PyUnicode_InternFromString("__builtins__");
if (builtins_str == NULL)
return NULL;
silly_list = PyList_New(0);
if (silly_list == NULL)
return NULL;
if (_PY_STATICVAR_INIT(&empty_list, PyList_New(0))) {
return NULL;
}
if (_PY_STATICVAR_INIT(&builtins_str,
PyUnicode_InternFromString("__builtins__"))) {
return NULL;
}
if (_PY_STATICVAR_INIT(&import_str,
PyUnicode_InternFromString("__import__"))) {
return NULL;
}

/* Get the builtins from current globals */
globals = PyEval_GetGlobals();
if (globals != NULL) {
Py_INCREF(globals);
builtins = PyObject_GetItem(globals, builtins_str);
builtins = PyObject_GetItem(globals, builtins_str.obj);
if (builtins == NULL)
goto err;
}
Expand All @@ -1757,27 +1757,27 @@ PyImport_Import(PyObject *module_name)
NULL, NULL, NULL, 0);
if (builtins == NULL)
return NULL;
globals = Py_BuildValue("{OO}", builtins_str, builtins);
globals = Py_BuildValue("{OO}", builtins_str.obj, builtins);
if (globals == NULL)
goto err;
}

/* Get the __import__ function from the builtins */
if (PyDict_Check(builtins)) {
import = PyObject_GetItem(builtins, import_str);
import = PyObject_GetItem(builtins, import_str.obj);
if (import == NULL)
PyErr_SetObject(PyExc_KeyError, import_str);
PyErr_SetObject(PyExc_KeyError, import_str.obj);
}
else
import = PyObject_GetAttr(builtins, import_str);
import = PyObject_GetAttr(builtins, import_str.obj);
if (import == NULL)
goto err;

/* Call the __import__ function with the proper argument list
Always use absolute import here.
Calling for side-effect of import. */
r = PyObject_CallFunction(import, "OOOOi", module_name, globals,
globals, silly_list, 0, NULL);
globals, empty_list.obj, 0, NULL);
if (r == NULL)
goto err;
Py_DECREF(r);
Expand Down
2 changes: 2 additions & 0 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ static void call_ll_exitfuncs(void);
extern int _PyUnicode_Init(void);
extern int _PyStructSequence_Init(void);
extern void _PyUnicode_Fini(void);
extern void _PyStaticVar_Fini(void);
extern int _PyLong_Init(void);
extern void PyLong_Fini(void);
extern int _PyFaulthandler_Init(void);
Expand Down Expand Up @@ -699,6 +700,7 @@ Py_FinalizeEx(void)

/* Cleanup Unicode implementation */
_PyUnicode_Fini();
_PyStaticVar_Fini();

/* reset file system default encoding */
if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
Expand Down
10 changes: 4 additions & 6 deletions Python/sysmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ sys_displayhook(PyObject *self, PyObject *o)
PyInterpreterState *interp = PyThreadState_GET()->interp;
PyObject *modules = interp->modules;
PyObject *builtins;
static PyObject *newline = NULL;
_Py_STATICVAR(newline);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Py_static_string() can be used.

int err;

builtins = _PyDict_GetItemId(modules, &PyId_builtins);
Expand Down Expand Up @@ -197,12 +197,10 @@ sys_displayhook(PyObject *self, PyObject *o)
return NULL;
}
}
if (newline == NULL) {
newline = PyUnicode_FromString("\n");
if (newline == NULL)
return NULL;
if (_PY_STATICVAR_INIT(&newline, PyUnicode_FromString("\n"))) {
return NULL;
}
if (PyFile_WriteObject(newline, outf, Py_PRINT_RAW) != 0)
if (PyFile_WriteObject(newline.obj, outf, Py_PRINT_RAW) != 0)
return NULL;
if (_PyObject_SetAttrId(builtins, &PyId__, o) != 0)
return NULL;
Expand Down