[pypy-svn] r30860 - pypy/dist/pypy/translator/stackless

mwh at codespeak.net mwh at codespeak.net
Tue Aug 1 18:32:44 CEST 2006


Author: mwh
Date: Tue Aug  1 18:32:43 2006
New Revision: 30860

Modified:
   pypy/dist/pypy/translator/stackless/transform.py
Log:
reuse some resume blocks, saves another ~130k in pypy-c-stackless.
obscurity++ though.
next: reusing resume points when only the erased types are the same, cleanups?


Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Tue Aug  1 18:32:43 2006
@@ -449,6 +449,7 @@
         assert self.curr_graph is None
         self.curr_graph = graph
         self.curr_graph_save_blocks = {}
+        self.curr_graph_resume_blocks = {}
         if SAVE_STATISTICS:
             self.stats.cur_rp_exact_types = {}
             self.stats.cur_rp_erased_types = {}
@@ -482,6 +483,7 @@
            
         self.curr_graph = None
         self.curr_graph_save_blocks = None
+        self.curr_graph_resume_blocks = None
 
     def ops_read_global_state_field(self, targetvar, fieldname):
         ops = []
@@ -519,8 +521,12 @@
         not_resuming_link.llexitcase = -1
         resuming_links = []
         for resume_index, resume_block in enumerate(self.resume_blocks):
+            if resume_block.inputargs:
+                args = [var_resume_state]
+            else:
+                args = []
             resuming_links.append(
-                model.Link([], resume_block, resume_index))
+                model.Link(args, resume_block, resume_index))
             resuming_links[-1].llexitcase = resume_index
 
         new_start_block.exitswitch = var_resume_state
@@ -897,68 +903,111 @@
 
     def _generate_resume_block(self, varsinfieldorder, frame_type,
                                var_result, links_to_resumption):
-        newblock = model.Block([])
-        newargs = []
-        llops = LowLevelOpList()
-        llops.genop("setfield",
-                    [self.ll_global_state,
-                     self.c_restart_substate_name,
-                     self.c_minus_one])
-        frame_top = varoftype(lltype.Ptr(frame_type))
-        llops.extend(self.ops_read_global_state_field(frame_top, "top"))
-        llops.genop("setfield",
-                   [self.ll_global_state,
-                    self.c_inst_top_name,
-                    self.c_null_state])
-        varmap = {}
-        fielditer = iter(frame_type._names[1:])
-        for arg in varsinfieldorder:
-            assert arg is not var_result
-            t = storage_type(arg.concretetype)
-            if t is lltype.Void:
-                v_newarg = model.Constant(None, lltype.Void)
-            else:
-                fname = model.Constant(fielditer.next(), lltype.Void)
-                assert frame_type._flds[fname.value] is t
-                v_newarg = llops.genop('getfield', [frame_top, fname],
-                                       resulttype = t)
-                v_newarg = gen_cast(llops, arg.concretetype, v_newarg)
-            varmap[arg] = v_newarg
-
-        rettype = storage_type(var_result.concretetype)
-        getretval = self.fetch_retvals[rettype]
-        retval = llops.genop("direct_call", [getretval],
-                             resulttype = rettype)
-        varmap[var_result] = retval
-
-        newblock.operations.extend(llops)
-
-        def rename(arg):
-            if isinstance(arg, model.Variable):
-                if arg in varmap:
+        typekey = [v.concretetype for v in varsinfieldorder]
+        linkkey = [(link.target, link.exitcase) for link in links_to_resumption[1:]]
+        key = tuple([var_result.concretetype] + typekey + linkkey)
+        if key in self.curr_graph_resume_blocks:
+            newblock, switchblock, newargs, newresult = self.curr_graph_resume_blocks[key]
+            if switchblock is None:
+                newblock.inputargs = [varoftype(lltype.Signed)]
+                switchblock = unsimplify.insert_empty_block(None, newblock.exits[0], [])
+                newblock.exits[0].args.append(newblock.inputargs[0])
+                switchblock.inputargs.append(varoftype(lltype.Signed))
+                switchblock.exitswitch = switchblock.inputargs[-1]
+                link, = switchblock.exits
+                link.exitcase = link.llexitcase = self.resume_blocks.index(newblock)
+                mapping = {}
+                for i in range(len(newblock.exits[0].args)):
+                    mapping[newblock.exits[0].args[i]] = switchblock.inputargs[i]
+                if newresult in mapping:
+                    newresult = mapping[newresult]
+                newnewargs = []
+                for arg in newargs:
+                    newnewargs.append(mapping[arg])
+                newargs = newnewargs
+                self.curr_graph_resume_blocks[key] = newblock, switchblock, newnewargs, newresult
+            oldlink = links_to_resumption[0]
+            varmap = {}
+            for old, new in zip(varsinfieldorder, newargs):
+                varmap[old] = new
+            varmap[var_result] = newresult
+            def rename(arg):
+                if isinstance(arg, model.Variable):
                     return varmap[arg]
                 else:
