[pypy-svn] r26681 - in pypy/dist/pypy/objspace/cpy: . test
arigo at codespeak.net
arigo at codespeak.net
Tue May 2 20:17:36 CEST 2006
Author: arigo
Date: Tue May 2 20:17:33 2006
New Revision: 26681
Added:
pypy/dist/pypy/objspace/cpy/refcount.py (contents, props changed)
pypy/dist/pypy/objspace/cpy/test/test_refcount.py (contents, props changed)
Modified:
pypy/dist/pypy/objspace/cpy/ann_policy.py
pypy/dist/pypy/objspace/cpy/capi.py
pypy/dist/pypy/objspace/cpy/ctypes_base.py
pypy/dist/pypy/objspace/cpy/test/test_compile.py
pypy/dist/pypy/objspace/cpy/wrappable.py
Log:
(pedronis, arigo) Preserve tracebacks through the RPython code.
Added necessary support to manipulate the refcounts directly.
Modified: pypy/dist/pypy/objspace/cpy/ann_policy.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/ann_policy.py (original)
+++ pypy/dist/pypy/objspace/cpy/ann_policy.py Tue May 2 20:17:33 2006
@@ -29,11 +29,11 @@
# restart this loop: for all we know follow_annotations()
# could have found new objects
- # force w_type, w_value attributes into the OperationError class
+ # force w_type/w_value/w_traceback attrs into the OperationError class
bk = annotator.bookkeeper
classdef = bk.getuniqueclassdef(OperationError)
s_instance = annmodel.SomeInstance(classdef=classdef)
- for name in ['w_type', 'w_value']:
+ for name in ['w_type', 'w_value', 'w_traceback']:
s_instance.setattr(bk.immutablevalue(name),
bk.valueoftype(W_Object))
Modified: pypy/dist/pypy/objspace/cpy/capi.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/capi.py (original)
+++ pypy/dist/pypy/objspace/cpy/capi.py Tue May 2 20:17:33 2006
@@ -223,6 +223,12 @@
RAW_PyErr_SetObject.restype = None
RAW_PyErr_SetObject._rctypes_pyerrchecker_ = None
+# WARNING: consumes references
+RAW_PyErr_Restore = pythonapi.PyErr_Restore
+RAW_PyErr_Restore.argtypes = [W_Object, W_Object, W_Object]
+RAW_PyErr_Restore.restype = None
+RAW_PyErr_Restore._rctypes_pyerrchecker_ = None
+
RAW_PyErr_Occurred = pythonapi.PyErr_Occurred
RAW_PyErr_Occurred.argtypes = []
RAW_PyErr_Occurred.restype = c_int
Modified: pypy/dist/pypy/objspace/cpy/ctypes_base.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/ctypes_base.py (original)
+++ pypy/dist/pypy/objspace/cpy/ctypes_base.py Tue May 2 20:17:33 2006
@@ -33,7 +33,7 @@
w_val = W_Object()
w_tb = W_Object()
RAW_PyErr_Fetch(byref(w_exc), byref(w_val), byref(w_tb))
- raise OperationError(w_exc, w_val) # XXX traceback
+ raise OperationError(w_exc, w_val, w_tb)
class CPyAPI(PyDLL):
"""Class of the singleton 'cpyapi' object, out of which C functions
@@ -53,7 +53,8 @@
except:
exc, val, tb = sys.exc_info()
raise OperationError(W_Object(exc),
- W_Object(val)) # XXX traceback
+ W_Object(val),
+ W_Object(tb))
cpyapi = CPyAPI.__new__(CPyAPI)
cpyapi.__dict__ = pythonapi.__dict__.copy()
Added: pypy/dist/pypy/objspace/cpy/refcount.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/cpy/refcount.py Tue May 2 20:17:33 2006
@@ -0,0 +1,69 @@
+from pypy.annotation import model as annmodel
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.objspace.cpy.capi import *
+
+
+###################################################################
+# ____________________ Reference counter hacks ____________________
+
+_XX_PyObject_GetItem = pythonapi.PyObject_GetItem
+_XX_PyObject_GetItem.argtypes = [W_Object, W_Object]
+_XX_PyObject_GetItem.restype = None # !
+
+_XX_PyList_SetItem = pythonapi.PyList_SetItem
+_XX_PyList_SetItem.argtypes = [W_Object, Py_ssize_t, W_Object]
+_XX_PyList_SetItem.restype = c_int
+
+def Py_Incref(w):
+ container = (w.value,)
+ _XX_PyObject_GetItem(W_Object(container), W_Object(0))
+ # the new reference returned by PyObject_GetItem is ignored and lost
+
+def Py_Decref(w):
+ lst = [None]
+ # consume a reference
+ _XX_PyList_SetItem(W_Object(lst), 0, w)
+
+def Py_XIncref(w):
+ if w:
+ Py_Incref(w)
+
+def Py_XDecref(w):
+ if w:
+ Py_Decref(w)
+
+
+class IncrefFnEntry(ExtRegistryEntry):
+ "Annotation and specialization of calls to Py_Incref()."
+ _about_ = Py_Incref
+
+ def compute_result_annotation(self, s_arg):
+ return annmodel.s_None
+
+ def specialize_call(self, hop):
+ from pypy.rpython.lltypesystem import lltype
+ s_pyobj = annmodel.SomeCTypesObject(W_Object,
+ annmodel.SomeCTypesObject.MEMORYALIAS)
+ r_pyobj = hop.rtyper.getrepr(s_pyobj)
+ [v_box] = hop.inputargs(r_pyobj)
+ v_value = r_pyobj.getvalue(hop.llops, v_box)
+ hop.genop('gc_push_alive_pyobj', [v_value])
+ return hop.inputconst(lltype.Void, None)
+
+
+class DecrefFnEntry(ExtRegistryEntry):
+ "Annotation and specialization of calls to Py_Decref()."
+ _about_ = Py_Decref
+
+ def compute_result_annotation(self, s_arg):
+ return annmodel.s_None
+
+ def specialize_call(self, hop):
+ from pypy.rpython.lltypesystem import lltype
+ s_pyobj = annmodel.SomeCTypesObject(W_Object,
+ annmodel.SomeCTypesObject.MEMORYALIAS)
+ r_pyobj = hop.rtyper.getrepr(s_pyobj)
+ [v_box] = hop.inputargs(r_pyobj)
+ v_value = r_pyobj.getvalue(hop.llops, v_box)
+ hop.genop('gc_pop_alive_pyobj', [v_value])
+ return hop.inputconst(lltype.Void, None)
Modified: pypy/dist/pypy/objspace/cpy/test/test_compile.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/test/test_compile.py (original)
+++ pypy/dist/pypy/objspace/cpy/test/test_compile.py Tue May 2 20:17:33 2006
@@ -150,12 +150,10 @@
def test_compile_exception_through_rpython():
space = CPyObjSpace()
- def myfunc(n):
- w_sys = space.getbuiltinmodule('sys')
- w_n = space.wrap(n)
- space.call_method(w_sys, 'exit', w_n)
+ def myfunc(w_callback):
+ space.call_function(w_callback, space.wrap(5))
return space.w_None # should not actually reach this point
- myfunc.unwrap_spec = [int]
+ myfunc.unwrap_spec = [W_Root]
w_myfunc = space.wrap(interp2app(myfunc))
def entrypoint():
@@ -163,7 +161,13 @@
fn = compile(entrypoint, [],
annotatorpolicy = CPyAnnotatorPolicy(space))
+
+ def mycallback(n):
+ assert n == 5
+ raise SystemExit(12)
+
myfunc1 = fn()
- e = py.test.raises(SystemExit, myfunc1, 5)
+ e = py.test.raises(SystemExit, myfunc1, mycallback)
ex = e.value
- assert ex.args == (5,)
+ assert ex.args == (12,)
+ assert e.traceback[-1].frame.code.name == 'mycallback'
Added: pypy/dist/pypy/objspace/cpy/test/test_refcount.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/cpy/test/test_refcount.py Tue May 2 20:17:33 2006
@@ -0,0 +1,39 @@
+import sys
+from pypy.translator.c.test.test_genc import compile
+from pypy.objspace.cpy.refcount import *
+
+
+def test_reftricks():
+ x = object()
+ w_x = W_Object(x)
+ before = sys.getrefcount(x)
+ Py_Incref(w_x)
+ after = sys.getrefcount(x)
+ assert after == before+1
+ assert w_x.value is x
+
+ Py_Decref(w_x)
+ after = sys.getrefcount(x)
+ assert after == before
+ assert w_x.value is x
+
+
+def test_compile_reftricks():
+ def func(obj, flag):
+ w = W_Object(obj)
+ if flag > 0:
+ Py_Incref(w)
+ else:
+ Py_Decref(w)
+
+ fn = compile(func, [object, int])
+
+ x = object()
+ before = sys.getrefcount(x)
+ fn(x, +1)
+ after = sys.getrefcount(x)
+ assert after == before+1
+
+ fn(x, -1)
+ after = sys.getrefcount(x)
+ assert after == before
Modified: pypy/dist/pypy/objspace/cpy/wrappable.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/wrappable.py (original)
+++ pypy/dist/pypy/objspace/cpy/wrappable.py Tue May 2 20:17:33 2006
@@ -6,6 +6,7 @@
import py
from pypy.annotation.pairtype import pair, pairtype
from pypy.objspace.cpy.capi import *
+from pypy.objspace.cpy.refcount import Py_XIncref
from pypy.objspace.cpy.objspace import CPyObjSpace
from pypy.interpreter.error import OperationError
from pypy.interpreter.function import Function
@@ -49,6 +50,19 @@
self.passedargs = []
+def reraise(e):
+ w_type = e.w_type
+ w_value = e.w_value
+ w_traceback = e.application_traceback
+ if e.application_traceback is None:
+ w_traceback = W_Object() # NULL
+ else:
+ Py_XIncref(w_traceback)
+ Py_XIncref(w_type)
+ Py_XIncref(w_value)
+ RAW_PyErr_Restore(e.w_type, e.w_value, w_traceback)
+
+
class __extend__(pairtype(CPyObjSpace, Function)):
def wrap((space, func)):
@@ -76,8 +90,7 @@
sourcelines.append(' w_result = ___bltin(%s)' % (
', '.join(tramp.passedargs),))
sourcelines.append(' except ___OperationError, e:')
- sourcelines.append(' ___PyErr_SetObject(e.w_type.value,')
- sourcelines.append(' e.w_value.value)')
+ sourcelines.append(' ___reraise(e)')
# the following line is not reached, unless we are translated
# in which case it makes the function return (PyObject*)NULL.
sourcelines.append(' w_result = ___W_Object()')
@@ -92,7 +105,7 @@
'___PyInt_AsLong': PyInt_AsLong,
'___bltin': bltin,
'___OperationError': OperationError,
- '___PyErr_SetObject': RAW_PyErr_SetObject,
+ '___reraise': reraise,
}
exec py.code.Source('\n'.join(sourcelines)).compile() in miniglobals
More information about the Pypy-commit
mailing list