Closed
Description
Currently the symbol structure looks like this:
struct _Py_UopsSymbol {
int flags; // 0 bits: Top; 2 or more bits: Bottom
PyTypeObject *typ; // Borrowed reference
PyObject *const_val; // Owned reference (!)
unsigned int type_version; // currently stores type version
};
which is both hard to use and inefficient. This awkwardness is effectively blocking 2 PRs: python/cpython#119478 and python/cpython#121002 as I am not willing to risk introducing bugs.
We should change the symbol to a tagged union:
union _Py_UopSymbol {
uint8_t tag;
_PyUopSym_Instance instance;
_PyUopSym_Value value;
_PyUopSym_Function func;
_PyUopSym_Tuple tuple;
...
}
Each of the subtypes would start with uint8_t tag;
and should be no larger than 16 bytes (on a 64bit machine).
E.g.
struct _PyUopSym_Instance {
uint8_t tag;
PyTypeObject *typ; // Borrowed reference
};
All operations would take the form of a switch statement. Using an enum
for the tag would allow the C compiler to generate warnings when a case was forgotten.
E.g.
bool
_Py_uop_sym_matches_type(_Py_UopsSymbol *sym, PyTypeObject *typ)
{
switch(sym->tag) {
case INSTANCE_TAG:
return sym->instance.typ == typ;
case VALUE_TAG:
return Py_TYPE(sym->value.value) == typ;
...
This is nothing novel, just good engineering practice.
Metadata
Metadata
Assignees
Labels
No labels