[pypy-svn] r59013 - in pypy/dist/pypy/translator/backendopt: . test
arigo at codespeak.net
arigo at codespeak.net
Sun Oct 12 11:25:59 CEST 2008
Author: arigo
Date: Sun Oct 12 11:25:57 2008
New Revision: 59013
Modified:
pypy/dist/pypy/translator/backendopt/mallocv.py
pypy/dist/pypy/translator/backendopt/test/test_mallocv.py
Log:
Start tests and work on exceptions.
Modified: pypy/dist/pypy/translator/backendopt/mallocv.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/mallocv.py (original)
+++ pypy/dist/pypy/translator/backendopt/mallocv.py Sun Oct 12 11:25:57 2008
@@ -1,5 +1,6 @@
from pypy.objspace.flow.model import Variable, Constant, Block, Link
from pypy.objspace.flow.model import SpaceOperation, FunctionGraph, copygraph
+from pypy.objspace.flow.model import c_last_exception
from pypy.translator.backendopt.support import log
from pypy.rpython.typesystem import getfunctionptr
from pypy.rpython.lltypesystem import lltype
@@ -458,10 +459,21 @@
block = currentframe.sourceblock
self.specblock.exitswitch = self.rename_nonvirtual(block.exitswitch,
'exitswitch')
+ catch_exc = self.specblock.exitswitch == c_last_exception
newlinks = []
for link in block.exits:
- targetnodes = {}
+ is_exc_link = catch_exc and link.exitcase is not None
+ if is_exc_link:
+ extravars = []
+ for attr in ['last_exception', 'last_exc_value']:
+ v = getattr(link, attr)
+ if isinstance(v, Variable):
+ rtnode = RuntimeSpecNode(v, v.concretetype)
+ self.setnode(v, rtnode)
+ self.renamings[rtnode] = v = rtnode.newvar()
+ extravars.append(v)
+ targetnodes = {}
rtnodes = []
for v1, v2 in zip(link.args, link.target.inputargs):
node = self.getnode(v1)
@@ -494,7 +506,10 @@
linkargs = [self.renamings[rtnode] for rtnode in rtnodes]
newlink = Link(linkargs, specblock)
newlink.exitcase = link.exitcase
- newlink.llexitcase = link.llexitcase
+ if hasattr(link, 'llexitcase'):
+ newlink.llexitcase = link.llexitcase
+ if is_exc_link:
+ newlink.extravars(*extravars)
newlinks.append(newlink)
self.specblock.closeblock(*newlinks)
@@ -675,6 +690,10 @@
# don't include the variables produced by the current or future operations
for op in block.operations[index:]:
seen[op.result] = True
+ # don't include the extra vars produced by exception-catching links
+ for link in block.exits:
+ for v in link.getextravars():
+ seen[v] = True
# but include the variables consumed by the current or any future operation
for op in block.operations[index:]:
for v in op.args:
Modified: pypy/dist/pypy/translator/backendopt/test/test_mallocv.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_mallocv.py (original)
+++ pypy/dist/pypy/translator/backendopt/test/test_mallocv.py Sun Oct 12 11:25:57 2008
@@ -1,4 +1,5 @@
import py
+import sys
from pypy.translator.backendopt.mallocv import MallocVirtualizer
from pypy.translator.backendopt.inline import inline_function
from pypy.translator.backendopt.all import backend_optimizations
@@ -6,12 +7,20 @@
from pypy.translator import simplify
from pypy.objspace.flow.model import checkgraph, flatten, Block, mkentrymap
from pypy.objspace.flow.model import summary
-from pypy.rpython.llinterp import LLInterpreter
+from pypy.rpython.llinterp import LLInterpreter, LLException
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.ootypesystem import ootype
from pypy.rlib import objectmodel
+from pypy.rlib.rarithmetic import ovfcheck
from pypy.conftest import option
+DONT_CHECK_RESULT = object()
+class CHECK_RAISES:
+ def __init__(self, excname):
+ assert isinstance(excname, str)
+ self.excname = excname
+
+
class BaseMallocRemovalTest(object):
type_system = None
MallocRemover = None
@@ -52,10 +61,15 @@
if progress and option.view:
t.view()
t.checkgraphs()
- if expected_result is not Ellipsis:
+ if expected_result is not DONT_CHECK_RESULT:
interp = LLInterpreter(t.rtyper)
- res = interp.eval_graph(graph, args)
- assert res == expected_result
+ if not isinstance(expected_result, CHECK_RAISES):
+ res = interp.eval_graph(graph, args)
+ assert res == expected_result
+ else:
+ excinfo = py.test.raises(LLException,
+ interp.eval_graph, graph, args)
+ assert expected_result.excname in str(excinfo.value)
if not progress:
break
maxiter -= 1
@@ -165,6 +179,110 @@
graph = self.check(f, [int], [19], 42,
expected_calls=0) # inlined
+ def test_catch_simple(self):
+ class A:
+ pass
+ class E(Exception):
+ def __init__(self, n):
+ self.n = n
+ def g(n):
+ if n < 0:
+ raise E(n)
+ def f(n):
+ a = A()
+ a.n = 10
+ try:
+ g(n)
+ except E, e:
+ a.n = e.n
+ return a.n
+ self.check(f, [int], [15], 10, expected_calls=1)
+ self.check(f, [int], [-15], -15, expected_calls=1)
+
+ def test_raise_catch(self):
+ class A:
+ pass
+ class E(Exception):
+ def __init__(self, n):
+ self.n = n
+ def f(n):
+ a = A()
+ e1 = E(n)
+ try:
+ raise e1
+ except E, e:
+ a.n = e.n
+ return a.n
+ self.check(f, [int], [15], 15)
+
+ def test_raising_op(self):
+ class A:
+ pass
+ def f(n):
+ a = A()
+ a.n = n
+ try:
+ a.n = ovfcheck(a.n + 1)
+ except OverflowError:
+ return -42
+ return a.n
+ self.check(f, [int], [19], 20)
+ self.check(f, [int], [sys.maxint], -42)
+
+ def test_raises_through_spec_graph(self):
+ class A:
+ pass
+ def g(a):
+ if a.n < 0:
+ raise ValueError
+ def f(n):
+ a = A()
+ a.n = n
+ g(a)
+ return a.n
+ self.check(f, [int], [19], 19,
+ expected_calls=1)
+ self.check(f, [int], [-19], CHECK_RAISES("ValueError"),
+ expected_calls=1)
+
+ def test_raises_through_inlining(self):
+ py.test.skip("in-progress")
+ class A:
+ pass
+ def g(a):
+ a.n -= 1
+ if a.n < 0:
+ raise ValueError
+ def f(n):
+ a = A()
+ a.n = n
+ g(a)
+ return a.n
+ self.check(f, [int], [19], 18)
+ self.check(f, [int], [-19], CHECK_RAISES("ValueError"))
+
+ def test_call_raise_catch(self):
+ py.test.skip("in-progress")
+ class A:
+ pass
+ def g(a):
+ a.n -= 1
+ if a.n <= 0:
+ raise StopIteration
+ return a.n * 10
+ def f(n):
+ a = A()
+ a.n = n
+ total = 0
+ try:
+ while True:
+ total += g(a)
+ except StopIteration:
+ pass
+ return total
+ graph = self.check(f, [int], [11], 550,
+ expected_calls=0) # inlined
+
def test_fn2(self):
class T:
pass
@@ -445,7 +563,7 @@
x.u1.a = 3
x.u2.b = 6
return x.u1.b * x.u2.a
- self.check(fn, [], [], Ellipsis)
+ self.check(fn, [], [], DONT_CHECK_RESULT)
def test_keep_all_keepalives(self):
py.test.skip("redo me")
More information about the Pypy-commit
mailing list