Move exc state to generator. Fixes bpo-25612 (#1773)

Move exception state information from frame objects to coroutine (generator/thread) object where it belongs.
diff --git a/Include/frameobject.h b/Include/frameobject.h
index dbe0a84..a95baf8 100644
--- a/Include/frameobject.h
+++ b/Include/frameobject.h
@@ -30,14 +30,6 @@
     char f_trace_lines;         /* Emit per-line trace events? */
     char f_trace_opcodes;       /* Emit per-opcode trace events? */
 
-    /* In a generator, we need to be able to swap between the exception
-       state inside the generator and the exception state of the calling
-       frame (which shouldn't be impacted when the generator "yields"
-       from an except handler).
-       These three fields exist exactly for that, and are unused for
-       non-generator frames. See the save_exc_state and swap_exc_state
-       functions in ceval.c for details of their use. */
-    PyObject *f_exc_type, *f_exc_value, *f_exc_traceback;
     /* Borrowed reference to a generator, or NULL */
     PyObject *f_gen;
 
diff --git a/Include/genobject.h b/Include/genobject.h
index b9db9f9..87fbe17 100644
--- a/Include/genobject.h
+++ b/Include/genobject.h
@@ -25,7 +25,8 @@
     /* Name of the generator. */                                            \
     PyObject *prefix##_name;                                                \
     /* Qualified name of the generator. */                                  \
-    PyObject *prefix##_qualname;
+    PyObject *prefix##_qualname;                                            \
+    _PyErr_StackItem prefix##_exc_state;
 
 typedef struct {
     /* The gi_ prefix is intended to remind of generator-iterator. */
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index fcaba85..9418201 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -78,6 +78,7 @@
 PyAPI_FUNC(void) PyErr_SetObject(PyObject *, PyObject *);
 #ifndef Py_LIMITED_API
 PyAPI_FUNC(void) _PyErr_SetKeyError(PyObject *);
+_PyErr_StackItem *_PyErr_GetTopmostException(PyThreadState *tstate);
 #endif
 PyAPI_FUNC(void) PyErr_SetString(
     PyObject *exception,
diff --git a/Include/pystate.h b/Include/pystate.h
index 507a598..238008f 100644
--- a/Include/pystate.h
+++ b/Include/pystate.h
@@ -123,6 +123,21 @@
 #ifdef Py_LIMITED_API
 typedef struct _ts PyThreadState;
 #else
+
+typedef struct _err_stackitem {
+    /* This struct represents an entry on the exception stack, which is a 
+     * per-coroutine state. (Coroutine in the computer science sense, 
+     * including the thread and generators).
+     * This ensures that the exception state is not impacted by "yields"
+     * from an except handler.
+     */
+    PyObject *exc_type, *exc_value, *exc_traceback;
+
+    struct _err_stackitem *previous_item;
+
+} _PyErr_StackItem;
+
+
 typedef struct _ts {
     /* See Python/ceval.c for comments explaining most fields */
 
@@ -147,13 +162,19 @@
     PyObject *c_profileobj;
     PyObject *c_traceobj;
 
+    /* The exception currently being raised */
     PyObject *curexc_type;
     PyObject *curexc_value;
     PyObject *curexc_traceback;
 
-    PyObject *exc_type;
-    PyObject *exc_value;
-    PyObject *exc_traceback;
+    /* The exception currently being handled, if no coroutines/generators
+     * are present. Always last element on the stack referred to be exc_info.
+     */
+    _PyErr_StackItem exc_state;
+
+    /* Pointer to the top of the stack of the exceptions currently
+     * being handled */
+    _PyErr_StackItem *exc_info;
 
     PyObject *dict;  /* Stores per-thread state */