aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2021-08-25 13:44:20 +0100
committerGitHub <noreply@github.com>2021-08-25 13:44:20 +0100
commitf9242d50b18572ef0d584a1c815ed08d1a38e4f4 (patch)
tree0c7c137c701b1dd69f89227dee85aaee95ff5dfb /Python/ceval.c
parent214c2e5d916d3ce5e7b1db800210b93001850bbb (diff)
downloadcpython-f9242d50b18572ef0d584a1c815ed08d1a38e4f4.tar.gz
cpython-f9242d50b18572ef0d584a1c815ed08d1a38e4f4.zip
bpo-44990: Change layout of evaluation frames. "Layout B" (GH-27933)
Places the locals between the specials and stack. This is the more "natural" layout for a C struct, makes the code simpler and gives a slight speedup (~1%)
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c76
1 files changed, 40 insertions, 36 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 333c54f50e2..5fec90b1048 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1367,7 +1367,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
/* The stack can grow at most MAXINT deep, as co_nlocals and
co_stacksize are ints. */
-#define STACK_LEVEL() ((int)(stack_pointer - frame->stack))
+#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame)))
#define EMPTY() (STACK_LEVEL() == 0)
#define TOP() (stack_pointer[-1])
#define SECOND() (stack_pointer[-2])
@@ -1413,7 +1413,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
/* Local variable macros */
-#define GETLOCAL(i) (localsplus[i])
+#define GETLOCAL(i) (frame->localsplus[i])
/* The SETLOCAL() macro must not DECREF the local variable in-place and
then store the new value; it must copy the old value to a temporary
@@ -1559,7 +1559,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
PyObject *names = co->co_names;
PyObject *consts = co->co_consts;
- PyObject **localsplus = _PyFrame_GetLocalsArray(frame);
_Py_CODEUNIT *first_instr = co->co_firstinstr;
/*
frame->f_lasti refers to the index of the last instruction,
@@ -1578,14 +1577,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
*/
assert(frame->f_lasti >= -1);
_Py_CODEUNIT *next_instr = first_instr + frame->f_lasti + 1;
- PyObject **stack_pointer = frame->stack + frame->stackdepth;
+ PyObject **stack_pointer = _PyFrame_GetStackPointer(frame);
/* Set stackdepth to -1.
* Update when returning or calling trace function.
- Having f_stackdepth <= 0 ensures that invalid
+ Having stackdepth <= 0 ensures that invalid
values are not visible to the cycle GC.
We choose -1 rather than 0 to assist debugging.
*/
- frame->stackdepth = -1;
+ frame->stacktop = -1;
frame->f_state = FRAME_EXECUTING;
#ifdef LLTRACE
@@ -1668,7 +1667,7 @@ check_eval_breaker:
int err;
/* see maybe_call_line_trace()
for expository comments */
- frame->stackdepth = (int)(stack_pointer - frame->stack);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
err = maybe_call_line_trace(tstate->c_tracefunc,
tstate->c_traceobj,
@@ -1679,8 +1678,9 @@ check_eval_breaker:
}
/* Reload possibly changed frame fields */
JUMPTO(frame->f_lasti);
- stack_pointer = frame->stack+frame->stackdepth;
- frame->stackdepth = -1;
+
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ frame->stacktop = -1;
TRACING_NEXTOPARG();
}
PRE_DISPATCH_GOTO();
@@ -2439,7 +2439,7 @@ check_eval_breaker:
retval = POP();
assert(EMPTY());
frame->f_state = FRAME_RETURNED;
- frame->stackdepth = 0;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
goto exiting;
}
@@ -2627,7 +2627,7 @@ check_eval_breaker:
assert(frame->f_lasti > 0);
frame->f_lasti -= 1;
frame->f_state = FRAME_SUSPENDED;
- frame->stackdepth = (int)(stack_pointer - frame->stack);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
goto exiting;
}
@@ -2644,7 +2644,7 @@ check_eval_breaker:
retval = w;
}
frame->f_state = FRAME_SUSPENDED;
- frame->stackdepth = (int)(stack_pointer - frame->stack);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
goto exiting;
}
@@ -4346,7 +4346,7 @@ check_eval_breaker:
oparg = cache->adaptive.original_oparg;
STAT_DEC(LOAD_METHOD, unquickened);
JUMP_TO_INSTRUCTION(LOAD_METHOD);
- }
+ }
}
TARGET(LOAD_METHOD_CACHED): {
@@ -4364,7 +4364,7 @@ check_eval_breaker:
assert(cache1->tp_version != 0);
assert(self_cls->tp_dictoffset >= 0);
assert(Py_TYPE(self_cls)->tp_dictoffset > 0);
-
+
// inline version of _PyObject_GetDictPtr for offset >= 0
PyObject *dict = self_cls->tp_dictoffset != 0 ?
*(PyObject **) ((char *)self + self_cls->tp_dictoffset) : NULL;
@@ -4817,17 +4817,20 @@ exception_unwind:
assert(_PyErr_Occurred(tstate));
/* Pop remaining stack entries. */
- while (!EMPTY()) {
+ PyObject **stackbase = _PyFrame_Stackbase(frame);
+ while (stack_pointer > stackbase) {
PyObject *o = POP();
Py_XDECREF(o);
}
- frame->stackdepth = 0;
+ assert(STACK_LEVEL() == 0);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
frame->f_state = FRAME_RAISED;
goto exiting;
}
assert(STACK_LEVEL() >= level);
- while (STACK_LEVEL() > level) {
+ PyObject **new_top = _PyFrame_Stackbase(frame) + level;
+ while (stack_pointer > new_top) {
PyObject *v = POP();
Py_XDECREF(v);
}
@@ -4981,7 +4984,7 @@ missing_arguments(PyThreadState *tstate, PyCodeObject *co,
end = start + co->co_kwonlyargcount;
}
for (i = start; i < end; i++) {
- if (GETLOCAL(i) == NULL) {
+ if (localsplus[i] == NULL) {
PyObject *raw = PyTuple_GET_ITEM(co->co_localsplusnames, i);
PyObject *name = PyObject_Repr(raw);
if (name == NULL) {
@@ -5010,7 +5013,7 @@ too_many_positional(PyThreadState *tstate, PyCodeObject *co,
assert((co->co_flags & CO_VARARGS) == 0);
/* Count missing keyword-only args. */
for (i = co_argcount; i < co_argcount + co->co_kwonlyargcount; i++) {
- if (GETLOCAL(i) != NULL) {
+ if (localsplus[i] != NULL) {
kwonly_given++;
}
}
@@ -5217,7 +5220,8 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
if (co->co_flags & CO_VARARGS) {
i++;
}
- SETLOCAL(i, kwdict);
+ assert(localsplus[i] == NULL);
+ localsplus[i] = kwdict;
}
else {
kwdict = NULL;
@@ -5234,7 +5238,8 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
for (j = 0; j < n; j++) {
PyObject *x = args[j];
Py_INCREF(x);
- SETLOCAL(j, x);
+ assert(localsplus[j] == NULL);
+ localsplus[j] = x;
}
/* Pack other positional arguments into the *args argument */
@@ -5243,7 +5248,8 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
if (u == NULL) {
goto fail;
}
- SETLOCAL(total_args, u);
+ assert(localsplus[total_args] == NULL);
+ localsplus[total_args] = u;
}
/* Handle keyword arguments */
@@ -5307,14 +5313,14 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
continue;
kw_found:
- if (GETLOCAL(j) != NULL) {
+ if (localsplus[j] != NULL) {
_PyErr_Format(tstate, PyExc_TypeError,
"%U() got multiple values for argument '%S'",
con->fc_qualname, keyword);
goto fail;
}
Py_INCREF(value);
- SETLOCAL(j, value);
+ localsplus[j] = value;
}
}
@@ -5331,7 +5337,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
Py_ssize_t m = co->co_argcount - defcount;
Py_ssize_t missing = 0;
for (i = argcount; i < m; i++) {
- if (GETLOCAL(i) == NULL) {
+ if (localsplus[i] == NULL) {
missing++;
}
}
@@ -5347,10 +5353,10 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
if (defcount) {
PyObject **defs = &PyTuple_GET_ITEM(con->fc_defaults, 0);
for (; i < defcount; i++) {
- if (GETLOCAL(m+i) == NULL) {
+ if (localsplus[m+i] == NULL) {
PyObject *def = defs[i];
Py_INCREF(def);
- SETLOCAL(m+i, def);
+ localsplus[m+i] = def;
}
}
}
@@ -5360,14 +5366,14 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
if (co->co_kwonlyargcount > 0) {
Py_ssize_t missing = 0;
for (i = co->co_argcount; i < total_args; i++) {
- if (GETLOCAL(i) != NULL)
+ if (localsplus[i] != NULL)
continue;
PyObject *varname = PyTuple_GET_ITEM(co->co_localsplusnames, i);
if (con->fc_kwdefaults != NULL) {
PyObject *def = PyDict_GetItemWithError(con->fc_kwdefaults, varname);
if (def) {
Py_INCREF(def);
- SETLOCAL(i, def);
+ localsplus[i] = def;
continue;
}
else if (_PyErr_Occurred(tstate)) {
@@ -5407,18 +5413,17 @@ make_coro_frame(PyThreadState *tstate,
assert(con->fc_defaults == NULL || PyTuple_CheckExact(con->fc_defaults));
PyCodeObject *code = (PyCodeObject *)con->fc_code;
int size = code->co_nlocalsplus+code->co_stacksize + FRAME_SPECIALS_SIZE;
- PyObject **localsarray = PyMem_Malloc(sizeof(PyObject *)*size);
- if (localsarray == NULL) {
+ InterpreterFrame *frame = (InterpreterFrame *)PyMem_Malloc(sizeof(PyObject *)*size);
+ if (frame == NULL) {
PyErr_NoMemory();
return NULL;
}
for (Py_ssize_t i=0; i < code->co_nlocalsplus; i++) {
- localsarray[i] = NULL;
+ frame->localsplus[i] = NULL;
}
- InterpreterFrame *frame = (InterpreterFrame *)(localsarray + code->co_nlocalsplus);
_PyFrame_InitializeSpecials(frame, con, locals, code->co_nlocalsplus);
assert(frame->frame_obj == NULL);
- if (initialize_locals(tstate, con, localsarray, args, argcount, kwnames)) {
+ if (initialize_locals(tstate, con, frame->localsplus, args, argcount, kwnames)) {
_PyFrame_Clear(frame, 1);
return NULL;
}
@@ -5497,7 +5502,7 @@ _PyEval_Vector(PyThreadState *tstate, PyFrameConstructor *con,
}
assert (tstate->interp->eval_frame != NULL);
PyObject *retval = _PyEval_EvalFrame(tstate, frame, 0);
- assert(frame->stackdepth == 0);
+ assert(_PyFrame_GetStackPointer(frame) == _PyFrame_Stackbase(frame));
if (_PyEvalFrameClearAndPop(tstate, frame)) {
retval = NULL;
}
@@ -6764,7 +6769,6 @@ unicode_concatenate(PyThreadState *tstate, PyObject *v, PyObject *w,
switch (opcode) {
case STORE_FAST:
{
- PyObject **localsplus = _PyFrame_GetLocalsArray(frame);
if (GETLOCAL(oparg) == v)
SETLOCAL(oparg, NULL);
break;