bpo-34301: Add _PyInterpreterState_Get() helper function (GH-8592)

sys_setcheckinterval() now uses a local variable to parse arguments,
before writing into interp->check_interval.
diff --git a/Python/_warnings.c b/Python/_warnings.c
index d6614b2..2229206 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -78,7 +78,7 @@
            gone, then we can't even use PyImport_GetModule without triggering
            an interpreter abort.
         */
-        if (!PyThreadState_GET()->interp->modules) {
+        if (!_PyInterpreterState_GET_UNSAFE()->modules) {
             return NULL;
         }
         warnings_module = PyImport_GetModule(warnings_str);
@@ -686,7 +686,7 @@
     }
 
     if (f == NULL) {
-        globals = PyThreadState_Get()->interp->sysdict;
+        globals = _PyInterpreterState_GET_UNSAFE()->sysdict;
         *filename = PyUnicode_FromString("sys");
         *lineno = 1;
     }
diff --git a/Python/ceval.c b/Python/ceval.c
index 46da295..f3a74b0 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -532,8 +532,8 @@
 PyObject *
 PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
 {
-    PyThreadState *tstate = PyThreadState_GET();
-    return tstate->interp->eval_frame(f, throwflag);
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
+    return interp->eval_frame(f, throwflag);
 }
 
 PyObject* _Py_HOT_FUNCTION
@@ -4435,7 +4435,7 @@
 {
     PyFrameObject *current_frame = PyEval_GetFrame();
     if (current_frame == NULL)
-        return PyThreadState_GET()->interp->builtins;
+        return _PyInterpreterState_GET_UNSAFE()->builtins;
     else
         return current_frame->f_builtins;
 }
@@ -4769,7 +4769,7 @@
     }
 
     /* Fast path for not overloaded __import__. */
