Important
- The bytecode interpreter is a source of potential problems for us. Once the first few phases are in we need to really understand what it does and to what extent we need to enlighten it.
- Add a field to the object header to store the immutable state (used in later phase, so make ptr size)
- Make immortal
- Freeze performs object graph traversal and freezes all reachable objects
- Use tp_traverse to look at the fields of the object
- Look at type, which may or may not be returned by tp_traverse
- Look at mapping and list items if they have them
- Numpy etc will require recompiling against the new runtime.
- How do we use the flag in the object header to determine if a write is allowed?
- We need to intercept all setattr calls and check the flag
- Slice types in numpy will need to know about the underlying objects immutability
- Exceptions can be raised as late as possible. i.e., to the actual point of mutation.
- Places where Py_SET_TYPE() is called are worth keeping in mind when we add in regions. They are always places where weird things are happening.
- ADD_TYPE() calls in various places designate places where special types are being created on the fly. We need to ensure we handle dependent type generation properly wrt regions
- Do we need a new type flag to specify that the type supports deep immutability? tp_flags is a bitfield, so we could add a new flag.
- Add field
- DFS to set flag and immortal
- [makeimmutable]
- [isimmutable]
- [PyObject_Type]
- [PyObject_Dir/PyObject_GetAttr]
- [PySequence_Check/PySequence_GetItem]
- [PySequence_Fast/PySequence_Fast_ITEMS] (where appropriate)
- [PyMapping_Check/PyMapping_Items]
- Add NotWriteableError
- Checking flag on anything that could mutate.
- PyObject_SetItem (
mp_ass_subscript
,sq_ass_item
) - PySequence_SetItem (
sq_ass_item
) - PySequence_SetSlice (
mp_ass_subscript
) - PySequence_DelItem (
sq_ass_item
) - PySequence_DelSlice (
mp_ass_subscript
) - PyObject_DelItem (
mp_ass_subscript
,sq_ass_item
) - PyNumber_InPlaceAdd (
nb_inplace_add
,sq_inplace_concat
) - PySequence_InPlaceConcat (
sq_inplace_concat
,nb_inplace_add
) - PyNumber_InPlaceMultiply (
nb_inplace_multiply
,sq_inplace_repeat
) - PySequence_InPlaceRepeat (
sq_inplace_repeat
,nb_inplace_multiply
) - PyNumber_InPlacePower (
nb_inplace_power
) - INPLACE_BINOP Macro (
nb_inplace_or
,nb_inplace_xor
,nb_inplace_and
,nb_inplace_lshift
,nb_inplace_rshift
,nb_inplace_subtract
,nb_inplace_matrix_multiply
,nb_inplace_floor_divide
,nb_inplace_true_divide
,nb_inplace_remainder
) - PyObject_SetAttr (
tp_setattro
,tp_setattr
) - PyObject_GenericSetAttr
- PyObject_GenericSetDict
- PyObject_GetBuffer (
tp_as_buffer
, need to setreadonly
flag) - PyObject_AsWriteBuffer (see above)
- PyDict_SetItem
- [PyDict_SetDefault]
- PyDict_DelItem
- PyDict_Clear
- PyList_SetItem
- PyList_SetSlice
- PyList_Sort
- [list_sort_impl]
- PyList_Reverse
- [list_reverse_impl]
- PyList_Append
- [list_append_impl]
- PyList_Insert
- [list_insert_impl]
- [list_clear_impl]
- PySet_Add
- PySet_Pop
- PySet_Clear
- PySet_Discard
- [set_add]
- [set_remove]
- [set_discard]
- [set_clear]
- [set_pop]
- [set_update]
- PyTuple_SetItem
- PyException_SetTraceback
- PyException_SetCause
- PyException_SetContext
- PyException_SetArgs
- PyCell_Set
- DELETE_DEREF
- STORE_DEREF
- PyObject_SetItem (