[pypy-svn] r17943 - in pypy/dist/pypy/translator/llvm: . backendopt module

ericvrp at codespeak.net ericvrp at codespeak.net
Wed Sep 28 15:51:56 CEST 2005


Author: ericvrp
Date: Wed Sep 28 15:51:55 2005
New Revision: 17943

Modified:
   pypy/dist/pypy/translator/llvm/backendopt/exception.py
   pypy/dist/pypy/translator/llvm/backendopt/mergemallocs.py
   pypy/dist/pypy/translator/llvm/backendopt/removeexcmallocs.py
   pypy/dist/pypy/translator/llvm/exception.py
   pypy/dist/pypy/translator/llvm/funcnode.py
   pypy/dist/pypy/translator/llvm/gc.py
   pypy/dist/pypy/translator/llvm/module/extfunction.py
   pypy/dist/pypy/translator/llvm/opwriter.py
Log:
Added ringbuffer for data that looks like an Exception or Error.
It seems to work. Moving to another machine now to see how fast
it actually is.


Modified: pypy/dist/pypy/translator/llvm/backendopt/exception.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/backendopt/exception.py	(original)
+++ pypy/dist/pypy/translator/llvm/backendopt/exception.py	Wed Sep 28 15:51:55 2005
@@ -15,7 +15,7 @@
     Because of the added exitswitch we need an additional block.
     """
     global n_calls, n_calls_patched
-    n_calls_begin = n_calls
+    n_calls_patched_begin = n_calls_patched
     e = translator.rtyper.getexceptiondata()
     blocks = [x for x in flatten(graph) if isinstance(x, Block)]
     for block in blocks:
@@ -58,5 +58,6 @@
             l.prevblock  = block
             l.exitcase   = l.llexitcase = False
             block.exits.insert(0, l)    #False case needs to go first
-    if n_calls != n_calls_begin:
-        print 'create_exception_handling: patched %d out of %d calls' % (n_calls_patched, n_calls)
+    #if n_calls_patched != n_calls_patched_begin:
+    #    print 'create_exception_handling: patched %d out of %d calls' % (n_calls_patched, n_calls)
+    return n_calls_patched_begin - n_calls_patched

Modified: pypy/dist/pypy/translator/llvm/backendopt/mergemallocs.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/backendopt/mergemallocs.py	(original)
+++ pypy/dist/pypy/translator/llvm/backendopt/mergemallocs.py	Wed Sep 28 15:51:55 2005
@@ -11,6 +11,7 @@
 
     warning: some will consider this a dirty hack, that's ok! :)
     """
+    n_times_merged = 0
     blocks = [x for x in flatten(graph) if isinstance(x, Block)]
     for block in blocks:
         n_mallocs_in_block = 0
@@ -20,3 +21,5 @@
             n_mallocs_in_block += 1
         if n_mallocs_in_block >= 2:
             print 'merge_mallocs: n_mallocs_in_block=%d' % n_mallocs_in_block
+            n_times_merged += 1
+    return n_times_merged

Modified: pypy/dist/pypy/translator/llvm/backendopt/removeexcmallocs.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/backendopt/removeexcmallocs.py	(original)
+++ pypy/dist/pypy/translator/llvm/backendopt/removeexcmallocs.py	Wed Sep 28 15:51:55 2005
@@ -2,10 +2,6 @@
 from pypy.translator.backendopt.inline import _find_exception_type
 
 
-def _llvm_structsize(struct):
-    #XXX TODO take a save guess
-    return 16
-
 def remove_exception_mallocs(translator, graph, ringbuffer_entry_maxsize=16, ringbuffer_n_entries=1024):
     """Remove mallocs that occur because an exception is raised.
     Typically this data is shortlived and occuring often in highlevel
@@ -20,18 +16,19 @@
     warning: this code will not work when your code references
              an exception instance 'long' after it has been raised.
     """
+    n_removed = 0
     blocks = [x for x in flatten(graph) if isinstance(x, Block)]
     for block in blocks:
         ops = block.operations
