Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Next Next commit
Add version number to code object for better versioning of functions.
  • Loading branch information
markshannon committed Oct 21, 2022
commit d1e02c48ffd9312350eeeaf0c584bc6bee329785
1 change: 1 addition & 0 deletions Include/cpython/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ typedef struct {
int co_nplaincellvars; /* number of non-arg cell variables */ \
int co_ncellvars; /* total number of cell variables */ \
int co_nfreevars; /* number of free variables */ \
uint32_t co_version; /* version number */ \
\
PyObject *co_localsplusnames; /* tuple mapping offsets to names */ \
PyObject *co_localspluskinds; /* Bytes mapping to local kinds (one byte \
Expand Down
6 changes: 5 additions & 1 deletion Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "pycore_tuple.h" // _PyTuple_ITEMS()
#include "clinic/codeobject.c.h"

extern uint32_t _Py_next_func_version;

/******************
* generic helpers
Expand Down Expand Up @@ -347,7 +348,10 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
co->co_nplaincellvars = nplaincellvars;
co->co_ncellvars = ncellvars;
co->co_nfreevars = nfreevars;

co->co_version = _Py_next_func_version;
if (_Py_next_func_version != 0) {
_Py_next_func_version++;
}
/* not set */
co->co_weakreflist = NULL;
co->co_extra = NULL;
Expand Down
6 changes: 3 additions & 3 deletions Objects/funcobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "pycore_pyerrors.h" // _PyErr_Occurred()
#include "structmember.h" // PyMemberDef

static uint32_t next_func_version = 1;
uint32_t _Py_next_func_version = 10000; /* Leave plenty of space for deep frozen code objects */

PyFunctionObject *
_PyFunction_FromConstructor(PyFrameConstructor *constr)
Expand Down Expand Up @@ -137,10 +137,10 @@ uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func)
if (func->vectorcall != _PyFunction_Vectorcall) {
return 0;
}
if (next_func_version == 0) {
if (_Py_next_func_version == 0) {
return 0;
}
uint32_t v = next_func_version++;
uint32_t v = _Py_next_func_version++;
func->func_version = v;
return v;
}
Expand Down
1 change: 1 addition & 0 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -4814,6 +4814,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
assert(PyTuple_CheckExact(TOP()));
func->func_defaults = POP();
}
func->func_version = ((PyCodeObject *)codeobj)->co_version;

PUSH((PyObject *)func);
DISPATCH();
Expand Down
4 changes: 4 additions & 0 deletions Tools/build/deepfreeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def make_string_literal(b: bytes) -> str:
CO_FAST_CELL = 0x40
CO_FAST_FREE = 0x80

next_code_version = 1

def get_localsplus(code: types.CodeType):
a = collections.defaultdict(int)
Expand Down Expand Up @@ -228,6 +229,7 @@ def generate_unicode(self, name: str, s: str) -> str:


def generate_code(self, name: str, code: types.CodeType) -> str:
global next_code_version
# The ordering here matches PyCode_NewWithPosOnlyArgs()
# (but see below).
co_consts = self.generate(name + "_consts", code.co_consts)
Expand Down Expand Up @@ -270,6 +272,8 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
self.write(f".co_nplaincellvars = {nplaincellvars},")
self.write(f".co_ncellvars = {ncellvars},")
self.write(f".co_nfreevars = {nfreevars},")
self.write(f".co_version = {next_code_version},")
next_code_version += 1
self.write(f".co_localsplusnames = {co_localsplusnames},")
self.write(f".co_localspluskinds = {co_localspluskinds},")
self.write(f".co_filename = {co_filename},")
Expand Down