-                    assert arg in [l.last_exception, l.last_exc_value]
-                    r = unsimplify.copyvar(None, arg)
-                    varmap[arg] = r
-                    return r
-            else:
-                return arg
-
-        newblock.closeblock(*[l.copy(rename)
-                              for l in links_to_resumption])
-        # this check is a bit implicit!
-        if len(links_to_resumption) > 1:
-            newblock.exitswitch = model.c_last_exception
+                    return arg
+            newlink = oldlink.copy(rename)
+            newlink.exitcase = newlink.llexitcase = len(self.resume_blocks)
+            switchblock.recloseblock(*(switchblock.exits + (newlink,)))
+            rettype = newresult.concretetype
+            retval = newresult
+            retlink = newlink
         else:
-            newblock.exitswitch = None
+            newblock = model.Block([])
+            newargs = []
+            llops = LowLevelOpList()
+            llops.genop("setfield",
+                        [self.ll_global_state,
+                         self.c_restart_substate_name,
+                         self.c_minus_one])
+            frame_top = varoftype(lltype.Ptr(frame_type))
+            llops.extend(self.ops_read_global_state_field(frame_top, "top"))
+            llops.genop("setfield",
+                       [self.ll_global_state,
+                        self.c_inst_top_name,
+                        self.c_null_state])
+            varmap = {}
+            newargs = []
+            fielditer = iter(frame_type._names[1:])
+            for arg in varsinfieldorder:
+                assert arg is not var_result
+                t = storage_type(arg.concretetype)
+                if t is lltype.Void:
+                    v_newarg = model.Constant(None, lltype.Void)
+                else:
+                    fname = model.Constant(fielditer.next(), lltype.Void)
+                    assert frame_type._flds[fname.value] is t
+                    v_newarg = llops.genop('getfield', [frame_top, fname],
+                                           resulttype = t)
+                    v_newarg = gen_cast(llops, arg.concretetype, v_newarg)
+                newargs.append(v_newarg)
+                varmap[arg] = v_newarg
+
+            rettype = storage_type(var_result.concretetype)
+            getretval = self.fetch_retvals[rettype]
+            retval = llops.genop("direct_call", [getretval],
+                                 resulttype = rettype)
+            varmap[var_result] = retval
+
+            newblock.operations.extend(llops)
+
+            def rename(arg):
+                if isinstance(arg, model.Variable):
+                    if arg in varmap:
+                        return varmap[arg]
+                    else:
+                        assert arg in [l.last_exception, l.last_exc_value]
+                        r = unsimplify.copyvar(None, arg)
+                        varmap[arg] = r
+                        return r
+                else:
+                    return arg
 
+            newblock.closeblock(*[l.copy(rename)
+                                  for l in links_to_resumption])
+            # this check is a bit implicit!
+            if len(links_to_resumption) > 1:
+                newblock.exitswitch = model.c_last_exception
+            else:
+                newblock.exitswitch = None
+            self.curr_graph_resume_blocks[key] = newblock, None, newargs, retval
+            retlink = newblock.exits[0]
+            if SAVE_STATISTICS:
+                self.stats.resumeops += len(newblock.operations)
+        
         if var_result.concretetype != rettype:
-            self.insert_return_conversion(
-                newblock.exits[0], var_result.concretetype, retval)
+            self.insert_return_conversion(retlink, var_result.concretetype, retval)
 
-        if SAVE_STATISTICS:
-            self.stats.resumeops += len(newblock.operations)
         return newblock
         
     def generate_restart_infos(self, graph):



More information about the Pypy-commit mailing list