-        if (len(ops) < 3 or
-            ops[0].opname != 'malloc'   or ops[1].opname != 'cast_pointer'   or
-            ops[2].opname != 'setfield' or ops[2].args[1].value != 'typeptr' or
-            not isinstance(ops[2].args[1], Constant) or
-            _llvm_structsize(ops[0].args[0]) > ringbuffer_entry_maxsize): #todo: ops[2].args[2] to vtable
+        if len(ops) < 3 or \
+           ops[0].opname != 'malloc'   or ops[1].opname != 'cast_pointer'   or \
+           ops[2].opname != 'setfield' or ops[2].args[1].value != 'typeptr' or \
+           not isinstance(ops[2].args[1], Constant):
+            continue
+        name = str(ops[0].args[0])
+        if 'Exception' not in name and 'Error' not in name: #XXX better to look at the actual structure
             continue
-        print 'remove_exception_malloc: ', str(ops[0].args[0]), ops[2].args[2]
-        #ops = [SpaceOperation('ops[0].result = load sbyte** %exception_ringbuffer'),
-        #       SpaceOperation('%tmpptr.0 = add sbyte* ops[0].result, ringbuffer_entry_maxsize'),
-        #       SpaceOperation('%tmpptr.1 = and sbyte* tmpptr.0, ~(ringbuffer_n_entries*ringbuffer_entry_maxsize)'),
-        #       SpaceOperation('store sbyte* %tmpptr.1, sbyte** %exception_ringbuffer),
-        #       ops[1:]]
+        print 'remove_exception_malloc: ', name
+        ops[0].opname = 'malloc_exception'  #XXX refactor later to not use a new operationtype
+        n_removed += 1
+    return n_removed

Modified: pypy/dist/pypy/translator/llvm/exception.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/exception.py	(original)
+++ pypy/dist/pypy/translator/llvm/exception.py	Wed Sep 28 15:51:55 2005
@@ -2,8 +2,27 @@
 
 
 class ExceptionPolicy:
+    RINGBUGGER_SIZE          = 8192
     RINGBUFFER_ENTRY_MAXSIZE = 16
-    RINGBUGGER_N_ENTRIES = 1024
+    RINGBUGGER_OVERSIZE      = RINGBUGGER_SIZE + RINGBUFFER_ENTRY_MAXSIZE
+    RINGBUFFER_LLVMCODE      = '''
+internal fastcc sbyte* %%malloc_exception(uint %%nbytes) {
+    %%cond = setle uint %%nbytes, %d
+    br bool %%cond, label %%then, label %%else
+
+then:
+    %%tmp.3 = load uint* %%exception_ringbuffer_index
+    %%tmp.4 = getelementptr [%d x sbyte]* %%exception_ringbuffer, int 0, uint %%tmp.3
+    %%tmp.6 = add uint %%tmp.3, %%nbytes
+    %%tmp.7 = and uint %%tmp.6, %d
+    store uint %%tmp.7, uint* %%exception_ringbuffer_index
+    ret sbyte* %%tmp.4
+
+else:
+    %%tmp.8  = call ccc sbyte* %%GC_malloc(uint %%nbytes)
+    ret sbyte* %%tmp.8
+}
+''' % (RINGBUFFER_ENTRY_MAXSIZE, RINGBUGGER_OVERSIZE, RINGBUGGER_SIZE-1)
 
     def __init__(self):
         raise Exception, 'ExceptionPolicy should not be used directly'
@@ -81,7 +100,7 @@
 internal fastcc void %%unwind() {
     unwind
 }
-''' % locals()
+''' % locals() + self.RINGBUFFER_LLVMCODE
 
     def invoke(self, codewriter, targetvar, tail_, cconv, returntype, functionref, args, label, except_label):
         labels = 'to label %%%s except label %%%s' % (label, except_label)
@@ -174,7 +193,7 @@
 internal fastcc void %%unwind() {
     ret void
 }
-''' % locals()
+''' % locals() + self.RINGBUFFER_LLVMCODE
 
     def transform(self, translator, graph=None):
         from pypy.translator.llvm.backendopt.exception import create_exception_handling

Modified: pypy/dist/pypy/translator/llvm/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm/funcnode.py	Wed Sep 28 15:51:55 2005
@@ -40,7 +40,12 @@
         self.ref   = self.make_ref('%pypy_', value.graph.name)
         self.graph = value.graph
         self.db.genllvm.exceptionpolicy.transform(self.db.translator, self.graph)
