[pypy-commit] pypy cpyext-gc-support: Starting to rewrite cpyext, add a lot of ZZZ
arigo
noreply at buildbot.pypy.org
Wed Oct 14 14:05:55 EDT 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-gc-support
Changeset: r80215:8e73db7caf49
Date: 2015-10-14 20:06 +0200
http://bitbucket.org/pypy/pypy/changeset/8e73db7caf49/
Log: Starting to rewrite cpyext, add a lot of ZZZ
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -286,75 +286,67 @@
@specialize.ll()
def unwrapper(space, *args):
from pypy.module.cpyext.pyobject import Py_DecRef
- from pypy.module.cpyext.pyobject import make_ref, from_ref
+ from pypy.module.cpyext.pyobject import as_pyobj, is_pyobj
from pypy.module.cpyext.pyobject import Reference
newargs = ()
- to_decref = []
assert len(args) == len(api_function.argtypes)
for i, (ARG, is_wrapped) in types_names_enum_ui:
input_arg = args[i]
if is_PyObject(ARG) and not is_wrapped:
- # build a reference
- if input_arg is None:
- arg = lltype.nullptr(PyObject.TO)
- elif isinstance(input_arg, W_Root):
- ref = make_ref(space, input_arg)
- to_decref.append(ref)
- arg = rffi.cast(ARG, ref)
+ # build a 'PyObject *' (not holding a reference)
+ if not is_pyobj(input_arg):
+ input_arg = as_pyobj(input_arg)
+ arg = rffi.cast(ARG, input_arg)
+ elif is_PyObject(ARG) and is_wrapped:
+ # convert to a wrapped object
+ if is_pyobj(input_arg):
+ arg = from_ref(input_arg)
else:
arg = input_arg
- elif is_PyObject(ARG) and is_wrapped:
- # convert to a wrapped object
- if input_arg is None:
- arg = input_arg
- elif isinstance(input_arg, W_Root):
- arg = input_arg
- else:
- try:
- arg = from_ref(space,
- rffi.cast(PyObject, input_arg))
- except TypeError, e:
- err = OperationError(space.w_TypeError,
- space.wrap(
- "could not cast arg to PyObject"))
- if not catch_exception:
- raise err
- state = space.fromcache(State)
- state.set_exception(err)
- if is_PyObject(restype):
- return None
- else:
- return api_function.error_value
+
+ ## ZZZ: for is_pyobj:
+ ## try:
+ ## arg = from_ref(space,
+ ## rffi.cast(PyObject, input_arg))
+ ## except TypeError, e:
+ ## err = OperationError(space.w_TypeError,
+ ## space.wrap(
+ ## "could not cast arg to PyObject"))
+ ## if not catch_exception:
+ ## raise err
+ ## state = space.fromcache(State)
+ ## state.set_exception(err)
+ ## if is_PyObject(restype):
+ ## return None
+ ## else:
+ ## return api_function.error_value
else:
- # convert to a wrapped object
+ # arg is not declared as PyObject, no magic
arg = input_arg
newargs += (arg, )
try:
- try:
- res = func(space, *newargs)
- except OperationError, e:
- if not catch_exception:
- raise
- if not hasattr(api_function, "error_value"):
- raise
- state = space.fromcache(State)
- state.set_exception(e)
- if is_PyObject(restype):
- return None
- else:
- return api_function.error_value
- if not we_are_translated():
- got_integer = isinstance(res, (int, long, float))
- assert got_integer == expect_integer,'got %r not integer' % res
- if res is None:
+ res = func(space, *newargs)
+ except OperationError, e:
+ if not catch_exception:
+ raise
+ if not hasattr(api_function, "error_value"):
+ raise
+ state = space.fromcache(State)
+ state.set_exception(e)
+ if is_PyObject(restype):
return None
- elif isinstance(res, Reference):
- return res.get_wrapped(space)
else:
- return res
- finally:
- for arg in to_decref:
- Py_DecRef(space, arg)
+ return api_function.error_value
+ if not we_are_translated():
+ got_integer = isinstance(res, (int, long, float))
+ assert got_integer == expect_integer,'got %r not integer' % res
+ ZZZ # where is the logic to return PyObject??
+ if res is None:
+ return None
+ elif isinstance(res, Reference):
+ return res.get_wrapped(space)
+ else:
+ return res
unwrapper.func = func
unwrapper.api_func = api_function
unwrapper._always_inline_ = 'try'
@@ -730,9 +722,9 @@
compilation_info=eci, _nowrapper=True)
def init_types(space):
from pypy.module.cpyext.typeobject import py_type_ready
- py_type_ready(space, get_buffer_type())
- py_type_ready(space, get_cobject_type())
- py_type_ready(space, get_capsule_type())
+ #py_type_ready(space, get_buffer_type()) ZZZ
+ #py_type_ready(space, get_cobject_type()) ZZZ
+ #py_type_ready(space, get_capsule_type()) ZZZ
INIT_FUNCTIONS.append(init_types)
from pypy.module.posix.interp_posix import add_fork_hook
reinit_tls = rffi.llexternal('%sThread_ReInitTLS' % prefix, [], lltype.Void,
@@ -831,7 +823,8 @@
space.fromcache(State).install_dll(eci)
# populate static data
- for name, (typ, expr) in GLOBALS.iteritems():
+ if 0: # ZZZ
+ for name, (typ, expr) in GLOBALS.iteritems():
from pypy.module import cpyext
w_obj = eval(expr)
if name.endswith('#'):
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
@@ -1,16 +1,16 @@
import sys
from pypy.interpreter.baseobjspace import W_Root, SpaceCache
-from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
from pypy.module.cpyext.api import (
cpython_api, bootstrap_function, PyObject, PyObjectP, ADDR,
- CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr)
+ CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr, is_PyObject)
from pypy.module.cpyext.state import State
from pypy.objspace.std.typeobject import W_TypeObject
from pypy.objspace.std.objectobject import W_ObjectObject
from rpython.rlib.objectmodel import specialize, we_are_translated
-from rpython.rlib.rweakref import RWeakKeyDictionary
from rpython.rtyper.annlowlevel import llhelper
+from rpython.rlib import rawrefcount
#________________________________________________________
# type description
@@ -136,6 +136,7 @@
class RefcountState:
def __init__(self, space):
+ ZZZ
self.space = space
self.py_objects_w2r = {} # { w_obj -> raw PyObject }
self.py_objects_r2w = {} # { addr of raw PyObject -> w_obj }
@@ -251,6 +252,7 @@
Allocates a PyObject, and fills its fields with info from the given
intepreter object.
"""
+ ZZZ
state = space.fromcache(RefcountState)
w_type = space.type(w_obj)
if w_type.is_cpytype():
@@ -270,6 +272,7 @@
"""
Ties together a PyObject and an interpreter object.
"""
+ ZZZ
# XXX looks like a PyObject_GC_TRACK
ptr = rffi.cast(ADDR, py_obj)
state = space.fromcache(RefcountState)
@@ -282,12 +285,62 @@
if ptr: # init_typeobject() bootstraps with NULL references
state.py_objects_r2w[ptr] = w_obj
-def make_ref(space, w_obj):
+
+NULL_GCREF = lltype.nullptr(llmemory.GCREF.TO)
+
+def _create_pyobj_from_w_obj(w_obj):
+ # XXX temp, needs cases
+ ob = lltype.malloc(PyObject, flavor='raw', track_allocation=False)
+ ob.ob_refcnt = 0
+ ob.ob_pypy_link = NULL_GCREF
+ rawrefcount.create_link_pypy(w_obj, ob)
+ return ob
+
+
+def as_pyobj(w_obj):
"""
- Returns a new reference to an intepreter object.
+ Returns a 'PyObject *' representing the given intepreter object.
+ 'None' is returned as a NULL. This doesn't give a new reference, but
+ the returned 'PyObject *' is valid at least as long as 'w_obj' is.
"""
+ assert is_wrapped(w_obj)
if w_obj is None:
return lltype.nullptr(PyObject.TO)
+ #if isinstance(w_obj, W_CPyExtPlaceHolderObject):
+ # xxx
+ ob = rawrefcount.from_obj(PyObject.TO, w_obj)
+ if not ob:
+ ob = _create_pyobj_from_w_obj(w_obj)
+ return ob
+as_pyobj._always_inline_ = True
+
+
+ at specialize.ll()
+def from_ref(pyobj):
+ assert not is_wrapped(pyobj)
+ if not pyobj:
+ return None
+ 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)
+ return w_obj
+from_ref._always_inline_ = True
+
+
+def is_pyobj(x):
+ "NOT_RPYTHON"
+ if x is None or isinstance(x, W_Root):
+ return False
+ else:
+ assert is_PyObject(lltype.typeOf(x))
+ return True
+
+# ZZZ: use an ExtRegistryEntry to constant-fold is_pyobj()
+
+
+def make_ref(space, w_obj):
+ ZZZ
assert isinstance(w_obj, W_Root)
state = space.fromcache(RefcountState)
try:
@@ -300,7 +353,7 @@
return py_obj
-def from_ref(space, ref):
+def ZZZ_from_ref(space, ref):
"""
Finds the interpreter object corresponding to the given reference. If the
object is not yet realized (see stringobject.py), creates it.
@@ -390,6 +443,7 @@
class PyOLifeline(object):
def __init__(self, space, pyo):
+ ZZZ
self.pyo = pyo
self.space = space
@@ -408,6 +462,7 @@
Create a borrowed reference, which will live as long as the container
has a living reference (as a PyObject!)
"""
+ ZZZ
if w_borrowed is None:
return lltype.nullptr(PyObject.TO)
@@ -416,6 +471,7 @@
class Reference:
def __init__(self, pyobj):
+ ZZZ
assert not isinstance(pyobj, W_Root)
self.pyobj = pyobj
@@ -430,6 +486,7 @@
Delays the creation of a borrowed reference.
"""
def __init__(self, w_container, w_borrowed):
+ ZZZ
self.w_container = w_container
self.w_borrowed = w_borrowed
diff --git a/pypy/module/cpyext/test/test_api.py b/pypy/module/cpyext/test/test_api.py
--- a/pypy/module/cpyext/test/test_api.py
+++ b/pypy/module/cpyext/test/test_api.py
@@ -49,21 +49,24 @@
return state.clear_exception()
def setup_method(self, func):
+ return # ZZZ
freeze_refcnts(self)
def teardown_method(self, func):
- state = self.space.fromcache(State)
- try:
- state.check_and_raise_exception()
- except OperationError, e:
- print e.errorstr(self.space)
- raise
+ if 0: # ZZZ
+ state = self.space.fromcache(State)
+ try:
+ state.check_and_raise_exception()
+ except OperationError, e:
+ print e.errorstr(self.space)
+ raise
try:
del self.space.getexecutioncontext().cpyext_threadstate
except AttributeError:
pass
+ return # ZZZ
if self.check_and_print_leaks():
assert False, "Test leaks or loses object(s)."
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -92,6 +92,7 @@
return str(pydname)
def freeze_refcnts(self):
+ ZZZ
state = self.space.fromcache(RefcountState)
self.frozen_refcounts = {}
for w_obj, obj in state.py_objects_w2r.iteritems():
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -320,6 +320,8 @@
# - object.tp_bases is a tuple
# - tuple.tp_bases is a tuple
+ return # ZZZ
+
# insert null placeholders to please create_ref()
track_reference(space, lltype.nullptr(PyObject.TO), space.w_type)
track_reference(space, lltype.nullptr(PyObject.TO), space.w_object)
More information about the pypy-commit
mailing list