[pypy-svn] r35810 - in pypy/dist/pypy/jit: codegen codegen/i386 codegen/i386/test timeshifter

ac at codespeak.net ac at codespeak.net
Fri Dec 15 17:00:50 CET 2006


Author: ac
Date: Fri Dec 15 17:00:49 2006
New Revision: 35810

Modified:
   pypy/dist/pypy/jit/codegen/i386/rgenop.py
   pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py
   pypy/dist/pypy/jit/codegen/model.py
   pypy/dist/pypy/jit/timeshifter/rtimeshift.py
Log:
Pause builders when they are put on return/split/global_merge chains so they
can release temporary resources (The i386 one will release it's
MachineCodeBlock). This way we won't use up the addresspace so easily.



Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/rgenop.py	Fri Dec 15 17:00:49 2006
@@ -220,27 +220,51 @@
 
 class Builder(GenBuilder):
 
-    def __init__(self, rgenop, mc_factory, stackdepth):
+    def __init__(self, rgenop, stackdepth):
         self.rgenop = rgenop
         self.stackdepth = stackdepth
         self.mc = None
-        self._mc_factory = mc_factory
         self._pending_come_from = {}
         self.start = 0
+        self.closed = False
+        self.tail = (0, 0)
         rgenop.openbuilders += 1
         #os.write(1, 'Open builders+: %d\n' % rgenop.openbuilders)
 
     def _open(self):
-        if self.mc is None and self._pending_come_from is not None:
-            self.mc = self._mc_factory()
-            self.start = self.mc.tell()
-            come_froms = self._pending_come_from
-            self._pending_come_from = None
-            for start, (end, insn) in come_froms.iteritems():
-                mc = self.rgenop.InMemoryCodeBuilder(start, end)
-                self._emit_come_from(mc, insn, self.start)
+        if self.mc is None and not self.closed:
+            self.mc = self.rgenop.open_mc()
+            if not self.start:
+                # This is the first open. remember the start address
+                # and patch all come froms.
+                self.start = self.mc.tell()
+                come_froms = self._pending_come_from
+                self._pending_come_from = None
+                for start, (end, insn) in come_froms.iteritems():
+                    mc = self.rgenop.InMemoryCodeBuilder(start, end)
+                    self._emit_come_from(mc, insn, self.start)
+                    mc.done()
+            else:
+                # We have been paused and are being opened again.
+                # Patch the jump at the end of the previous codeblock.
+                mc = self.rgenop.InMemoryCodeBuilder(*self.tail)
+                mc.JMP(rel32(self.mc.tell()))
                 mc.done()
 
+    def pause(self):
+        if self.mc is None:
+            return
+        start = self.mc.tell()
+        self.mc.JMP(rel32(0))
+        end = self.mc.tell()
+        self.tail = (start, end)
+        self.mc.done()
+        self.rgenop.close_mc(self.mc)
+        self.mc = None
+        
+    def resume(self):
+        self._open()
+        
     def _emit_come_from(self, mc, insn, addr):
         if insn == 'JMP':
             mc.JMP(rel32(addr))
@@ -273,6 +297,7 @@
         return [Var(pos) for pos in range(numargs-1, -1, -1)]
 
     def _close(self):
+        self.closed = True
         self.mc.done()
         self.rgenop.close_mc(self.mc)
         self.mc = None
@@ -459,6 +484,7 @@
         return targetbuilder
 
     def finish_and_return(self, sigtoken, gv_returnvar):
+        self._open()
         numargs = sigtoken      # for now
         initialstackdepth = numargs + 1
         self.mc.MOV(eax, gv_returnvar.operand(self))
@@ -467,6 +493,7 @@
         self._close()
 
     def finish_and_goto(self, outputargs_gv, target):
+        self._open()
         remap_stack_layout(self, outputargs_gv, target)
         self.mc.JMP(rel32(target.startaddr))
         self._close()
@@ -961,7 +988,7 @@
         assert len(self.mcs) == self.total_code_blocks
 
     def openbuilder(self, stackdepth):
-        return Builder(self, self.open_mc, stackdepth)
+        return Builder(self, stackdepth)
 
     def newgraph(self, sigtoken, name):
         numargs = sigtoken          # for now

Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py	Fri Dec 15 17:00:49 2006
@@ -59,9 +59,6 @@
                                     backendoptimize=backendoptimize)
         cmdargs = ' '.join([str(arg) for arg in main_args])
         output = self.cbuilder.cmdexec(cmdargs)
-        print '-'*60
-        print output
-        print '-'*60
         lines = output.split()
         lastline = lines[-1]
         assert not lastline.startswith('EXCEPTION:')

Modified: pypy/dist/pypy/jit/codegen/model.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/model.py	(original)
+++ pypy/dist/pypy/jit/codegen/model.py	Fri Dec 15 17:00:49 2006
@@ -142,7 +142,15 @@
         '''Optional method: prints or logs the position of the generated code
         along with the given msg.
         '''
-
+    def pause(self):
+        '''Optional method: Called when the builder will not be used for a
+        while. This allows the builder to free temporary resources needed
+        during code generation. The next call to the builder will have to be
+        to enter_next_block, finish_and_got, finish_and_return or resume.
+        '''
+    def resume(self):
+        'Resumes a paused builder.'
+        
 class GenLabel(object):
     '''A "smart" label.  Represents an address of the start of a basic
     block and the location of the inputargs on entry to that block.'''

Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py	Fri Dec 15 17:00:49 2006
@@ -308,6 +308,7 @@
             resuming.mergesleft -= 1
 
 def guard_global_merge(jitstate, resumepoint):
+    jitstate.curbuilder.pause()
     dispatchqueue = jitstate.frame.dispatchqueue
     jitstate.next = dispatchqueue.global_merge_chain
     dispatchqueue.global_merge_chain = jitstate
@@ -392,6 +393,7 @@
     elif dispatchqueue.global_merge_chain is not None:
         jitstate = dispatchqueue.global_merge_chain
         dispatchqueue.global_merge_chain = jitstate.next
+        jitstate.curbuilder.resume()
         return jitstate
     else:
         oldjitstate.resumepoint = -1
@@ -439,6 +441,7 @@
 
 def save_return(jitstate):
     # add 'jitstate' to the chain of return-jitstates
+    jitstate.curbuilder.pause()
     dispatchqueue = jitstate.frame.dispatchqueue
     jitstate.next = dispatchqueue.return_chain
     dispatchqueue.return_chain = jitstate
@@ -913,10 +916,13 @@
     while return_chain is not None:
         jitstate = return_chain
         return_chain = return_chain.next
+        jitstate.curbuilder.resume()
         res = retrieve_jitstate_for_merge(return_cache, jitstate, (),
                                           return_marker,
                                           force_merge=force_merge)
         if res is False:    # not finished
+            if still_pending:
+                still_pending.curbuilder.pause()
             jitstate.next = still_pending
             still_pending = jitstate
     
@@ -929,10 +935,13 @@
         while return_chain is not None:
             jitstate = return_chain
             return_chain = return_chain.next
+            jitstate.curbuilder.resume()
             res = retrieve_jitstate_for_merge(return_cache, jitstate, (),
                                               return_marker,
                                               force_merge=force_merge)
             if res is False:    # not finished
+                if still_pending:
+                    still_pending.curbuilder.pause()
                 jitstate.next = still_pending
                 still_pending = jitstate
     return still_pending
@@ -992,4 +1001,3 @@
         leave_frame(jitstate)
         jitstate = jitstate.next
     return return_chain    # a jitstate, which is the head of the chain
-


More information about the pypy-svn mailing list