-        #remove_exception_mallocs(self.db.translator, self.graph)
+        if remove_exception_mallocs(self.db.translator, self.graph):
+            print '            from function', self.ref
+            import sys
+            sys.stdout.flush()
+            #if self.ref not in ('%pypy_ll_raise_OSError__Signed', '%pypy_getitem'):
+            #    self.db.translator.view()
         #merge_mallocs(self.db.translator, self.graph)
         remove_double_links(self.db.translator, self.graph)
 

Modified: pypy/dist/pypy/translator/llvm/gc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/gc.py	(original)
+++ pypy/dist/pypy/translator/llvm/gc.py	Wed Sep 28 15:51:55 2005
@@ -10,8 +10,6 @@
 
     def malloc(self, targetvar, type_, size, is_atomic, word, uword):
         s = str(size)
-        if s == '0':
-            return '%(targetvar)s = cast %(type_)s* null to %(type_)s* ;was malloc 0 bytes' % locals()
         return '%(targetvar)s = malloc %(type_)s, uint %(s)s' % locals()
 
     def pyrex_code(self):
@@ -61,8 +59,6 @@
 
     def malloc(self, targetvar, type_, size, is_atomic, word, uword):
         s = str(size)
-        if s == '0':
-            return '%(targetvar)s = cast %(type_)s* null to %(type_)s* ;was malloc 0 bytes' % locals()
         self.n_malloced += 1
         cnt = '.%d' % self.n_malloced
         atomic = is_atomic and '_atomic' or ''

Modified: pypy/dist/pypy/translator/llvm/module/extfunction.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/extfunction.py	(original)
+++ pypy/dist/pypy/translator/llvm/module/extfunction.py	Wed Sep 28 15:51:55 2005
@@ -2,8 +2,9 @@
 %last_exception_type  = internal global %RPYTHON_EXCEPTION_VTABLE* null
 %last_exception_value = internal global %RPYTHON_EXCEPTION* null
 
-%exception_ringbuffer = internal global [8192 x sbyte] zeroinitializer
-%exception_ringbuffer_index = internal global int 0
+;8208=8192+16 in the next line because the last one (16 bytes maxsize) might start at 8190 for instance.
+%exception_ringbuffer = internal global [8208 x sbyte] zeroinitializer
+%exception_ringbuffer_index = internal global uint 0
 '''
 
 extfunctions = {}   #dependencies, llvm-code

Modified: pypy/dist/pypy/translator/llvm/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/opwriter.py	(original)
+++ pypy/dist/pypy/translator/llvm/opwriter.py	Wed Sep 28 15:51:55 2005
@@ -387,6 +387,18 @@
             ep.reraise(self.node, self.codewriter)
         ep.fetch_exceptions(self.codewriter, exc_found_labels, lltype_of_exception_type, lltype_of_exception_value)
 
+    def malloc_exception(self, op): 
+        arg_type = op.args[0].value
+        targetvar = self.db.repr_arg(op.result) 
+        type_ = self.db.repr_type(arg_type)
+        tmpvar1 = self.db.repr_tmpvar()
+        tmpvar2 = self.db.repr_tmpvar()
+        tmpvar3 = self.db.repr_tmpvar()
+        self.codewriter.indent('%(tmpvar1)s = getelementptr %(type_)s* null, int 1' % locals())
+        self.codewriter.cast(tmpvar2, type_+'*', tmpvar1, 'uint')
+        self.codewriter.call(tmpvar3, 'sbyte*', '%malloc_exception', [tmpvar2], ['uint'])
+        self.codewriter.cast(targetvar, 'sbyte*', tmpvar3, type_+'*')
+
     def malloc(self, op): 
         arg_type = op.args[0].value
         targetvar = self.db.repr_arg(op.result) 
@@ -397,7 +409,7 @@
         arg_type = op.args[0].value
         if isinstance(arg_type, lltype.Array) and arg_type.OF is lltype.Void:
             # This is a backend decision to NOT represent a void array with
-            # anything and save space - therefore not varsizeda anymore
+            # anything and save space - therefore not varsized anymore
             self.malloc(op)
             return
         



More information about the Pypy-commit mailing list