(original) (raw)


On Sun, Feb 7, 2016 at 8:45 PM, Guido van Rossum <guido@python.org> wrote:
I think it's probably line 2649 in typeobject.c, in type\_new():

type->tp\_alloc = PyType\_GenericAlloc;
I pondered it but it doesn't seem to be that. Isn't \`type\_new\` called after PyType\_Type.tp\_alloc has been called? I thought that line was only being executed for user-defined types, and maybe some built-in types, but certainly not PyType\_Type.

On Sun, Feb 7, 2016 at 9:27 PM, eryk sun <eryksun@gmail.com> wrote:
On Sun, Feb 7, 2016 at 7:58 AM, Randy Eels <randyeels@gmail.com> wrote:
\>
\> Yet, I can't seem to understand where and when does the \`tp\_alloc\` slot of
\> PyType\_Type get re-assigned to PyType\_GenericAlloc. Does that even happen?
\> Or am I missing something bigger?

\_Py\_InitializeEx\_Private in Python/pylifecycle.c calls \_Py\_ReadyTypes
in Objects/object.c. This calls PyType\_Ready(&PyType\_Type) in
Objects/typeobject.c, which assigns type->tp\_base = &PyBaseObject\_Type
and then calls inherit\_slots. This executes COPYSLOT(tp\_alloc), which
assigns PyType\_Type.tp\_alloc = PyBaseObject\_Type.tp\_alloc, which is
statically assigned as PyType\_GenericAlloc.

Debug trace on Windows:

0:000> bp python35!PyType\_Ready
0:000> g
Breakpoint 0 hit
python35!PyType\_Ready:
00000000\`6502d160 4053 push rbx
0:000> ?? ((PyTypeObject \*)@rcx)->tp\_name
char \* 0x00000000\`650e4044
"object"
0:000> g
Breakpoint 0 hit
python35!PyType\_Ready:
00000000\`6502d160 4053 push rbx
0:000> ?? ((PyTypeObject \*)@rcx)->tp\_name
char \* 0x00000000\`651d8e5c
"type"
0:000> bp python35!inherit\_slots
0:000> g
Breakpoint 1 hit
python35!inherit\_slots:
00000000\`6502c440 48895c2408 mov qword ptr \[rsp+8\],rbx
ss:00000000\`0028f960={
python35!PyType\_Type
(00000000\`6527cba0)}

At entry to inherit\_slots, PyType\_Type.tp\_alloc is NULL:

0:000> ?? python35!PyType\_Type.tp\_alloc
\* 0x00000000\`00000000
0:000> pt
python35!inherit\_slots+0xd17:
00000000\`6502d157 c3 ret

At exit it's set to PyType\_GenericAlloc:

0:000> ?? python35!PyType\_Type.tp\_alloc
\* 0x00000000\`65025580
0:000> ln 65025580
(00000000\`65025580) python35!PyType\_GenericAlloc |
(00000000\`650256a0) python35!PyType\_GenericNew
Exact matches:
python35!PyType\_GenericAlloc (void)

This makes quite a bit of sense. I completely overlooked the interpreter init routines.

Thank you both Guido and eryk!