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/Include/pystate.h b/Include/pystate.h
index bbeea9d..e410665 100644
--- a/Include/pystate.h
+++ b/Include/pystate.h
@@ -245,6 +245,13 @@
 PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void);
 PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *);
 PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *);
+#if !defined(Py_LIMITED_API)
+PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void);
+#endif
+#ifdef Py_BUILD_CORE
+   /* Macro which should only be used for performance critical code */
+#  define _PyInterpreterState_GET_UNSAFE() (PyThreadState_GET()->interp)
+#endif
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000
 /* New in 3.7 */
 PyAPI_FUNC(int64_t) PyInterpreterState_GetID(PyInterpreterState *);
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index 69e27be..f6b39de 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -1049,7 +1049,7 @@
     boot = PyMem_NEW(struct bootstate, 1);
     if (boot == NULL)
         return PyErr_NoMemory();
-    boot->interp = PyThreadState_GET()->interp;
+    boot->interp = _PyInterpreterState_Get();
     boot->func = func;
     boot->args = args;
     boot->keyw = keyw;
@@ -1154,8 +1154,8 @@
 static PyObject *
 thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
 {
-    PyThreadState *tstate = PyThreadState_Get();
-    return PyLong_FromLong(tstate->interp->num_threads);
+    PyInterpreterState *interp = _PyInterpreterState_Get();
+    return PyLong_FromLong(interp->num_threads);
 }
 
 PyDoc_STRVAR(_count_doc,
@@ -1348,7 +1348,7 @@
     PyObject *m, *d, *v;
     double time_max;
     double timeout_max;
-    PyThreadState *tstate = PyThreadState_Get();
+    PyInterpreterState *interp = _PyInterpreterState_Get();
 
     /* Initialize types: */
     if (PyType_Ready(&localdummytype) < 0)
@@ -1395,7 +1395,7 @@
     if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
         return NULL;
 
-    tstate->interp->num_threads = 0;
+    interp->num_threads = 0;
 
     str_dict = PyUnicode_InternFromString("__dict__");
     if (str_dict == NULL)
diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c
index 8567e4f..6162c53 100644
--- a/Modules/_xxsubinterpretersmodule.c
+++ b/Modules/_xxsubinterpretersmodule.c
@@ -26,10 +26,9 @@
 static PyInterpreterState *
 _get_current(void)
 {
-    PyThreadState *tstate = PyThreadState_Get();
-    // PyThreadState_Get() aborts if lookup fails, so we don't need
+    // _PyInterpreterState_Get() aborts if lookup fails, so don't need
     // to check the result for NULL.
-    return tstate->interp;
+    return _PyInterpreterState_Get();
 }
 
 static int64_t
@@ -1941,7 +1940,7 @@
 
     // Switch to interpreter.
     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/Modules/posixmodule.c b/Modules/posixmodule.c
index 6104c0f..3e03039 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -437,7 +437,7 @@
 void
 PyOS_BeforeFork(void)
 {
-    run_at_forkers(PyThreadState_Get()->interp->before_forkers, 1);
+    run_at_forkers(_PyInterpreterState_Get()->before_forkers, 1);
 
     _PyImport_AcquireLock();
 }
@@ -448,7 +448,7 @@
     if (_PyImport_ReleaseLock() <= 0)
         Py_FatalError("failed releasing import lock after fork");
 
-    run_at_forkers(PyThreadState_Get()->interp->after_forkers_parent, 0);
+    run_at_forkers(_PyInterpreterState_Get()->after_forkers_parent, 0);
 }
 
 void
@@ -459,7 +459,7 @@
     _PyImport_ReInitLock();
     _PySignal_AfterFork();
 
-    run_at_forkers(PyThreadState_Get()->interp->after_forkers_child, 0);
+    run_at_forkers(_PyInterpreterState_Get()->after_forkers_child, 0);
 }
 
 static int
@@ -5655,7 +5655,7 @@
         check_null_or_callable(after_in_parent, "after_in_parent")) {
         return NULL;
     }
