[pypy-svn] r28575 - in pypy/dist/pypy: rpython rpython/lltypesystem rpython/lltypesystem/test translator/c translator/c/src
arigo at codespeak.net
arigo at codespeak.net
Fri Jun 9 11:42:42 CEST 2006
Author: arigo
Date: Fri Jun 9 11:42:39 2006
New Revision: 28575
Modified:
pypy/dist/pypy/rpython/lltypesystem/lltype.py
pypy/dist/pypy/rpython/lltypesystem/rclass.py
pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py
pypy/dist/pypy/rpython/objectmodel.py
pypy/dist/pypy/rpython/rcpy.py
pypy/dist/pypy/rpython/rtyper.py
pypy/dist/pypy/translator/c/gc.py
pypy/dist/pypy/translator/c/genc.py
pypy/dist/pypy/translator/c/node.py
pypy/dist/pypy/translator/c/primitive.py
pypy/dist/pypy/translator/c/src/module.h
Log:
(arre, arigo)
Fixed the type objects of the hybrid RPython-CPython objects,
by creating a PyTypeObject structure with lltype.
Added rcpy.cpy_import() to cast from CPython to RPython.
lltype pointer solidity fix.
A convenient CDefinedIntSymbolic.
Wack wack wack until genc produces exactly the correct CPython-friendly
kind of code. GenC support for the _pyobjheaders of lltype.
Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Fri Jun 9 11:42:39 2006
@@ -752,7 +752,7 @@
raise TypeError, "%s has no field %r" % (CURTYPE, fieldname)
if not structptr:
raise RuntimeError("direct_fieldptr: NULL argument")
- return _subarray._makeptr(structptr._obj, fieldname)
+ return _subarray._makeptr(structptr._obj, fieldname, structptr._solid)
def direct_arrayitems(arrayptr):
"""Get a pointer to the first item of the array. The resulting
@@ -765,7 +765,7 @@
raise TypeError, "direct_arrayitems: not an array"
if not arrayptr:
raise RuntimeError("direct_arrayitems: NULL argument")
- return _subarray._makeptr(arrayptr._obj, 0)
+ return _subarray._makeptr(arrayptr._obj, 0, arrayptr._solid)
def direct_ptradd(ptr, n):
"""Shift a pointer forward or backward by n items. The pointer must
@@ -776,7 +776,7 @@
if not isinstance(ptr._obj, _subarray):
raise TypeError("direct_ptradd: only for direct_arrayitems() ptrs")
parent, base = parentlink(ptr._obj)
- return _subarray._makeptr(parent, base + n)
+ return _subarray._makeptr(parent, base + n, ptr._solid)
def _expose(val, solid=False):
"""XXX A nice docstring here"""
@@ -1130,7 +1130,7 @@
self._parent_type = typeOf(parent)
self._parent_index = parentindex
if (isinstance(self._parent_type, Struct)
- and parentindex == self._parent_type._names[0]
+ and parentindex in (self._parent_type._names[0], 0)
and self._TYPE._gckind == typeOf(parent)._gckind):
# keep strong reference to parent, we share the same allocation
self._keepparent = parent
@@ -1365,7 +1365,7 @@
else:
self._parentstructure().setitem(baseoffset + index, value)
- def _makeptr(parent, baseoffset_or_fieldname):
+ def _makeptr(parent, baseoffset_or_fieldname, solid=False):
cache = _subarray._cache.setdefault(parent, {})
try:
subarray = cache[baseoffset_or_fieldname]
@@ -1380,7 +1380,7 @@
ARRAYTYPE = FixedSizeArray(ITEMTYPE, 1)
subarray = _subarray(ARRAYTYPE, parent, baseoffset_or_fieldname)
cache[baseoffset_or_fieldname] = subarray
- return _ptr(Ptr(subarray._TYPE), subarray)
+ return _ptr(Ptr(subarray._TYPE), subarray, solid)
_makeptr = staticmethod(_makeptr)
Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Fri Jun 9 11:42:39 2006
@@ -485,8 +485,14 @@
mallocop = 'flavored_malloc'
vlist.insert(0, inputconst(Void, flavor))
if flavor == 'cpy':
- cpytype = self.classdef._cpy_exported_type_
- c = inputconst(Ptr(PyObject), lltype.pyobjectptr(cpytype))
+ cache = self.rtyper.classdef_to_pytypeobject
+ try:
+ pytype = cache[self.classdef]
+ except KeyError:
+ from pypy.rpython import rcpy
+ pytype = rcpy.build_pytypeobject(self)
+ cache[self.classdef] = pytype
+ c = inputconst(Ptr(PyObject), pytype)
vlist.append(c)
vptr = llops.genop(mallocop, vlist,
resulttype = Ptr(self.object_type))
Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py Fri Jun 9 11:42:39 2006
@@ -1,5 +1,5 @@
from pypy.translator.c.test.test_genc import compile
-from pypy.rpython.rcpy import cpy_export
+from pypy.rpython.rcpy import cpy_export, cpy_import
class W_MyTest(object):
@@ -17,8 +17,26 @@
def f():
w = W_MyTest(21)
- return cpy_export(w, mytest)
+ return cpy_export(mytest, w)
fn = compile(f, [])
res = fn()
- assert type(res).__name__.endswith('mytest')
+ assert type(res).__name__ == 'mytest'
+
+
+def test_cpy_import():
+ class mytest(object):
+ pass
+
+ def f():
+ w = W_MyTest(21)
+ return cpy_export(mytest, w)
+
+ def g():
+ obj = f()
+ w = cpy_import(W_MyTest, obj)
+ return w.double()
+
+ fn = compile(g, [])
+ res = fn()
+ assert res == 42
Modified: pypy/dist/pypy/rpython/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/objectmodel.py (original)
+++ pypy/dist/pypy/rpython/objectmodel.py Fri Jun 9 11:42:39 2006
@@ -35,6 +35,19 @@
from pypy.rpython.lltypesystem import lltype
return lltype.Signed
+class CDefinedIntSymbolic(Symbolic):
+
+ def __init__(self, expr):
+ self.expr = expr
+
+ def annotation(self):
+ from pypy.annotation import model
+ return model.SomeInteger()
+
+ def lltype(self):
+ from pypy.rpython.lltypesystem import lltype
+ return lltype.Signed
+
def instantiate(cls):
"Create an empty instance of 'cls'."
Modified: pypy/dist/pypy/rpython/rcpy.py
==============================================================================
--- pypy/dist/pypy/rpython/rcpy.py (original)
+++ pypy/dist/pypy/rpython/rcpy.py Fri Jun 9 11:42:39 2006
@@ -1,14 +1,19 @@
from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.objectmodel import CDefinedIntSymbolic
-def cpy_export(obj, cpytype):
+def cpy_export(cpytype, obj):
+ raise NotImplementedError("only works in translated versions")
+
+def cpy_import(rpytype, obj):
raise NotImplementedError("only works in translated versions")
class Entry(ExtRegistryEntry):
_about_ = cpy_export
- def compute_result_annotation(self, s_obj, s_cpytype):
+ def compute_result_annotation(self, s_cpytype, s_obj):
from pypy.annotation.model import SomeObject
from pypy.annotation.model import SomeInstance
assert isinstance(s_obj, SomeInstance)
@@ -24,7 +29,79 @@
def specialize_call(self, hop):
from pypy.rpython.lltypesystem import lltype
- r_inst = hop.args_r[0]
- v_inst = hop.inputarg(r_inst, arg=0)
+ s_obj = hop.args_s[1]
+ r_inst = hop.args_r[1]
+ v_inst = hop.inputarg(r_inst, arg=1)
return hop.genop('cast_pointer', [v_inst],
resulttype = lltype.Ptr(lltype.PyObject))
+
+
+class Entry(ExtRegistryEntry):
+ _about_ = cpy_import
+
+ def compute_result_annotation(self, s_rpytype, s_obj):
+ from pypy.annotation.bookkeeper import getbookkeeper
+ from pypy.annotation.model import SomeInstance
+ assert s_rpytype.is_constant()
+ rpytype = s_rpytype.const
+ bk = getbookkeeper()
+ return SomeInstance(bk.getuniqueclassdef(rpytype))
+
+ def specialize_call(self, hop):
+ from pypy.annotation.model import SomeInstance
+ from pypy.rpython.robject import pyobj_repr
+ s_rpytype = hop.args_s[0]
+ assert s_rpytype.is_constant()
+ rpytype = s_rpytype.const
+ classdef = hop.rtyper.annotator.bookkeeper.getuniqueclassdef(rpytype)
+ s_inst = SomeInstance(classdef)
+ r_inst = hop.rtyper.getrepr(s_inst)
+ assert r_inst.lowleveltype.TO._gckind == 'cpy'
+ v_obj = hop.inputarg(pyobj_repr, arg=1)
+ return hop.genop('cast_pointer', [v_obj],
+ resulttype = r_inst.lowleveltype)
+
+
+PyObjPtr = lltype.Ptr(lltype.PyObject)
+
+PY_TYPE_OBJECT = lltype.PyStruct(
+ 'PyTypeObject',
+ ('head', lltype.PyObject),
+ ('c_ob_size', lltype.Signed),
+ ('c_tp_name', lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1))),
+ ('c_tp_basicsize', lltype.Signed),
+ ('c_tp_itemsize', lltype.Signed),
+ ('c_tp_dealloc', lltype.Signed),
+ ('c_tp_print', lltype.Signed),
+ ('c_tp_getattr', lltype.Signed),
+ ('c_tp_setattr', lltype.Signed), # in
+ ('c_tp_compare', lltype.Signed),
+ ('c_tp_repr', lltype.Signed), # progress
+ ('c_tp_as_number', lltype.Signed),
+ ('c_tp_as_sequence',lltype.Signed),
+ ('c_tp_as_mapping',lltype.Signed),
+ ('c_tp_hash', lltype.Signed),
+ ('c_tp_call', lltype.Signed),
+ ('c_tp_str', lltype.Signed),
+ ('c_tp_getattro', lltype.Signed),
+ ('c_tp_setattro', lltype.Signed),
+ ('c_tp_as_buffer', lltype.Signed),
+ ('c_tp_flags', lltype.Signed),
+
+ hints={'c_name': '_typeobject', 'external': True, 'inline_head': True})
+# XXX should be PyTypeObject but genc inserts 'struct' :-(
+
+def build_pytypeobject(r_inst):
+ typetype = lltype.pyobjectptr(type)
+ pytypeobj = lltype.malloc(PY_TYPE_OBJECT, flavor='cpy',
+ extra_args=(typetype,))
+ name = r_inst.classdef._cpy_exported_type_.__name__
+ T = lltype.FixedSizeArray(lltype.Char, len(name)+1)
+ p = lltype.malloc(T, immortal=True)
+ for i in range(len(name)):
+ p[i] = name[i]
+ p[len(name)] = '\x00'
+ pytypeobj.c_tp_name = lltype.direct_arrayitems(p)
+ pytypeobj.c_tp_basicsize = llmemory.sizeof(r_inst.lowleveltype.TO)
+ pytypeobj.c_tp_flags = CDefinedIntSymbolic('Py_TPFLAGS_DEFAULT')
+ return lltype.cast_pointer(PyObjPtr, pytypeobj)
Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py (original)
+++ pypy/dist/pypy/rpython/rtyper.py Fri Jun 9 11:42:39 2006
@@ -60,6 +60,7 @@
self.pbc_reprs = {}
self.classes_with_wrapper = {}
self.wrapper_context = None # or add an extra arg to convertvar?
+ self.classdef_to_pytypeobject = {}
self.concrete_calltables = {}
self.class_pbc_attributes = {}
self.oo_meth_impls = {}
Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py (original)
+++ pypy/dist/pypy/translator/c/gc.py Fri Jun 9 11:42:39 2006
@@ -2,13 +2,11 @@
from pypy.translator.c.support import cdecl
from pypy.translator.c.node import ContainerNode
from pypy.rpython.lltypesystem.lltype import \
- typeOf, Ptr, PyObject, ContainerType, GcArray, GcStruct, \
+ typeOf, Ptr, ContainerType, GcArray, GcStruct, \
RuntimeTypeInfo, getRuntimeTypeInfo, top_container
from pypy.rpython.memory import gctransform
from pypy.rpython.lltypesystem import lltype, llmemory
-PyObjPtr = Ptr(PyObject)
-
class BasicGcPolicy(object):
requires_stackless = False
@@ -63,13 +61,7 @@
class RefcountingInfo:
static_deallocator = None
-from pypy.rpython.objectmodel import Symbolic
-class REFCOUNT_IMMORTAL(Symbolic):
- def annotation(self):
- from pypy.annotation.model import SomeInteger
- return SomeInteger()
- def lltype(self):
- return lltype.Signed
+from pypy.rpython.objectmodel import CDefinedIntSymbolic
class RefcountingGcPolicy(BasicGcPolicy):
transformerclass = gctransform.RefcountingGCTransformer
@@ -78,7 +70,7 @@
return [('refcount', lltype.Signed)]
def common_gcheader_initdata(self, defnode):
- return [REFCOUNT_IMMORTAL()]
+ return [CDefinedIntSymbolic('REFCOUNT_IMMORTAL')]
# for structs
Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py (original)
+++ pypy/dist/pypy/translator/c/genc.py Fri Jun 9 11:42:39 2006
@@ -1,6 +1,6 @@
import autopath
import py
-from pypy.translator.c.node import PyObjectNode, FuncNode
+from pypy.translator.c.node import PyObjectNode, PyObjHeadNode, FuncNode
from pypy.translator.c.database import LowLevelDatabase
from pypy.translator.c.extfunc import pre_include_code_lines
from pypy.translator.gensupp import uniquemodulename, NameManager
@@ -689,10 +689,17 @@
print >> f
print >> f, 'static globalobjectdef_t globalobjectdefs[] = {'
for node in database.globalcontainers():
- if isinstance(node, PyObjectNode):
+ if isinstance(node, (PyObjectNode, PyObjHeadNode)):
for target in node.where_to_copy_me:
- print >> f, '\t{%s, "%s"},' % (target, node.name)
- print >> f, '\t{ NULL }\t/* Sentinel */'
+ print >> f, '\t{%s, "%s"},' % (target, node.exported_name)
+ print >> f, '\t{ NULL, NULL }\t/* Sentinel */'
+ print >> f, '};'
+ print >> f
+ print >> f, 'static cpyobjheaddef_t cpyobjheaddefs[] = {'
+ for node in database.containerlist:
+ if isinstance(node, PyObjHeadNode):
+ print >> f, '\t{"%s", %s},' % (node.exported_name, node.ptrname)
+ print >> f, '\t{ NULL, NULL }\t/* Sentinel */'
print >> f, '};'
print >> f
print >> f, '/***********************************************************/'
Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py (original)
+++ pypy/dist/pypy/translator/c/node.py Fri Jun 9 11:42:39 2006
@@ -1,9 +1,9 @@
from __future__ import generators
from pypy.rpython.lltypesystem.lltype import \
Struct, Array, FixedSizeArray, FuncType, PyObjectType, typeOf, \
- GcStruct, GcArray, ContainerType, \
+ GcStruct, GcArray, PyStruct, ContainerType, \
parentlink, Ptr, PyObject, Void, OpaqueType, Float, \
- RuntimeTypeInfo, getRuntimeTypeInfo, Char, _subarray
+ RuntimeTypeInfo, getRuntimeTypeInfo, Char, _subarray, _pyobjheader
from pypy.rpython.lltypesystem.llmemory import WeakGcAddress
from pypy.translator.c.funcgen import FunctionCodeGenerator
from pypy.translator.c.external import CExternalFunctionCodeGenerator
@@ -16,7 +16,7 @@
def needs_gcheader(T):
if not isinstance(T, ContainerType):
return False
- if T._gckind == 'raw':
+ if T._gckind != 'gc':
return False
if isinstance(T, GcStruct):
if T._first_struct() != (None, None):
@@ -60,6 +60,9 @@
def setup(self):
# this computes self.fields
+ if self.STRUCT._hints.get('external'): # XXX hack
+ self.fields = None # external definition only
+ return
self.fields = []
db = self.db
STRUCT = self.STRUCT
@@ -101,22 +104,41 @@
return self.prefix + name
def verbatim_field_name(self, name):
- assert name.startswith('c_') # produced in this way by rctypes
- return name[2:]
+ if name.startswith('c_'): # produced in this way by rctypes
+ return name[2:]
+ else:
+ # field names have to start with 'c_' or be meant for names that
+ # vanish from the C source, like 'head' if 'inline_head' is set
+ raise Exception("field %r should not be accessed in this way" % (
+ name,))
def c_struct_field_type(self, name):
return self.STRUCT._flds[name]
def access_expr(self, baseexpr, fldname):
+ if self.STRUCT._hints.get('inline_head'):
+ first, FIRST = self.STRUCT._first_struct()
+ if fldname == first:
+ # "invalid" cast according to C99 but that's what CPython
+ # requires and does all the time :-/
+ return '(*(%s) &(%s))' % (cdecl(self.db.gettype(FIRST), '*'),
+ baseexpr)
fldname = self.c_struct_field_name(fldname)
return '%s.%s' % (baseexpr, fldname)
def ptr_access_expr(self, baseexpr, fldname):
+ if self.STRUCT._hints.get('inline_head'):
+ first, FIRST = self.STRUCT._first_struct()
+ if fldname == first:
+ # "invalid" cast according to C99 but that's what CPython
+ # requires and does all the time :-/
+ return '(*(%s) %s)' % (cdecl(self.db.gettype(FIRST), '*'),
+ baseexpr)
fldname = self.c_struct_field_name(fldname)
return '%s->%s' % (baseexpr, fldname)
def definition(self):
- if self.STRUCT._hints.get('external'): # XXX hack
+ if self.fields is None: # external definition only
return
yield 'struct %s {' % self.name
is_empty = True
@@ -421,10 +443,13 @@
data.append((name, getattr(self.obj, name)))
for name, value in data:
- c_name = defnode.c_struct_field_name(name)
- lines = generic_initializationexpr(self.db, value,
- '%s.%s' % (self.name, c_name),
- decoration + name)
+ if isinstance(value, _pyobjheader): # hack
+ node = self.db.getcontainernode(value)
+ lines = [node.pyobj_initexpr()]
+ else:
+ c_expr = defnode.access_expr(self.name, name)
+ lines = generic_initializationexpr(self.db, value, c_expr,
+ decoration + name)
for line in lines:
yield '\t' + line
if not lines[0].startswith('/*'):
@@ -711,6 +736,7 @@
self.obj = obj
self.name = db.pyobjmaker.computenameof(obj.value)
self.ptrname = self.name
+ self.exported_name = self.name
# a list of expressions giving places where this constant PyObject
# must be copied. Normally just in the global variable of the same
# name, but see also StructNode.initializationexpr() :-(
@@ -725,13 +751,44 @@
return []
+class PyObjHeadNode(ContainerNode):
+ nodekind = 'pyobj'
+
+ def __init__(self, db, T, obj):
+ ContainerNode.__init__(self, db, T, obj)
+ self.where_to_copy_me = []
+ self.exported_name = db.namespace.uniquename('cpyobj')
+
+ def basename(self):
+ raise Exception("PyObjHead should always have a parent")
+
+ def enum_dependencies(self):
+ yield self.obj.ob_type
+
+ def pyobj_initexpr(self):
+ parent, parentindex = parentlink(self.obj)
+ assert typeOf(parent)._hints.get('inline_head')
+ typenode = self.db.getcontainernode(self.obj.ob_type._obj)
+ typenode.where_to_copy_me.append('(PyObject **) & %s.ob_type' % (
+ self.name,))
+ return 'PyObject_HEAD_INIT(NULL)'
+
+
+def objectnode_factory(db, T, obj):
+ if isinstance(obj, _pyobjheader):
+ return PyObjHeadNode(db, T, obj)
+ else:
+ return PyObjectNode(db, T, obj)
+
+
ContainerNodeFactory = {
Struct: StructNode,
GcStruct: StructNode,
+ PyStruct: StructNode,
Array: ArrayNode,
GcArray: ArrayNode,
FixedSizeArray: FixedSizeArrayNode,
FuncType: FuncNode,
OpaqueType: opaquenode_factory,
- PyObjectType: PyObjectNode,
+ PyObjectType: objectnode_factory,
}
Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py (original)
+++ pypy/dist/pypy/translator/c/primitive.py Fri Jun 9 11:42:39 2006
@@ -1,5 +1,6 @@
import sys
from pypy.rpython.objectmodel import Symbolic, ComputedIntSymbolic
+from pypy.rpython.objectmodel import CDefinedIntSymbolic
from pypy.rpython.lltypesystem.lltype import *
from pypy.rpython.lltypesystem.llmemory import Address, fakeaddress, \
AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \
@@ -14,7 +15,6 @@
def name_signed(value, db):
if isinstance(value, Symbolic):
- from pypy.translator.c.gc import REFCOUNT_IMMORTAL
if isinstance(value, FieldOffset):
structnode = db.gettypedefnode(value.TYPE)
return 'offsetof(%s, %s)'%(
@@ -39,8 +39,8 @@
return '0'
elif type(value) == GCHeaderOffset:
return '0'
- elif type(value) == REFCOUNT_IMMORTAL:
- return 'REFCOUNT_IMMORTAL'
+ elif isinstance(value, CDefinedIntSymbolic):
+ return str(value.expr)
elif isinstance(value, ComputedIntSymbolic):
value = value.compute_fn()
else:
Modified: pypy/dist/pypy/translator/c/src/module.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/module.h (original)
+++ pypy/dist/pypy/translator/c/src/module.h Fri Jun 9 11:42:39 2006
@@ -40,7 +40,7 @@
return; \
if (setup_initcode(frozen_initcode, FROZEN_INITCODE_SIZE) < 0) \
return; \
- if (setup_globalobjects(globalobjectdefs) < 0) \
+ if (setup_globalobjects(globalobjectdefs, cpyobjheaddefs) < 0) \
return;
/*** table of global objects ***/
@@ -53,6 +53,11 @@
} globalobjectdef_t;
typedef struct {
+ char* name;
+ PyObject* cpyobj;
+} cpyobjheaddef_t;
+
+typedef struct {
PyObject** p;
char* gfunc_name;
PyMethodDef ml;
@@ -69,11 +74,29 @@
#ifndef PYPY_NOT_MAIN_FILE
-static int setup_globalobjects(globalobjectdef_t* def)
+static int setup_globalobjects(globalobjectdef_t* globtable,
+ cpyobjheaddef_t* cpyheadtable)
{
PyObject* obj;
-
- for (; def->p != NULL; def++) {
+ globalobjectdef_t* def;
+ cpyobjheaddef_t* cpydef;
+
+ /* Store the object given by their heads into the module's dict.
+ Warning: these object heads might still be invalid, e.g.
+ typically their ob_type needs patching!
+ But PyDict_SetItemString() doesn't inspect them...
+ */
+ for (cpydef = cpyheadtable; cpydef->name != NULL; cpydef++) {
+ obj = cpydef->cpyobj;
+ if (PyDict_SetItemString(this_module_globals,
+ cpydef->name, obj) < 0)
+ return -1;
+ }
+ /* Patch all locations that need to contain a specific PyObject*.
+ This must go after the previous loop, otherwise
+ PyDict_GetItemString() might not find some of them.
+ */
+ for (def = globtable; def->p != NULL; def++) {
obj = PyDict_GetItemString(this_module_globals, def->name);
if (obj == NULL) {
PyErr_Format(PyExc_AttributeError,
@@ -84,6 +107,16 @@
Py_INCREF(obj);
*def->p = obj; /* store the object ref in the global var */
}
+ /* All objects should be valid at this point. Loop again and
+ make sure all types are ready.
+ */
+ for (cpydef = cpyheadtable; cpydef->name != NULL; cpydef++) {
+ obj = cpydef->cpyobj;
+ if (PyType_Check(obj)) {
+ if (PyType_Ready((PyTypeObject*) obj) < 0)
+ return -1;
+ }
+ }
return 0;
}
More information about the Pypy-commit
mailing list