mirror of https://github.com/python/cpython
GH-98522: Add version number to code objects. (GH-98525)
* Add version number to code object for better versioning of functions. * Improves specialization for closures and list comprehensions.
This commit is contained in:
parent
3c5355496b
commit
fb713b2183
|
@ -87,6 +87,7 @@ typedef struct {
|
||||||
int co_nplaincellvars; /* number of non-arg cell variables */ \
|
int co_nplaincellvars; /* number of non-arg cell variables */ \
|
||||||
int co_ncellvars; /* total number of cell variables */ \
|
int co_ncellvars; /* total number of cell variables */ \
|
||||||
int co_nfreevars; /* number of free variables */ \
|
int co_nfreevars; /* number of free variables */ \
|
||||||
|
uint32_t co_version; /* version number */ \
|
||||||
\
|
\
|
||||||
PyObject *co_localsplusnames; /* tuple mapping offsets to names */ \
|
PyObject *co_localsplusnames; /* tuple mapping offsets to names */ \
|
||||||
PyObject *co_localspluskinds; /* Bytes mapping to local kinds (one byte \
|
PyObject *co_localspluskinds; /* Bytes mapping to local kinds (one byte \
|
||||||
|
|
|
@ -474,6 +474,8 @@ typedef struct _PyShimCodeDef {
|
||||||
extern PyCodeObject *
|
extern PyCodeObject *
|
||||||
_Py_MakeShimCode(const _PyShimCodeDef *code);
|
_Py_MakeShimCode(const _PyShimCodeDef *code);
|
||||||
|
|
||||||
|
extern uint32_t _Py_next_func_version;
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Add an internal version number to code objects, to give better versioning of
|
||||||
|
inner functions and comprehensions, and thus better specialization of those
|
||||||
|
functions. This change is invisible to both Python and C extensions.
|
|
@ -11,7 +11,6 @@
|
||||||
#include "pycore_tuple.h" // _PyTuple_ITEMS()
|
#include "pycore_tuple.h" // _PyTuple_ITEMS()
|
||||||
#include "clinic/codeobject.c.h"
|
#include "clinic/codeobject.c.h"
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
notify_code_watchers(PyCodeEvent event, PyCodeObject *co)
|
notify_code_watchers(PyCodeEvent event, PyCodeObject *co)
|
||||||
{
|
{
|
||||||
|
@ -398,7 +397,10 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
|
||||||
co->co_nplaincellvars = nplaincellvars;
|
co->co_nplaincellvars = nplaincellvars;
|
||||||
co->co_ncellvars = ncellvars;
|
co->co_ncellvars = ncellvars;
|
||||||
co->co_nfreevars = nfreevars;
|
co->co_nfreevars = nfreevars;
|
||||||
|
co->co_version = _Py_next_func_version;
|
||||||
|
if (_Py_next_func_version != 0) {
|
||||||
|
_Py_next_func_version++;
|
||||||
|
}
|
||||||
/* not set */
|
/* not set */
|
||||||
co->co_weakreflist = NULL;
|
co->co_weakreflist = NULL;
|
||||||
co->co_extra = NULL;
|
co->co_extra = NULL;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_ceval.h" // _PyEval_BuiltinsFromGlobals()
|
#include "pycore_ceval.h" // _PyEval_BuiltinsFromGlobals()
|
||||||
#include "pycore_function.h" // FUNC_MAX_WATCHERS
|
#include "pycore_code.h" // _Py_next_func_version
|
||||||
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
|
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
|
||||||
#include "pycore_pyerrors.h" // _PyErr_Occurred()
|
#include "pycore_pyerrors.h" // _PyErr_Occurred()
|
||||||
#include "structmember.h" // PyMemberDef
|
#include "structmember.h" // PyMemberDef
|
||||||
|
@ -64,7 +64,6 @@ PyFunction_ClearWatcher(int watcher_id)
|
||||||
interp->active_func_watchers &= ~(1 << watcher_id);
|
interp->active_func_watchers &= ~(1 << watcher_id);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyFunctionObject *
|
PyFunctionObject *
|
||||||
_PyFunction_FromConstructor(PyFrameConstructor *constr)
|
_PyFunction_FromConstructor(PyFrameConstructor *constr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include "Python/frozen_modules/importlib._bootstrap_external.h"
|
#include "Python/frozen_modules/importlib._bootstrap_external.h"
|
||||||
/* End includes */
|
/* End includes */
|
||||||
|
|
||||||
|
uint32_t _Py_next_func_version = 1;
|
||||||
|
|
||||||
/* Empty initializer for deepfrozen modules */
|
/* Empty initializer for deepfrozen modules */
|
||||||
int _Py_Deepfreeze_Init(void)
|
int _Py_Deepfreeze_Init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
Keep this file in sync with Programs/_freeze_module.py.
|
Keep this file in sync with Programs/_freeze_module.py.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <marshal.h>
|
#include <marshal.h>
|
||||||
#include "pycore_fileutils.h" // _Py_stat_struct
|
#include "pycore_fileutils.h" // _Py_stat_struct
|
||||||
|
@ -22,6 +23,8 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint32_t _Py_next_func_version = 1;
|
||||||
|
|
||||||
/* Empty initializer for deepfrozen modules */
|
/* Empty initializer for deepfrozen modules */
|
||||||
int _Py_Deepfreeze_Init(void)
|
int _Py_Deepfreeze_Init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3452,6 +3452,7 @@ dummy_func(
|
||||||
func->func_defaults = POP();
|
func->func_defaults = POP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func->func_version = ((PyCodeObject *)codeobj)->co_version;
|
||||||
PUSH((PyObject *)func);
|
PUSH((PyObject *)func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3693,6 +3693,7 @@
|
||||||
func->func_defaults = POP();
|
func->func_defaults = POP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func->func_version = ((PyCodeObject *)codeobj)->co_version;
|
||||||
PUSH((PyObject *)func);
|
PUSH((PyObject *)func);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ CO_FAST_LOCAL = 0x20
|
||||||
CO_FAST_CELL = 0x40
|
CO_FAST_CELL = 0x40
|
||||||
CO_FAST_FREE = 0x80
|
CO_FAST_FREE = 0x80
|
||||||
|
|
||||||
|
next_code_version = 1
|
||||||
|
|
||||||
def get_localsplus(code: types.CodeType):
|
def get_localsplus(code: types.CodeType):
|
||||||
a = collections.defaultdict(int)
|
a = collections.defaultdict(int)
|
||||||
|
@ -227,6 +228,7 @@ class Printer:
|
||||||
|
|
||||||
|
|
||||||
def generate_code(self, name: str, code: types.CodeType) -> str:
|
def generate_code(self, name: str, code: types.CodeType) -> str:
|
||||||
|
global next_code_version
|
||||||
# The ordering here matches PyCode_NewWithPosOnlyArgs()
|
# The ordering here matches PyCode_NewWithPosOnlyArgs()
|
||||||
# (but see below).
|
# (but see below).
|
||||||
co_consts = self.generate(name + "_consts", code.co_consts)
|
co_consts = self.generate(name + "_consts", code.co_consts)
|
||||||
|
@ -268,6 +270,8 @@ class Printer:
|
||||||
self.write(f".co_nplaincellvars = {nplaincellvars},")
|
self.write(f".co_nplaincellvars = {nplaincellvars},")
|
||||||
self.write(f".co_ncellvars = {ncellvars},")
|
self.write(f".co_ncellvars = {ncellvars},")
|
||||||
self.write(f".co_nfreevars = {nfreevars},")
|
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_localsplusnames = {co_localsplusnames},")
|
||||||
self.write(f".co_localspluskinds = {co_localspluskinds},")
|
self.write(f".co_localspluskinds = {co_localspluskinds},")
|
||||||
self.write(f".co_filename = {co_filename},")
|
self.write(f".co_filename = {co_filename},")
|
||||||
|
@ -461,6 +465,7 @@ def generate(args: list[str], output: TextIO) -> None:
|
||||||
with printer.block(f"if ({p} < 0)"):
|
with printer.block(f"if ({p} < 0)"):
|
||||||
printer.write("return -1;")
|
printer.write("return -1;")
|
||||||
printer.write("return 0;")
|
printer.write("return 0;")
|
||||||
|
printer.write(f"\nuint32_t _Py_next_func_version = {next_code_version};\n")
|
||||||
if verbose:
|
if verbose:
|
||||||
print(f"Cache hits: {printer.hits}, misses: {printer.misses}")
|
print(f"Cache hits: {printer.hits}, misses: {printer.misses}")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue