[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