-    if (import_func == PyThreadState_GET()->interp->import_func) {
+    if (import_func == _PyInterpreterState_GET_UNSAFE()->import_func) {
         int ilevel = _PyLong_AsInt(level);
         if (ilevel == -1 && PyErr_Occurred()) {
             return NULL;
@@ -5136,7 +5136,7 @@
 Py_ssize_t
 _PyEval_RequestCodeExtraIndex(freefunc free)
 {
-    PyInterpreterState *interp = PyThreadState_Get()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
     Py_ssize_t new_index;
 
     if (interp->co_extra_user_count == MAX_CO_EXTRA_USERS - 1) {
diff --git a/Python/codecs.c b/Python/codecs.c
index eb3cd35..4062429 100644
--- a/Python/codecs.c
+++ b/Python/codecs.c
@@ -32,7 +32,7 @@
 
 int PyCodec_Register(PyObject *search_function)
 {
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
         goto onError;
     if (search_function == NULL) {
@@ -99,7 +99,6 @@
 
 PyObject *_PyCodec_Lookup(const char *encoding)
 {
-    PyInterpreterState *interp;
     PyObject *result, *args = NULL, *v;
     Py_ssize_t i, len;
 
@@ -108,7 +107,7 @@
         goto onError;
     }
 
-    interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
         goto onError;
 
@@ -187,11 +186,10 @@
 
 int _PyCodec_Forget(const char *encoding)
 {
-    PyInterpreterState *interp;
     PyObject *v;
     int result;
 
-    interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     if (interp->codec_search_path == NULL) {
         return -1;
     }
@@ -624,7 +622,7 @@
    Return 0 on success, -1 on error */
 int PyCodec_RegisterError(const char *name, PyObject *error)
 {
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
         return -1;
     if (!PyCallable_Check(error)) {
@@ -642,7 +640,7 @@
 {
     PyObject *handler = NULL;
 
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
         return NULL;
 
@@ -1494,7 +1492,7 @@
         }
     };
 
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     PyObject *mod;
     unsigned i;
 
diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c
index f271193..73ae26d 100644
--- a/Python/dynload_shlib.c
+++ b/Python/dynload_shlib.c
@@ -91,7 +91,7 @@
         }
     }
 
-    dlopenflags = PyThreadState_GET()->interp->dlopenflags;
+    dlopenflags = _PyInterpreterState_Get()->dlopenflags;
 
     handle = dlopen(pathname, dlopenflags);
 
diff --git a/Python/import.c b/Python/import.c
index 71d5ea1..319b661 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -304,7 +304,7 @@
 PyObject *
 PyImport_GetModuleDict(void)
 {
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
     if (interp->modules == NULL) {
         Py_FatalError("PyImport_GetModuleDict: no module dictionary!");
     }
@@ -397,7 +397,7 @@
 {
     Py_ssize_t pos;
     PyObject *key, *value, *dict;
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     PyObject *modules = PyImport_GetModuleDict();
     PyObject *weaklist = NULL;
     const char * const *p;
@@ -592,7 +592,7 @@
 PyImport_GetMagicNumber(void)
 {
     long res;
-    PyInterpreterState *interp = PyThreadState_Get()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     PyObject *external, *pyc_magic;
 
     external = PyObject_GetAttrString(interp->importlib, "_bootstrap_external");
@@ -892,7 +892,7 @@
             goto error;
     }
     else if (cpathobj != NULL) {
-        PyInterpreterState *interp = PyThreadState_GET()->interp;
+        PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
         _Py_IDENTIFIER(_get_sourcefile);
 
         if (interp == NULL) {
@@ -972,7 +972,7 @@
                               PyObject *cpathname)
 {
     PyObject *d, *external, *res;
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
     _Py_IDENTIFIER(_fix_up_module);
 
     d = module_dict_for_exec(name);
@@ -1619,7 +1619,7 @@
 {
     _Py_IDENTIFIER(_find_and_load);
     PyObject *mod = NULL;
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
     int import_time = interp->core_config.import_time;
     static int import_level;
     static _PyTime_t accumulated;
@@ -1680,7 +1680,7 @@
     PyObject *final_mod = NULL;
     PyObject *mod = NULL;
     PyObject *package = NULL;
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
     int has_from;
 
     if (name == NULL) {
@@ -2289,7 +2289,7 @@
     d = PyModule_GetDict(m);
     if (d == NULL)
         goto failure;
-    _PyCoreConfig *config = &PyThreadState_GET()->interp->core_config;
+    _PyCoreConfig *config = &_PyInterpreterState_Get()->core_config;
     PyObject *pyc_mode = PyUnicode_FromString(config->_check_hash_pycs_mode);
     if (pyc_mode == NULL) {
         goto failure;
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 95fb861..c2ee4ff 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -2123,11 +2123,7 @@
 /* For the atexit module. */
 void _Py_PyAtExit(void (*func)(PyObject *), PyObject *module)
 {
-    PyThreadState *ts;
-    PyInterpreterState *is;
-
-    ts = PyThreadState_GET();
-    is = ts->interp;
+    PyInterpreterState *is = _PyInterpreterState_Get();
 
     /* Guard against API misuse (see bpo-17852) */
     assert(is->pyexitfunc == NULL || is->pyexitfunc == func);
diff --git a/Python/pystate.c b/Python/pystate.c
index e8d390d..7a4cd48 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -264,6 +264,21 @@
 }
 
 
+PyInterpreterState *
+_PyInterpreterState_Get(void)
+{
+    PyThreadState *tstate = GET_TSTATE();
+    if (tstate == NULL) {
+        Py_FatalError("_PyInterpreterState_Get(): no current thread state");
+    }
+    PyInterpreterState *interp = tstate->interp;
+    if (interp == NULL) {
+        Py_FatalError("_PyInterpreterState_Get(): no current interpreter");
+    }
+    return interp;
+}
+
+
 int64_t
 PyInterpreterState_GetID(PyInterpreterState *interp)
 {
@@ -1184,10 +1199,9 @@
 int
 _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
 {
-    PyThreadState *tstate = PyThreadState_Get();
-    // PyThreadState_Get() aborts if lookup fails, so we don't need
+    // _PyInterpreterState_Get() aborts if lookup fails, so we don't need
     // to check the result for NULL.
-    PyInterpreterState *interp = tstate->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
 
     // Reset data before re-populating.
     *data = (_PyCrossInterpreterData){0};
@@ -1235,7 +1249,7 @@
      * naive approach.
      */
     PyThreadState *save_tstate = NULL;
-    if (interp != PyThreadState_Get()->interp) {
+    if (interp != _PyInterpreterState_Get()) {
         // XXX Using the "head" thread isn't strictly correct.
         PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
         // XXX Possible GILState issues?
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index f6f06c7..273eae2 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -92,7 +92,7 @@
     PyCompilerFlags local_flags;
     int nomem_count = 0;
 #ifdef Py_REF_DEBUG
-    int show_ref_count = PyThreadState_GET()->interp->core_config.show_ref_count;
+    int show_ref_count = _PyInterpreterState_Get()->core_config.show_ref_count;
 #endif
 
     filename = PyUnicode_DecodeFSDefault(filename_str);
@@ -336,17 +336,13 @@
 static int
 set_main_loader(PyObject *d, const char *filename, const char *loader_name)
 {
-    PyInterpreterState *interp;
-    PyThreadState *tstate;
     PyObject *filename_obj, *bootstrap, *loader_type = NULL, *loader;
     int result = 0;
 
     filename_obj = PyUnicode_DecodeFSDefault(filename);
     if (filename_obj == NULL)
         return -1;
-    /* Get current thread state and interpreter pointer */
-    tstate = PyThreadState_GET();
-    interp = tstate->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     bootstrap = PyObject_GetAttrString(interp->importlib,
                                        "_bootstrap_external");
     if (bootstrap != NULL) {
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index b6c816e..177b830 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -56,51 +56,55 @@
 PyObject *
 _PySys_GetObjectId(_Py_Identifier *key)
 {
-    PyThreadState *tstate = PyThreadState_GET();
-    PyObject *sd = tstate->interp->sysdict;
-    if (sd == NULL)
+    PyObject *sd = _PyInterpreterState_GET_UNSAFE()->sysdict;
+    if (sd == NULL) {
         return NULL;
+    }
     return _PyDict_GetItemId(sd, key);
 }
 
 PyObject *
 PySys_GetObject(const char *name)
 {
-    PyThreadState *tstate = PyThreadState_GET();
-    PyObject *sd = tstate->interp->sysdict;
-    if (sd == NULL)
+    PyObject *sd = _PyInterpreterState_GET_UNSAFE()->sysdict;
+    if (sd == NULL) {
         return NULL;
+    }
     return PyDict_GetItemString(sd, name);
 }
 
 int
 _PySys_SetObjectId(_Py_Identifier *key, PyObject *v)
 {
-    PyThreadState *tstate = PyThreadState_GET();
-    PyObject *sd = tstate->interp->sysdict;
+    PyObject *sd = _PyInterpreterState_GET_UNSAFE()->sysdict;
     if (v == NULL) {
-        if (_PyDict_GetItemId(sd, key) == NULL)
+        if (_PyDict_GetItemId(sd, key) == NULL) {
             return 0;
-        else
+        }
+        else {
             return _PyDict_DelItemId(sd, key);
+        }
     }
-    else
+    else {
         return _PyDict_SetItemId(sd, key, v);
+    }
 }
 
 int
 PySys_SetObject(const char *name, PyObject *v)
 {
-    PyThreadState *tstate = PyThreadState_GET();
-    PyObject *sd = tstate->interp->sysdict;
+    PyObject *sd = _PyInterpreterState_GET_UNSAFE()->sysdict;
     if (v == NULL) {
-        if (PyDict_GetItemString(sd, name) == NULL)
+        if (PyDict_GetItemString(sd, name) == NULL) {
             return 0;
-        else
+        }
+        else {
             return PyDict_DelItemString(sd, name);
+        }
     }
-    else
+    else {
         return PyDict_SetItemString(sd, name, v);
+    }
 }
 
 static PyObject *
@@ -626,9 +630,13 @@
                      "are deprecated.  Use sys.setswitchinterval() "
                      "instead.", 1) < 0)
         return NULL;
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
-    if (!PyArg_ParseTuple(args, "i:setcheckinterval", &interp->check_interval))
+
+    int check_interval;
+    if (!PyArg_ParseTuple(args, "i:setcheckinterval", &check_interval))
         return NULL;
+
+    PyInterpreterState *interp = _PyInterpreterState_Get();
+    interp->check_interval = check_interval;
     Py_RETURN_NONE;
 }
 
@@ -647,7 +655,7 @@
                      "are deprecated.  Use sys.getswitchinterval() "
                      "instead.", 1) < 0)
         return NULL;
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     return PyLong_FromLong(interp->check_interval);
 }
 
@@ -1154,12 +1162,10 @@
 sys_setdlopenflags(PyObject *self, PyObject *args)
 {
     int new_val;
-    PyThreadState *tstate = PyThreadState_GET();
     if (!PyArg_ParseTuple(args, "i:setdlopenflags", &new_val))
         return NULL;
-    if (!tstate)
-        return NULL;
-    tstate->interp->dlopenflags = new_val;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
+    interp->dlopenflags = new_val;
     Py_RETURN_NONE;
 }
 
@@ -1176,10 +1182,8 @@
 static PyObject *
 sys_getdlopenflags(PyObject *self, PyObject *args)
 {
-    PyThreadState *tstate = PyThreadState_GET();
-    if (!tstate)
-        return NULL;
-    return PyLong_FromLong(tstate->interp->dlopenflags);
+    PyInterpreterState *interp = _PyInterpreterState_Get();
+    return PyLong_FromLong(interp->dlopenflags);
 }
 
 PyDoc_STRVAR(getdlopenflags_doc,
diff --git a/Python/thread.c b/Python/thread.c
index 0774384..a1e1fa6 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -92,7 +92,7 @@
 size_t
 PyThread_get_stacksize(void)
 {
-    return PyThreadState_GET()->interp->pythread_stacksize;
+    return _PyInterpreterState_Get()->pythread_stacksize;
 }
 
 /* Only platforms defining a THREAD_SET_STACKSIZE() macro