Author: Armin Rigo <ar...@tunes.org> Branch: cpyext-gc-support Changeset: r80337:21a3dead2ef1 Date: 2015-10-19 15:32 +0200 http://bitbucket.org/pypy/pypy/changeset/21a3dead2ef1/
Log: in-progress: from_pyobj() diff --git a/pypy/module/cpyext/intobject.py b/pypy/module/cpyext/intobject.py --- a/pypy/module/cpyext/intobject.py +++ b/pypy/module/cpyext/intobject.py @@ -19,11 +19,12 @@ @bootstrap_function def init_intobject(space): "Type description of PyIntObject" - from pypy.objspace.std.intobject import W_AbstractIntObject + from pypy.objspace.std.intobject import W_AbstractIntObject, W_IntObject setup_class_for_cpyext(W_AbstractIntObject, basestruct=PyIntObject.TO, - fill_pyobj=int_fill_pyobj) - #realize=int_realize) + fill_pyobj=int_fill_pyobj, + realize=int_realize, + realize_subclass_of=W_IntObject) def int_fill_pyobj(space, w_obj, py_int): """ @@ -32,15 +33,9 @@ """ py_int.c_ob_ival = space.int_w(w_obj) -def int_realize(space, obj): - intval = rffi.cast(lltype.Signed, rffi.cast(PyIntObject, obj).c_ob_ival) - w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) - w_obj = space.allocate_instance(W_IntObject, w_type) - w_obj.__init__(intval) - track_reference(space, obj, w_obj) - state = space.fromcache(RefcountState) - state.set_lifeline(w_obj, obj) - return w_obj +def int_realize(space, w_obj, py_obj): + intval = rffi.cast(lltype.Signed, rffi.cast(PyIntObject, py_obj).c_ob_ival) + W_IntObject.__init__(w_obj, intval) PyInt_Check, PyInt_CheckExact = build_type_checkers("Int") diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py --- a/pypy/module/cpyext/pyobject.py +++ b/pypy/module/cpyext/pyobject.py @@ -134,6 +134,7 @@ else: return _get_typedescr_1(typedef) + #________________________________________________________ # type description @@ -143,17 +144,20 @@ basestruct: The basic structure to allocate alloc_pyobj: default create_pyobj calls this to get the PyObject fill_pyobj: default create_pyobj calls this after attaching is done - realize : Function called to create a pypy object from a raw struct + realize : Function called to create a pypy object from a PyObject dealloc : a cpython_api(external=False), similar to PyObject_dealloc """ tp_basestruct = kw.pop('basestruct', PyObject.TO) tp_alloc_pyobj = kw.pop('alloc_pyobj', None) tp_fill_pyobj = kw.pop('fill_pyobj', None) - force_create_pyobj = kw.pop('force_create_pyobj', False) - #tp_realize = kw.pop('realize', None) + tp_realize = kw.pop('realize', None) + force_create_pyobj = kw.pop('force_create_pyobj', False) + realize_subclass_of = kw.pop('realize_subclass_of', None) #tp_dealloc = kw.pop('dealloc', None) - assert not kw, "Extra arguments to make_typedescr" + assert not kw, "Extra arguments to make_typedescr: %s" % kw.keys() + + assert 'cpyext_basestruct' not in W_Class.__dict__ # double set if tp_alloc_pyobj or tp_fill_pyobj or force_create_pyobj: # @@ -186,6 +190,22 @@ keepalive_until_here(self) W_Class.cpyext_fill_prebuilt_pyobj = cpyext_fill_prebuilt_pyobj + if tp_realize or realize_subclass_of: + W_CPyExtPlaceHolder = get_cpyextplaceholder_subclass( + realize_subclass_of or W_Class) + if tp_realize: + tp_realize._always_inline_ = True + # + def cpyext_realize(space, pyobj): + w_obj = W_CPyExtPlaceHolder(pyobj) + if tp_realize: + tp_realize(space, w_obj, pyobj) + return w_obj + # + typedef = realize_subclass_of.typedef + assert not hasattr(typedef, 'cpyext_realize') + typedef.cpyext_realize = cpyext_realize + W_Class.cpyext_basestruct = tp_basestruct @@ -210,13 +230,62 @@ ob = w_type.cpyext_create_pyobj(space) pto = rffi.cast(PyTypeObjectPtr, ob) return pto - W_TypeObject.cpyext_c_type_object = lltype.nullptr(PyTypeObjectPtr.TO) - @bootstrap_function def init_pyobject(space): - setup_class_for_cpyext(W_Root, force_create_pyobj=True) + setup_class_for_cpyext(W_Root, force_create_pyobj=True, + realize_subclass_of=W_ObjectObject) + + +#________________________________________________________ +# W_CPyExtPlaceHolderObject + +# When we ask for the convertion of a PyObject to a W_Root and there +# is none, we look up the correct W_Root subclass to use (W_IntObject, +# etc., or W_ObjectObject by default), take the W_CPyExtPlaceHolder +# special subclass of it, and instantiate that. W_CPyExtPlaceHolder +# adds the field "cpyext_pyobj" pointing back to the PyObject. +# W_CPyExtPlaceHolder is made using the following memo function. + +@specialize.memo() +def get_cpyextplaceholder_subclass(W_Class): + try: + return W_Class.__dict__['_cpyextplaceholder_subclass'] + except KeyError: + pass + assert W_Class is not W_TypeObject + + class W_CPyExtPlaceHolder(W_Class): + def __init__(self, pyobj): + self.cpyext_pyobj = pyobj + def cpyext_as_pyobj(self, space): + return self.cpyext_pyobj + + W_CPyExtPlaceHolder.__name__ = W_Class.__name__ + '_CPyExtPlaceHolder' + W_Class._cpyextplaceholder_subclass = W_CPyExtPlaceHolder + return W_CPyExtPlaceHolder + + + +def _default_cpyext_as_pyobj(self, space): + """Default implementation for most classes in PyPy. + Overridden by the W_CPyExtPlaceHolder subclasses.""" + ob = rawrefcount.from_obj(PyObject, self) + if not ob: + ob = self.cpyext_create_pyobj(space) + return ob +W_Root.cpyext_as_pyobj = _default_cpyext_as_pyobj + +def _type_cpyext_as_pyobj(self, space): + ob = get_c_ob_type(space, self) + return rffi.cast(PyObject, ob) +W_TypeObject.cpyext_as_pyobj = _type_cpyext_as_pyobj +W_TypeObject._cpyextplaceholder_subclass = W_TypeObject + +def _create_w_obj_from_pyobj(space, pyobj): + w_type = from_pyobj(pyobj.c_ob_type) + return w_type.instancetypedef.cpyext_realize(space, pyobj) #________________________________________________________ # refcounted object support @@ -385,13 +454,7 @@ use keepalive_until_here(w_obj) some time later. """ assert not is_pyobj(w_obj) - assert w_obj is not None - #if isinstance(w_obj, W_CPyExtPlaceHolderObject): - # xxx - ob = rawrefcount.from_obj(PyObject, w_obj) - if not ob: - ob = w_obj.cpyext_create_pyobj(space) - return ob + return w_obj.cpyext_as_pyobj(space) as_pyobj._always_inline_ = True def as_xpyobj(space, w_obj): @@ -408,7 +471,7 @@ pyobj = rffi.cast(PyObject, pyobj) w_obj = rawrefcount.to_obj(W_Root, pyobj) if w_obj is None: - w_obj = _create_w_obj_from_pyobj(pyobj) + w_obj = _create_w_obj_from_pyobj(space, pyobj) return w_obj from_pyobj._always_inline_ = True @@ -432,10 +495,7 @@ _about_ = is_pyobj def compute_result_annotation(self, s_x): from rpython.rtyper.llannotation import SomePtr - if isinstance(s_x, SomePtr): - return self.bookkeeper.immutablevalue(True) - else: - return self.bookkeeper.immutablevalue(False) + return self.bookkeeper.immutablevalue(isinstance(s_x, SomePtr)) def specialize_call(self, hop): hop.exception_cannot_occur() return hop.inputconst(lltype.Bool, hop.s_result.const) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit