#include <stdbool.h>
#include "Python.h"
#include "opcode.h"
#include "pycore_code.h"
#include "pycore_frame.h"
#include "pycore_hashtable.h"
#include "pycore_initconfig.h"
#include "pycore_interp.h"
#include "pycore_object.h"
#include "pycore_opcode_metadata.h"
#include "pycore_opcode_utils.h"
#include "pycore_pystate.h"
#include "pycore_setobject.h"
#include "pycore_tuple.h"
#include "clinic/codeobject.c.h"
static const char *
code_event_name(PyCodeEvent event) { … }
static void
notify_code_watchers(PyCodeEvent event, PyCodeObject *co)
{ … }
int
PyCode_AddWatcher(PyCode_WatchCallback callback)
{ … }
static inline int
validate_watcher_id(PyInterpreterState *interp, int watcher_id)
{ … }
int
PyCode_ClearWatcher(int watcher_id)
{ … }
static int
should_intern_string(PyObject *o)
{ … }
#ifdef Py_GIL_DISABLED
static PyObject *intern_one_constant(PyObject *op);
#endif
static int
intern_strings(PyObject *tuple)
{ … }
static int
intern_constants(PyObject *tuple, int *modified)
{ … }
static PyObject*
validate_and_copy_tuple(PyObject *tup)
{ … }
static int
init_co_cached(PyCodeObject *self) { … }
void
_Py_set_localsplus_info(int offset, PyObject *name, _PyLocals_Kind kind,
PyObject *names, PyObject *kinds)
{ … }
static void
get_localsplus_counts(PyObject *names, PyObject *kinds,
int *pnlocals, int *pncellvars,
int *pnfreevars)
{ … }
static PyObject *
get_localsplus_names(PyCodeObject *co, _PyLocals_Kind kind, int num)
{ … }
int
_PyCode_Validate(struct _PyCodeConstructor *con)
{ … }
extern void _PyCode_Quicken(PyCodeObject *code);
static void
init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
{ … }
static int
scan_varint(const uint8_t *ptr)
{ … }
static int
scan_signed_varint(const uint8_t *ptr)
{ … }
static int
get_line_delta(const uint8_t *ptr)
{ … }
static PyObject *
remove_column_info(PyObject *locations)
{ … }
static int
intern_code_constants(struct _PyCodeConstructor *con)
{ … }
PyCodeObject *
_PyCode_New(struct _PyCodeConstructor *con)
{ … }
PyCodeObject *
PyUnstable_Code_NewWithPosOnlyArgs(
int argcount, int posonlyargcount, int kwonlyargcount,
int nlocals, int stacksize, int flags,
PyObject *code, PyObject *consts, PyObject *names,
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
PyObject *filename, PyObject *name,
PyObject *qualname, int firstlineno,
PyObject *linetable,
PyObject *exceptiontable)
{ … }
PyCodeObject *
PyUnstable_Code_New(int argcount, int kwonlyargcount,
int nlocals, int stacksize, int flags,
PyObject *code, PyObject *consts, PyObject *names,
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
PyObject *filename, PyObject *name, PyObject *qualname,
int firstlineno,
PyObject *linetable,
PyObject *exceptiontable)
{ … }
static const uint8_t assert0[6] = …;
static const uint8_t linetable[2] = …;
PyCodeObject *
PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
{ … }
int
PyCode_Addr2Line(PyCodeObject *co, int addrq)
{ … }
void
_PyLineTable_InitAddressRange(const char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range)
{ … }
int
_PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds)
{ … }
int
_PyCode_CheckLineNumber(int lasti, PyCodeAddressRange *bounds)
{ … }
static int
is_no_line_marker(uint8_t b)
{ … }
#define ASSERT_VALID_BOUNDS(bounds) …
static int
next_code_delta(PyCodeAddressRange *bounds)
{ … }
static int
previous_code_delta(PyCodeAddressRange *bounds)
{ … }
static int
read_byte(PyCodeAddressRange *bounds)
{ … }
static int
read_varint(PyCodeAddressRange *bounds)
{ … }
static int
read_signed_varint(PyCodeAddressRange *bounds)
{ … }
static void
retreat(PyCodeAddressRange *bounds)
{ … }
static void
advance(PyCodeAddressRange *bounds)
{ … }
static void
advance_with_locations(PyCodeAddressRange *bounds, int *endline, int *column, int *endcolumn)
{ … }
int
PyCode_Addr2Location(PyCodeObject *co, int addrq,
int *start_line, int *start_column,
int *end_line, int *end_column)
{ … }
static inline int
at_end(PyCodeAddressRange *bounds) { … }
int
_PyLineTable_PreviousAddressRange(PyCodeAddressRange *range)
{ … }
int
_PyLineTable_NextAddressRange(PyCodeAddressRange *range)
{ … }
static int
emit_pair(PyObject **bytes, int *offset, int a, int b)
{ … }
static int
emit_delta(PyObject **bytes, int bdelta, int ldelta, int *offset)
{ … }
static PyObject *
decode_linetable(PyCodeObject *code)
{ … }
lineiterator;
static void
lineiter_dealloc(lineiterator *li)
{ … }
static PyObject *
_source_offset_converter(int *value) { … }
static PyObject *
lineiter_next(lineiterator *li)
{ … }
PyTypeObject _PyLineIterator = …;
static lineiterator *
new_linesiterator(PyCodeObject *code)
{ … }
positionsiterator;
static void
positionsiter_dealloc(positionsiterator* pi)
{ … }
static PyObject*
positionsiter_next(positionsiterator* pi)
{ … }
PyTypeObject _PyPositionsIterator = …;
static PyObject*
code_positionsiterator(PyCodeObject* code, PyObject* Py_UNUSED(args))
{ … }
_PyCodeObjectExtra;
int
PyUnstable_Code_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
{ … }
int
PyUnstable_Code_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
{ … }
static PyObject *
get_cached_locals(PyCodeObject *co, PyObject **cached_field,
_PyLocals_Kind kind, int num)
{ … }
PyObject *
_PyCode_GetVarnames(PyCodeObject *co)
{ … }
PyObject *
PyCode_GetVarnames(PyCodeObject *code)
{ … }
PyObject *
_PyCode_GetCellvars(PyCodeObject *co)
{ … }
PyObject *
PyCode_GetCellvars(PyCodeObject *code)
{ … }
PyObject *
_PyCode_GetFreevars(PyCodeObject *co)
{ … }
PyObject *
PyCode_GetFreevars(PyCodeObject *code)
{ … }
#ifdef _Py_TIER2
static void
clear_executors(PyCodeObject *co)
{
assert(co->co_executors);
for (int i = 0; i < co->co_executors->size; i++) {
if (co->co_executors->executors[i]) {
_Py_ExecutorDetach(co->co_executors->executors[i]);
assert(co->co_executors->executors[i] == NULL);
}
}
PyMem_Free(co->co_executors);
co->co_executors = NULL;
}
void
_PyCode_Clear_Executors(PyCodeObject *code)
{
clear_executors(code);
}
#endif
static void
deopt_code(PyCodeObject *code, _Py_CODEUNIT *instructions)
{ … }
PyObject *
_PyCode_GetCode(PyCodeObject *co)
{ … }
PyObject *
PyCode_GetCode(PyCodeObject *co)
{ … }
static PyObject *
code_new_impl(PyTypeObject *type, int argcount, int posonlyargcount,
int kwonlyargcount, int nlocals, int stacksize, int flags,
PyObject *code, PyObject *consts, PyObject *names,
PyObject *varnames, PyObject *filename, PyObject *name,
PyObject *qualname, int firstlineno, PyObject *linetable,
PyObject *exceptiontable, PyObject *freevars,
PyObject *cellvars)
{ … }
static void
free_monitoring_data(_PyCoMonitoringData *data)
{ … }
static void
code_dealloc(PyCodeObject *co)
{ … }
#ifdef Py_GIL_DISABLED
static int
code_traverse(PyCodeObject *co, visitproc visit, void *arg)
{
Py_VISIT(co->co_consts);
return 0;
}
#endif
static PyObject *
code_repr(PyCodeObject *co)
{ … }
static PyObject *
code_richcompare(PyObject *self, PyObject *other, int op)
{ … }
static Py_hash_t
code_hash(PyCodeObject *co)
{ … }
#define OFF(x) …
static PyMemberDef code_memberlist[] = …;
static PyObject *
code_getlnotab(PyCodeObject *code, void *closure)
{ … }
static PyObject *
code_getvarnames(PyCodeObject *code, void *closure)
{ … }
static PyObject *
code_getcellvars(PyCodeObject *code, void *closure)
{ … }
static PyObject *
code_getfreevars(PyCodeObject *code, void *closure)
{ … }
static PyObject *
code_getcodeadaptive(PyCodeObject *code, void *closure)
{ … }
static PyObject *
code_getcode(PyCodeObject *code, void *closure)
{ … }
static PyGetSetDef code_getsetlist[] = …;
static PyObject *
code_sizeof(PyCodeObject *co, PyObject *Py_UNUSED(args))
{ … }
static PyObject *
code_linesiterator(PyCodeObject *code, PyObject *Py_UNUSED(args))
{ … }
static PyObject *
code_replace_impl(PyCodeObject *self, int co_argcount,
int co_posonlyargcount, int co_kwonlyargcount,
int co_nlocals, int co_stacksize, int co_flags,
int co_firstlineno, PyObject *co_code, PyObject *co_consts,
PyObject *co_names, PyObject *co_varnames,
PyObject *co_freevars, PyObject *co_cellvars,
PyObject *co_filename, PyObject *co_name,
PyObject *co_qualname, PyObject *co_linetable,
PyObject *co_exceptiontable)
{ … }
static PyObject *
code__varname_from_oparg_impl(PyCodeObject *self, int oparg)
{ … }
static struct PyMethodDef code_methods[] = …;
PyTypeObject PyCode_Type = …;
PyObject*
_PyCode_ConstantKey(PyObject *op)
{ … }
#ifdef Py_GIL_DISABLED
static PyObject *
intern_one_constant(PyObject *op)
{
PyInterpreterState *interp = _PyInterpreterState_GET();
_Py_hashtable_t *consts = interp->code_state.constants;
assert(!PyUnicode_CheckExact(op));
_Py_hashtable_entry_t *entry = _Py_hashtable_get_entry(consts, op);
if (entry == NULL) {
if (_Py_hashtable_set(consts, op, op) != 0) {
return NULL;
}
#ifdef Py_REF_DEBUG
Py_ssize_t refcnt = Py_REFCNT(op);
if (refcnt != 1) {
_Py_AddRefTotal(_PyThreadState_GET(), -(refcnt - 1));
}
#endif
_Py_SetImmortal(op);
return op;
}
assert(_Py_IsImmortal(entry->value));
return (PyObject *)entry->value;
}
static int
compare_constants(const void *key1, const void *key2) {
PyObject *op1 = (PyObject *)key1;
PyObject *op2 = (PyObject *)key2;
if (op1 == op2) {
return 1;
}
if (Py_TYPE(op1) != Py_TYPE(op2)) {
return 0;
}
if (PyTuple_CheckExact(op1)) {
Py_ssize_t size = PyTuple_GET_SIZE(op1);
if (size != PyTuple_GET_SIZE(op2)) {
return 0;
}
for (Py_ssize_t i = 0; i < size; i++) {
if (PyTuple_GET_ITEM(op1, i) != PyTuple_GET_ITEM(op2, i)) {
return 0;
}
}
return 1;
}
else if (PyFrozenSet_CheckExact(op1)) {
if (PySet_GET_SIZE(op1) != PySet_GET_SIZE(op2)) {
return 0;
}
Py_ssize_t pos1 = 0, pos2 = 0;
PyObject *obj1, *obj2;
Py_hash_t hash1, hash2;
while ((_PySet_NextEntry(op1, &pos1, &obj1, &hash1)) &&
(_PySet_NextEntry(op2, &pos2, &obj2, &hash2)))
{
if (obj1 != obj2) {
return 0;
}
}
return 1;
}
else if (PySlice_Check(op1)) {
PySliceObject *s1 = (PySliceObject *)op1;
PySliceObject *s2 = (PySliceObject *)op2;
return (s1->start == s2->start &&
s1->stop == s2->stop &&
s1->step == s2->step);
}
else if (PyBytes_CheckExact(op1) || PyLong_CheckExact(op1)) {
return PyObject_RichCompareBool(op1, op2, Py_EQ);
}
else if (PyFloat_CheckExact(op1)) {
double f1 = PyFloat_AS_DOUBLE(op1);
double f2 = PyFloat_AS_DOUBLE(op2);
return memcmp(&f1, &f2, sizeof(double)) == 0;
}
else if (PyComplex_CheckExact(op1)) {
Py_complex c1 = ((PyComplexObject *)op1)->cval;
Py_complex c2 = ((PyComplexObject *)op2)->cval;
return memcmp(&c1, &c2, sizeof(Py_complex)) == 0;
}
_Py_FatalErrorFormat("unexpected type in compare_constants: %s",
Py_TYPE(op1)->tp_name);
return 0;
}
static Py_uhash_t
hash_const(const void *key)
{
PyObject *op = (PyObject *)key;
if (PySlice_Check(op)) {
PySliceObject *s = (PySliceObject *)op;
PyObject *data[3] = { s->start, s->stop, s->step };
return Py_HashBuffer(&data, sizeof(data));
}
else if (PyTuple_CheckExact(op)) {
Py_ssize_t size = PyTuple_GET_SIZE(op);
PyObject **data = _PyTuple_ITEMS(op);
return Py_HashBuffer(data, sizeof(PyObject *) * size);
}
Py_hash_t h = PyObject_Hash(op);
if (h == -1) {
Py_FatalError("code: hash failed");
}
return (Py_uhash_t)h;
}
static int
clear_containers(_Py_hashtable_t *ht, const void *key, const void *value,
void *user_data)
{
PyObject *op = (PyObject *)key;
if (PyTuple_CheckExact(op)) {
for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(op); i++) {
Py_CLEAR(_PyTuple_ITEMS(op)[i]);
}
}
else if (PySlice_Check(op)) {
PySliceObject *slice = (PySliceObject *)op;
Py_SETREF(slice->start, Py_None);
Py_SETREF(slice->stop, Py_None);
Py_SETREF(slice->step, Py_None);
}
else if (PyFrozenSet_CheckExact(op)) {
_PySet_ClearInternal((PySetObject *)op);
}
return 0;
}
static void
destroy_key(void *key)
{
_Py_ClearImmortal(key);
}
#endif
PyStatus
_PyCode_Init(PyInterpreterState *interp)
{ … }
void
_PyCode_Fini(PyInterpreterState *interp)
{ … }