8000 bpo-43693: Add _PyCode_New() and do some related cleanup. by ericsnowcurrently · Pull Request #26258 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-43693: Add _PyCode_New() and do some related cleanup. #26258

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
dce5124
Re-organize the _PyCodeObject fields.
ericsnowcurrently May 18, 2021
e416918
Spell out the PyCode_New*() signatures.
ericsnowcurrently May 18, 2021
6740572
Add a TODO to code.h.
ericsnowcurrently May 18, 2021
4381869
Fix a memory leak.
ericsnowcurrently May 18, 2021
19cfb8b
Add _PyCode_New().
ericsnowcurrently May 18, 2021
8f10f5d
Factor out _PyCode_GetFastlocalOffsetId().
ericsnowcurrently May 18, 2021
0c42221
Factor out _PyCode_HasFastlocals().
ericsnowcurrently May 18, 2021
3315b28
Factor out _PyCode_CellForLocal().
ericsnowcurrently May 18, 2021
2ac48ba
Add macros to hide away some of the PyCodeObject fields.
ericsnowcurrently May 19, 2021
02e15a4
Move the fast locals section down.
ericsnowcurrently May 19, 2021
ad70f99
Store more counts on PyCodeObject.
ericsnowcurrently May 19, 2021
e38643f
Update a comment.
ericsnowcurrently May 19, 2021
09fbe71 8000
Factor out macros related to co_code.
ericsnowcurrently May 14, 2021
9b4ca77
Fix some smelly names.
ericsnowcurrently May 20, 2021
f00133f
Fix whitespace.
ericsnowcurrently May 20, 2021
acef742
Fix co_nlocals in code.replace().
ericsnowcurrently May 20, 2021
559e408
Stop using statics in PyCode_NewEmpty().
ericsnowcurrently May 20, 2021
a923b5b
Actually fix whitespace.
ericsnowcurrently May 20, 2021
afcc944
Fix a typo.
ericsnowcurrently May 20, 2021
d304aba
Replace macros with inline functions.
ericsnowcurrently May 20, 2021
23e5485
Unify all the PyCodeObject validation code.
ericsnowcurrently May 20, 2021
81c4a49
Fix the logged function name.
ericsnowcurrently May 20, 2021
af51553
Fix the GDB script.
ericsnowcurrently May 21, 2021
cc3f435
-_PyCode_GetFastlocalOffsetId -> _PyCode_FastOffsetFromId().
ericsnowcurrently May 21, 2021
fcf4ea3
Fix CO_FAST_KWONLY.
ericsnowcurrently May 21, 2021
cb82a6a
Fix a typo.
ericsnowcurrently May 21, 2021
672a75f
Make sure int is used for fast offsets and PyCodeObject counts.
ericsnowcurrently May 22, 2021
32907b1
Fix the comment about fields in hash/comparision.
ericsnowcurrently May 22, 2021
aee3640
Drop co_nlocals from marshaled code objects.
ericsnowcurrently May 22, 2021
fd50f62
Regen a couple more files.
ericsnowcurrently May 22, 2021
9736ff5
Fix test_ctypes.
ericsnowcurrently May 22, 2021
c95314c
Factor out CO_FAST_ARG.
ericsnowcurrently May 24, 2021
b419060
Fix a typo.
ericsnowcurrently May 24, 2021
6195184
Add an assert for the return value of frame_nslots().
ericsnowcurrently May 24, 2021
3c4ec94
Add a comment about using an arguments struct for _PyCode_New().
ericsnowcurrently May 24, 2021
ffc4b54
Drop some outdated TODO comments.
ericsnowcurrently May 24, 2021
292b646
Fix a typo.
ericsnowcurrently May 24, 2021
cd9e34a
Add _PyCode_FastInfoFromOffset().
ericsnowcurrently May 24, 2021
cd4f587
Add _PyCode_GetFastFreevar().
ericsnowcurrently May 24, 2021
a4e6dd3
Use _PyCode_FastInfoFromOffset() elsewhere in ceval.c.
ericsnowcurrently May 24, 2021
f93b6df
Add _PyCode_OffsetFromIndex().
ericsnowcurrently May 24, 2021
f779627
_PyCode_FastInfoFromOffset() -> _PyCode_FastInfoFromOparg().
ericsnowcurrently May 24, 2021
292e457
Add _PyCode_FastInfoFromOffset() and use it in frameobject.c.
ericsnowcurrently May 24, 2021
f6bafb4
Fix warnings.
ericsnowcurrently May 24, 2021
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
Prev Previous commit
Next Next commit
Replace macros with inline functions.
  • Loading branch information
ericsnowcurrently committed May 21, 2021
commit d304aba2f6d6dd55363f8318118c8f8090e9b036
73 changes: 49 additions & 24 deletions Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>


Expand Down Expand Up @@ -87,31 +87,56 @@ PyAPI_FUNC(bool) _PyCode_HasFastlocals(PyCodeObject *, _PyFastLocalKind);
PyAPI_FUNC(Py_ssize_t) _PyCode_CellForLocal(PyCodeObject *, Py_ssize_t);

/* This does not fail. A negative result means "no match". */
PyAPI_FUNC(Py_ssize_t) _PyCode_GetFastlocalOffsetId(PyCodeObject *,
_Py_Identifier *,
_PyFastLocalKind);
PyAPI_FUNC(Py_ssize_t) _PyCode_GetFastlocalOffsetId(PyCodeObject *,
_Py_Identifier *,
_PyFastLocalKind);

// This is a speed hack for use in ceval.c.
#define _PyCode_LOCALVARS_ARRAY(co) \
(((PyTupleObject *)((co)->co_varnames))->ob_item)
#define _PyCode_GET_LOCALVAR(co, offset) \
(PyTuple_GetItem((co)->co_varnames, offset))

#define _PyCode_GET_CELLVAR(co, offset) \
(PyTuple_GetItem((co)->co_cellvars, offset))

#define _PyCode_GET_FREEVAR(co, offset) \
(PyTuple_GetItem((co)->co_freevars, offset))

#define _PyCode_CODE_IS_VALID(co) \
(PyBytes_Check((co)->co_code) && \
PyBytes_GET_SIZE((co)->co_code) <= INT_MAX && \
PyBytes_GET_SIZE((co)->co_code) % sizeof(_Py_CODEUNIT) == 0 && \
_Py_IS_ALIGNED(PyBytes_AS_STRING((co)->co_code), sizeof(_Py_CODEUNIT)))
#define _PyCode_GET_INSTRUCTIONS(co) \
((_Py_CODEUNIT *) PyBytes_AS_STRING((co)->co_code))
#define _PyCode_NUM_INSTRUCTIONS(co) \
(PyBytes_Size((co)->co_code) / sizeof(_Py_CODEUNIT))
static inline PyObject **
_PyCode_LocalvarsArray(PyCodeObject *co)
{
return ((PyTupleObject *)(co->co_varnames))->ob_item;
}

static inline PyObject *
_PyCode_GetLocalvar(PyCodeObject *co, Py_ssize_t offset)
{
return PyTuple_GetItem(co->co_varnames, offset);
}

static inline PyObject *
_PyCode_GetCellvar(PyCodeObject *co, Py_ssize_t offset)
{
return PyTuple_GetItem(co->co_cellvars, offset);
}

static inline PyObject *
_PyCode_GetFreevar(PyCodeObject *co, Py_ssize_t offset)
{
return PyTuple_GetItem(co->co_freevars, offset);
}

static inline bool
_PyCode_CodeIsValid(PyCodeObject *co)
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't check for validity, at all. A full validity check would be large and slow. Maybe rename to reflect what it does?

{
return PyBytes_Check(co->co_code) &&
PyBytes_GET_SIZE(co->co_code) <= INT_MAX &&
PyBytes_GET_SIZE(co->co_code) % sizeof(_Py_CODEUNIT) == 0 &&
_Py_IS_ALIGNED(PyBytes_AS_STRING(co->co_code),
sizeof(_Py_CODEUNIT));
}

static inline _Py_CODEUNIT *
_PyCode_GetInstructions(PyCodeObject *co)
Copy link
Member

Choose a reason for hiding this comment

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

This is going to be misleading with quickening, so could you drop it for now.
Plus these accessor functions have an annoying tendency to end up in the public API, historically.

{
return (_Py_CODEUNIT *)PyBytes_AS_STRING(co->co_code);
}

static inline Py_ssize_t
_PyCode_NumInstructions(PyCodeObject *co)
{
return PyBytes_Size(co->co_code) / sizeof(_Py_CODEUNIT);
}


