Introduction
These are some notes about Python port development.
R13
About R13 stuff inside files DevEnv/include/pythonX.Y/object.h
and DevEnv/include/pythonX.Y/objimpl.h
:
The python library has been compiled using smalldata mode, more known on Amiga as baserel mode. This mode permits to all functions in the code to access to
global data variables using an indirect way (a pointer): the PowerPC R13 register points on the smalldata region where data are really stored. Practicaly, this mode permits
to make portage of POSIX codes like Python where globals scope is limited to the process, that's not the case on AmigaOS-like systems as MorphOS.
So it's really important that R13 register is kept valid before calling any Python library API.
That's easy to warranty when an external function try to call a function exported
by the Python library: the code of this function is in fact a trampoline function into the real function, that set R13 guessed from the library base pointer, before to jump into the real Python function.
Ok, but now think about this: Python types expose some functions pointer through the PyTypeObject
structure.
But these functions can be anything! Like an thirdparty module function or a Python itself function.
In this last case if this function is the previously mentionned trampoline, R13 will be set correctly. But if it's an internal function1) R13 is not set!!! So calling directly exposed functions in PyTypeObject is not safe.
The most worst case is that two functions really often used everywhere do these unsafe calls: it's _Py_Dealloc()
and PyObject_IS_GC
.
The first one is called by Py_DECREF()
when the object's refcount reaches 0.
The second one less occures but is unsafe also.
The problem of these functions is that's not functions, but in fact macros defined in public Python includes! So any possible code can call them, in particular a code where R13 is not set correctly before calling the Python code (where globals data are accessed).
To warranty that in any cases R13 register is set with the good pointer value, I save the current value, force on the correct one2), call the possible unsafe Python function3), then restore the old R13 value at return.
Note that this old R13 value is saved in R14 register: the ppc ABI (SysV) defines this register as non-volatile, used for local variable. So I stole this one to compiler from the possible registers range. But PowerPC as enough registers to do that…