[pypy-svn] r59018 - in pypy/dist/pypy/translator/backendopt: . test
arigo at codespeak.net
arigo at codespeak.net
Sun Oct 12 14:13:40 CEST 2008
Author: arigo
Date: Sun Oct 12 14:13:38 2008
New Revision: 59018
Modified:
pypy/dist/pypy/translator/backendopt/mallocv.py
pypy/dist/pypy/translator/backendopt/test/test_mallocv.py
Log:
Refactorings. No more tests pass.
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 14:13:38 2008
@@ -105,9 +105,11 @@
class VirtualFrame(object):
- def __init__(self, sourceblock, nextopindex, allnodes, callerframe=None):
+ def __init__(self, sourcegraph, sourceblock, nextopindex,
+ allnodes, callerframe=None):
self.varlist = vars_alive_through_op(sourceblock, nextopindex)
self.nodelist = [allnodes[v] for v in self.varlist]
+ self.sourcegraph = sourcegraph
self.sourceblock = sourceblock
self.nextopindex = nextopindex
self.callerframe = callerframe
@@ -120,6 +122,7 @@
newframe.varlist = self.varlist
newframe.nodelist = [node.copy(memo, flagreadonly)
for node in self.nodelist]
+ newframe.sourcegraph = self.sourcegraph
newframe.sourceblock = self.sourceblock
newframe.nextopindex = self.nextopindex
if self.callerframe is None:
@@ -160,15 +163,24 @@
rtnodes, vtnodes = self.find_all_nodes()
return vtnodes
- def return_to_caller(self, returnblock, targetnodes):
- [v_ret] = returnblock.inputargs
- retnode = targetnodes[v_ret]
+ def return_to_caller(self, retnode):
callerframe = self.callerframe
+ if callerframe is None:
+ raise ForcedInline("return block")
for i in range(len(callerframe.nodelist)):
if isinstance(callerframe.nodelist[i], FutureReturnValue):
callerframe.nodelist[i] = retnode
return callerframe
+ def handle_raise(self, linkargsnodes):
+ if not is_trivial_nodelist(linkargsnodes):
+ raise ForcedInline("except block")
+ # XXX this assumes no exception handler in the callerframes
+ topframe = self
+ while topframe.callerframe is not None:
+ topframe = topframe.callerframe
+ return topframe, topframe.sourcegraph.exceptblock
+
def copynodes(nodelist, flagreadonly={}):
memo = {}
@@ -264,10 +276,10 @@
def try_remove_malloc(self, graph, block, op):
if (graph, op) in self.inline_and_remove_seen:
return False # no point in trying again
- graphbuilder = GraphBuilder(self)
+ graphbuilder = GraphBuilder(self, graph)
if graph in self.graphbuilders:
graphbuilder.initialize_from_old_builder(self.graphbuilders[graph])
- graphbuilder.start_from_a_malloc(block, op.result)
+ graphbuilder.start_from_a_malloc(graph, block, op.result)
try:
graphbuilder.propagate_specializations()
except CannotVirtualize, e:
@@ -305,7 +317,7 @@
if is_trivial_nodelist(nodelist):
return 'trivial', graph
nodes = dict(zip(graph.getargs(), nodelist))
- virtualframe = VirtualFrame(graph.startblock, 0, nodes)
+ virtualframe = VirtualFrame(graph, graph.startblock, 0, nodes)
key = virtualframe.getfrozenkey()
try:
return self.specialized_graphs[key]
@@ -316,8 +328,8 @@
def build_specialized_graph(self, graph, key, nodelist):
graph2 = copygraph(graph)
nodes = dict(zip(graph2.getargs(), nodelist))
- virtualframe = VirtualFrame(graph2.startblock, 0, nodes)
- graphbuilder = GraphBuilder(self)
+ virtualframe = VirtualFrame(graph2, graph2.startblock, 0, nodes)
+ graphbuilder = GraphBuilder(self, graph2)
specblock = graphbuilder.start_from_virtualframe(virtualframe)
specblock.isstartblock = True
specgraph = graph2
@@ -341,8 +353,9 @@
class GraphBuilder(object):
- def __init__(self, mallocv):
+ def __init__(self, mallocv, graph):
self.mallocv = mallocv
+ self.graph = graph
self.specialized_blocks = {}
self.pending_specializations = []
@@ -355,12 +368,12 @@
self.pending_specializations.append(spec)
return spec.specblock
- def start_from_a_malloc(self, block, v_result):
+ def start_from_a_malloc(self, graph, block, v_result):
assert v_result in [op.result for op in block.operations]
nodes = {}
for v in block.inputargs:
nodes[v] = RuntimeSpecNode(v, v.concretetype)
- trivialframe = VirtualFrame(block, 0, nodes)
+ trivialframe = VirtualFrame(graph, block, 0, nodes)
spec = BlockSpecializer(self, v_result)
spec.initialize_renamings(trivialframe)
self.pending_specializations.append(spec)
@@ -455,8 +468,7 @@
self.specblock.operations = newoperations
def follow_exits(self):
- currentframe = self.virtualframe
- block = currentframe.sourceblock
+ block = self.virtualframe.sourceblock
self.specblock.exitswitch = self.rename_nonvirtual(block.exitswitch,
'exitswitch')
catch_exc = self.specblock.exitswitch == c_last_exception
@@ -473,30 +485,30 @@
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)
- if isinstance(node, RuntimeSpecNode):
- rtnodes.append(node)
- targetnodes[v2] = node
+ currentframe = self.virtualframe
+ linkargsnodes = [self.getnode(v1) for v1 in link.args]
+ targetblock = link.target
+
+ if is_except(targetblock):
+ currentframe, targetblock = currentframe.handle_raise(
+ linkargsnodes)
+
+ assert len(targetblock.inputargs) == len(linkargsnodes)
+ targetnodes = dict(zip(targetblock.inputargs, linkargsnodes))
- if (len(rtnodes) == len(link.args) and
- currentframe.callerframe is None):
+ if (currentframe.callerframe is None and
+ is_trivial_nodelist(linkargsnodes)):
# there is no more VirtualSpecNodes being passed around,
- # so we can stop specializing.
- specblock = link.target
+ # so we can stop specializing
+ rtnodes = linkargsnodes
+ specblock = targetblock
else:
- if len(link.target.exits) == 0: # return or except block
- if len(link.target.inputargs) != 1:
- raise CannotVirtualize("except block")
- if currentframe.callerframe is None:
- raise ForcedInline("return block")
- newframe = currentframe.return_to_caller(link.target,
- targetnodes)
+ if is_return(targetblock):
+ newframe = currentframe.return_to_caller(linkargsnodes[0])
v_expand_malloc = None
else:
- newframe = VirtualFrame(link.target, 0, targetnodes,
+ newframe = VirtualFrame(currentframe.sourcegraph,
+ targetblock, 0, targetnodes,
callerframe=currentframe.callerframe)
v_expand_malloc = self.v_expand_malloc
rtnodes = newframe.find_rt_nodes()
@@ -636,10 +648,11 @@
raise ValueError(kind)
def get_updated_frame(self, op):
+ sourcegraph = self.virtualframe.sourcegraph
sourceblock = self.virtualframe.sourceblock
nextopindex = self.virtualframe.nextopindex
self.nodes[op.result] = FutureReturnValue(op)
- myframe = VirtualFrame(sourceblock, nextopindex,
+ myframe = VirtualFrame(sourcegraph, sourceblock, nextopindex,
self.nodes,
self.virtualframe.callerframe)
del self.nodes[op.result]
@@ -657,7 +670,7 @@
def handle_inlined_call(self, myframe, graph, newnodes):
assert len(graph.getargs()) == len(newnodes)
targetnodes = dict(zip(graph.getargs(), newnodes))
- calleeframe = VirtualFrame(graph.startblock, 0,
+ calleeframe = VirtualFrame(graph, graph.startblock, 0,
targetnodes, myframe)
self.virtualframe = calleeframe
self.nodes = calleeframe.get_nodes_in_use()
@@ -703,3 +716,9 @@
for v in link.args:
see(v)
return result
+
+def is_return(block):
+ return len(block.exits) == 0 and len(block.inputargs) == 1
+
+def is_except(block):
+ return len(block.exits) == 0 and len(block.inputargs) == 2
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 14:13:38 2008
@@ -179,6 +179,18 @@
graph = self.check(f, [int], [19], 42,
expected_calls=0) # inlined
+ def test_raises_simple(self):
+ class MyExc(Exception):
+ pass
+ def f(n):
+ if n < 3:
+ e = MyExc()
+ e.n = n
+ raise e
+ return n
+ self.check(f, [int], [5], 5, expected_mallocs=1)
+ self.check(f, [int], [-5], CHECK_RAISES("MyExc"), expected_mallocs=1)
+
def test_catch_simple(self):
class A:
pass
@@ -192,7 +204,7 @@
a = A()
a.n = 10
try:
- g(n)
+ g(n) # this call should not be inlined
except E, e:
a.n = e.n
return a.n
More information about the Pypy-commit
mailing list