#ifdef __cplusplus
Expand Down
4 changes: 2 additions & 2 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ top_of_stack(int64_t stack)
static int64_t *
mark_stacks(PyCodeObject *code_obj, int len)
{
const _Py_CODEUNIT *code = _PyCode_GET_INSTRUCTIONS(code_obj);
const _Py_CODEUNIT *code = _PyCode_GetInstructions(code_obj);
int64_t *stacks = PyMem_New(int64_t, len+1);
int i, j, opcode;

Expand Down Expand Up @@ -480,7 +480,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore

/* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this
* should never overflow. */
int len = (int)_PyCode_NUM_INSTRUCTIONS(f->f_code);
int len = (int)_PyCode_NumInstructions(f->f_code);
int *lines = marklines(f->f_code, len);
if (lines == NULL) {
return -1;
Expand Down
24 changes: 12 additions & 12 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1648,8 +1648,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
consts = co->co_consts;
fastlocals = f->f_localsptr;
freevars = f->f_localsptr + co->co_nlocals;
assert(_PyCode_CODE_IS_VALID(co));
first_instr = _PyCode_GET_INSTRUCTIONS(co);
assert(_PyCode_CodeIsValid(co));
first_instr = _PyCode_GetInstructions(co);
/*
f->f_lasti refers to the index of the last instruction,
unless it's -1 in which case next_instr should be first_instr.
Expand Down Expand Up @@ -1685,7 +1685,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
}
#if OPCACHE_STATS
opcache_code_objects_extra_mem +=
_PyCode_NUM_INSTRUCTIONS(co) +
_PyCode_NumInstructions(co) +
sizeof(_PyOpcache) * co->co_opcache_size;
opcache_code_objects++;
#endif
Expand Down Expand Up @@ -1822,7 +1822,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
if (value == NULL) {
format_exc_check_arg(tstate, PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
_PyCode_GET_LOCALVAR(co, oparg));
_PyCode_GetLocalvar(co, oparg));
goto error;
}
Py_INCREF(value);
Expand Down Expand Up @@ -3050,7 +3050,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
format_exc_check_arg(
tstate, PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
_PyCode_GET_LOCALVAR(co, oparg)
_PyCode_GetLocalvar(co, oparg)
);
goto error;
}
Expand Down Expand Up @@ -3082,7 +3082,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
assert(oparg >= co->co_ncellvars);
idx = oparg - co->co_ncellvars;
assert(idx >= 0 && idx < co->co_nfreevars);
name = _PyCode_GET_FREEVAR(co, idx);
name = _PyCode_GetFreevar(co, idx);
if (PyDict_CheckExact(locals)) {
value = PyDict_GetItemWithError(locals, name);
if (value != NULL) {
Expand Down Expand Up @@ -4656,7 +4656,7 @@ missing_arguments(PyThreadState *tstate, PyCodeObject *co,
}
for (i = start; i < end; i++) {
if (GETLOCAL(i) == NULL) {
PyObject *raw = _PyCode_GET_LOCALVAR(co, i);
PyObject *raw = _PyCode_GetLocalvar(co, i);
PyObject *name = PyObject_Repr(raw);
if (name == NULL) {
Py_DECREF(missing_names);
Expand Down Expand Up @@ -4737,7 +4737,7 @@ positional_only_passed_as_keyword(PyThreadState *tstate, PyCodeObject *co,
PyObject* posonly_names = PyList_New(0);

for(int k=0; k < co->co_posonlyargcount; k++){
PyObject* posonly_name = _PyCode_GET_LOCALVAR(co, k);
PyObject* posonly_name = _PyCode_GetLocalvar(co, k);

for (int k2=0; k2<kwcount; k2++){
/* Compare the pointers first and fallback to PyObject_RichCompareBool*/
Expand Down Expand Up @@ -4939,7 +4939,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,

/* Speed hack: do raw pointer compares. As names are
normally interned this should almost always hit. */
co_varnames = _PyCode_LOCALVARS_ARRAY(co);
co_varnames = _PyCode_LocalvarsArray(co);
for (j = co->co_posonlyargcount; j < total_args; j++) {
PyObject *varname = co_varnames[j];
if (varname == keyword) {
Expand Down Expand Up @@ -5037,7 +5037,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
for (i = co->co_argcount; i < total_args; i++) {
if (GETLOCAL(i) != NULL)
continue;
PyObject *varname = _PyCode_GET_LOCALVAR(co, i);
PyObject *varname = _PyCode_GetLocalvar(co, i);
if (con->fc_kwdefaults != NULL) {
PyObject *def = PyDict_GetItemWithError(con->fc_kwdefaults, varname);
if (def) {
Expand Down Expand Up @@ -6416,13 +6416,13 @@ format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg)
if (_PyErr_Occurred(tstate))
return;
if (oparg < co->co_ncellvars) {
name = _PyCode_GET_CELLVAR(co, oparg);
name = _PyCode_GetCellvar(co, oparg);
format_exc_check_arg(tstate,
PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
name);
} else {
name = _PyCode_GET_FREEVAR(co, oparg - co->co_ncellvars);
name = _PyCode_GetFreevar(co, oparg - co->co_ncellvars);
format_exc_check_arg(tstate, PyExc_NameError,
UNBOUNDFREE_ERROR_MSG, name);
}
Expand Down
2 changes: 1 addition & 1 deletion Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -2063,7 +2063,7 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags,
/* Bypass com_addop_varname because it will generate
LOAD_DEREF but LOAD_CLOSURE is needed.
*/
PyObject *name = _PyCode_GET_FREEVAR(co, i);
PyObject *name = _PyCode_GetFreevar(co, i);

/* Special case: If a class contains a method with a
free variable that has the same name as a method,
Expand Down
0