-    interp = PyThreadState_Get()->interp;
+    interp = _PyInterpreterState_Get();
 
     if (register_at_forker(&interp->before_forkers, before)) {
         return NULL;
diff --git a/Modules/zipimport.c b/Modules/zipimport.c
index 57e7a13..4df4ba9 100644
--- a/Modules/zipimport.c
+++ b/Modules/zipimport.c
@@ -1074,7 +1074,7 @@
         if (flags & 0x0800) {
             charset = "utf-8";
         }
-        else if (!PyThreadState_GET()->interp->codecs_initialized) {
+        else if (!_PyInterpreterState_Get()->codecs_initialized) {
             /* During bootstrap, we may need to load the encodings
                package from a ZIP file. But the cp437 encoding is implemented
                in Python in the encodings package.
@@ -1351,7 +1351,7 @@
 
     uint32_t flags = get_uint32(buf + 4);
     if (flags != 0) {
-        _PyCoreConfig *config = &PyThreadState_GET()->interp->core_config;
+        _PyCoreConfig *config = &_PyInterpreterState_Get()->core_config;
         // Hash-based pyc. We currently refuse to handle checked hash-based
         // pycs. We could validate hash-based pycs against the source, but it
         // seems likely that most people putting hash-based pycs in a zipfile
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index b07667c..cedf11e 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -3,6 +3,7 @@
 #include "Python.h"
 #include "code.h"
 #include "structmember.h"
+#include "internal/pystate.h"
 
 /* Holder for co_extra information */
 typedef struct {
@@ -428,7 +429,7 @@
 code_dealloc(PyCodeObject *co)
 {
     if (co->co_extra != NULL) {
-        PyInterpreterState *interp = PyThreadState_Get()->interp;
+        PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
         _PyCodeObjectExtra *co_extra = co->co_extra;
 
         for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) {
@@ -871,7 +872,7 @@
 int
 _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
 {
-    PyInterpreterState *interp = PyThreadState_Get()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
 
     if (!PyCode_Check(code) || index < 0 ||
             index >= interp->co_extra_user_count) {
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 4108f50..308ae83 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -85,7 +85,7 @@
 static void
 show_alloc(void)
 {
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     if (!interp->core_config.show_alloc_count) {
         return;
     }
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 5fad447..2156ca0 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -173,7 +173,7 @@
 PyObject *
 PyModule_Create2(struct PyModuleDef* module, int module_api_version)
 {
-    if (!_PyImport_IsInitialized(PyThreadState_GET()->interp))
+    if (!_PyImport_IsInitialized(_PyInterpreterState_Get()))
         Py_FatalError("Python import machinery not initialized");
     return _PyModule_CreateInitialized(module, module_api_version);
 }
@@ -693,8 +693,7 @@
 static PyObject *
 module_repr(PyModuleObject *m)
 {
-    PyThreadState *tstate = PyThreadState_GET();
-    PyInterpreterState *interp = tstate->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
 
     return PyObject_CallMethod(interp->importlib, "_module_repr", "O", m);
 }
diff --git a/Objects/object.c b/Objects/object.c
index 2471f6b..6498756 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -96,7 +96,7 @@
 void
 dump_counts(FILE* f)
 {
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     if (!interp->core_config.show_alloc_count) {
         return;
     }
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index e268f75..eaf92d5 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -44,7 +44,7 @@
 static void
 show_track(void)
 {
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     if (!interp->core_config.show_alloc_count) {
         return;
     }
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 2b06f15..04fd6d0 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -3413,7 +3413,7 @@
 #if defined(__APPLE__)
     return _PyUnicode_AsUTF8String(unicode, Py_FileSystemDefaultEncodeErrors);
 #else
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
     /* Bootstrap check: if the filesystem codec is implemented in Python, we
        cannot use it to encode and decode filenames before it is loaded. Load
        the Python codec requires to encode at least its own filename. Use the C
@@ -3639,7 +3639,7 @@
 #if defined(__APPLE__)
     return PyUnicode_DecodeUTF8Stateful(s, size, Py_FileSystemDefaultEncodeErrors, NULL);
 #else
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
     /* Bootstrap check: if the filesystem codec is implemented in Python, we
        cannot use it to encode and decode filenames before it is loaded. Load
        the Python codec requires to encode at least its own filename. Use the C
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index 3ed42d6..027de48 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -306,7 +306,7 @@
         exit(1); \
     }
 
-    PyInterpreterState *interp = PyThreadState_Get()->interp;
+    PyInterpreterState *interp = _PyInterpreterState_Get();
     _PyCoreConfig *config = &interp->core_config;
 
     printf("install_signal_handlers = %i\n", config->install_signal_handlers);
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