[pypy-svn] r22400 - pypy/dist/pypy/translator/llvm

rxe at codespeak.net rxe at codespeak.net
Wed Jan 18 22:20:35 CET 2006


Author: rxe
Date: Wed Jan 18 22:20:33 2006
New Revision: 22400

Modified:
   pypy/dist/pypy/translator/llvm/arraynode.py
   pypy/dist/pypy/translator/llvm/gc.py
   pypy/dist/pypy/translator/llvm/opwriter.py
   pypy/dist/pypy/translator/llvm/structnode.py
Log:
ooops forgot to complete refactoring the codewriter interface in gc.py - 
done now.

Added an experimental variable size malloc to gc policy - heading towards using
a policy object for flavoured mallocs (dont even know if this is a good idea,
or even an idea at all)
 
Might actually be (very) marginally faster now.



Modified: pypy/dist/pypy/translator/llvm/arraynode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/arraynode.py	(original)
+++ pypy/dist/pypy/translator/llvm/arraynode.py	Wed Jan 18 22:20:33 2006
@@ -47,15 +47,22 @@
                             self.db.repr_type(self.arraytype))
 
     def writedecl(self, codewriter): 
-        # declaration for constructor
+        return #XXX tmp?
+
         codewriter.declare(self.constructor_decl)
 
     def writeimpl(self, codewriter):
+        return  #XXX tmp?
+
+        current, indices_to_array = self.var_malloc_info()
         log.writeimpl(self.ref)
         gp = self.db.gcpolicy
         gp.write_constructor(codewriter, self.ref, self.constructor_decl,
-                             self.array, atomic=self.array._is_atomic())
+                             current, atomic=self.array._is_atomic())
 
+    def var_malloc_info(self):
+        return self.array, ()
+    
 class VoidArrayTypeNode(LLVMNode):
     __slots__ = "db array ref".split()
 

Modified: pypy/dist/pypy/translator/llvm/gc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/gc.py	(original)
+++ pypy/dist/pypy/translator/llvm/gc.py	Wed Jan 18 22:20:33 2006
@@ -1,3 +1,4 @@
+import sys
 from pypy.rpython.rstr import STR
 
 from pypy.translator.llvm.log import log
@@ -6,149 +7,184 @@
 class GcPolicy:
     def __init__(self, db):
         raise Exception, 'GcPolicy should not be used directly'
-
+    
     def genextern_code(self):
         return ""
     
     def gc_libraries(self):
         return []
-
-    # malloc is not an codewriter specific thing
-    def malloc(self, codewriter, targetvar, type_, size=1, atomic=False):
-        # XXX _indent & test
-        codewriter._indent('%(targetvar)s = malloc %(type_)s, uint %(s)s' % locals())
     
-    def write_constructor(self, codewriter, ref, constructor_decl, ARRAY, 
-                          indices_to_array=(), atomic=False, is_str=False):
-
-
-        #varsized arrays and structs look like this: 
-        #Array: {int length , elemtype*}
-        #Struct: {...., Array}
-
-        # the following indices access the last element in the array
-        elemtype = self.db.repr_type(ARRAY.OF)
-        word = lentype = self.db.get_machine_word()
-        uword = self.db.get_machine_uword()
-
-        codewriter.openfunc(constructor_decl)    
-
-        # Need room for NUL terminator
-        if ARRAY is STR.chars:
-            codewriter.binaryop("add", "%actuallen", lentype, "%len", 1)
-        else:
-            codewriter.cast("%actuallen", lentype, "%len", lentype)
-
-        elemindices = list(indices_to_array)
-        elemindices += [("uint", 1), (lentype, "%actuallen")]
-        codewriter.getelementptr("%size", ref + "*", "null", elemindices) 
-        codewriter.cast("%usize", elemtype + "*", "%size", uword)
-        self.malloc(codewriter, "%ptr", "sbyte*", "%usize", atomic=atomic)
-        codewriter.cast("%result", "sbyte*", "%ptr", ref + "*")
-
-        indices_to_arraylength = tuple(indices_to_array) + (("uint", 0),)
-
-        # the following accesses the length field of the array 
-        codewriter.getelementptr("%arraylength", ref + "*", 
-                                 "%result", 
-                                 indices_to_arraylength)
-        codewriter.store(lentype, "%len", "%arraylength")
-
-        #if is_str:
-        #    indices_to_hash = (("uint", 0),)
-        #    codewriter.getelementptr("%ptrhash", ref + "*", 
-        #                             "%result", 
-        #                             indices_to_hash)
-        #    codewriter.store("int", "0", "%ptrhash")
-
-
-        #if ARRAY is STR.chars:
-        #    codewriter.getelementptr("%ptrendofchar", ref + "*", 
-        #                             "%result", 
-        #                             elemindices)
-        #    codewriter.store(elemtype, "0", "%ptrendofchar")
-
-        codewriter.ret(ref + "*", "%result")
-        codewriter.closefunc()
-
     def pyrex_code(self):
         return ''
+    
+    #XXX tmp?
+##     def write_constructor(self, codewriter, ref, constructor_decl, ARRAY, 
+##                           indices_to_array=(), atomic=False):
+        
+##         # the following indices access the last element in the array
+##         elemtype = self.db.repr_type(ARRAY.OF)
+##         word = lentype = self.db.get_machine_word()
+##         uword = self.db.get_machine_uword()
+        
+##         codewriter.openfunc(constructor_decl)    
+
+##         # Need room for NUL terminator
+##         if ARRAY is STR.chars:
+##             codewriter.binaryop("add", "%actuallen", lentype, "%len", 1)
+##         else:
+##             codewriter.cast("%actuallen", lentype, "%len", lentype)
+            
+##         elemindices = list(indices_to_array)
+##         elemindices += [("uint", 1), (lentype, "%actuallen")]
+##         codewriter.getelementptr("%size", ref + "*", "null", elemindices) 
+##         codewriter.cast("%usize", elemtype + "*", "%size", uword)
+        
+##         self._malloc(codewriter, "%ptr", "%usize", atomic=atomic)
+##         codewriter.cast("%result", "sbyte*", "%ptr", ref + "*")
+
+##         indices_to_arraylength = tuple(indices_to_array) + (("uint", 0),)
+
+##         # the following accesses the length field of the array 
+##         codewriter.getelementptr("%arraylength", ref + "*", 
+##                                  "%result", 
+##                                  indices_to_arraylength)
+##         codewriter.store(lentype, "%len", "%arraylength")
+        
+##         codewriter.ret(ref + "*", "%result")
+##         codewriter.closefunc()
 
-    def new(db, gcpolicy=None):  #factory
-        gcpolicy = gcpolicy or 'boehm'
+    def malloc(self, codewriter, targetvar, type_, size=1, atomic=False):
+        raise NotImplementedError, 'GcPolicy should not be used directly'
 
+    def new(db, gcpolicy=None):
+        """ factory """
+        gcpolicy = gcpolicy or 'boehm'
+        
+        # XXX would be nice to localise this sort of thing?
         import distutils.sysconfig
         from os.path import exists
         libdir = distutils.sysconfig.EXEC_PREFIX + "/lib"  
         boehm_on_path = exists(libdir + '/libgc.so') or exists(libdir + '/libgc.a')
         if gcpolicy == 'boehm' and not boehm_on_path:
             log.gc.WARNING('warning: Boehm GC libary not found in /usr/lib, falling back on no gc')
-            gcpolicy = 'none'
+            gcpolicy = 'raw'
 
         if gcpolicy == 'boehm':
             gcpolicy = BoehmGcPolicy(db)
         elif gcpolicy == 'ref':
             gcpolicy = RefcountingGcPolicy(db)
-        elif gcpolicy == 'none':
-            gcpolicy = NoneGcPolicy(db)
+        elif gcpolicy == 'raw':
+            gcpolicy = RawGcPolicy(db)
         else:
             raise Exception, 'unknown gcpolicy: ' + str(gcpolicy)
         return gcpolicy
     new = staticmethod(new)
 
-
-class NoneGcPolicy(GcPolicy):
+class RawGcPolicy(GcPolicy):
     def __init__(self, db):
         self.db = db
 
-
+    def malloc(self, codewriter, targetvar, type_, size=1, atomic=False):
+        codewriter.malloc(targetvar, type_, size)
+        #XXX memset
+        
 class BoehmGcPolicy(GcPolicy):
     def __init__(self, db):
         self.db = db
         self.n_malloced = 0
-
+        
     def genextern_code(self):
         return '#include "boehm.h"'
-
+    
     def gc_libraries(self):
         return ['gc', 'pthread'] # XXX on windows?
 
-    def malloc(self, codewriter, targetvar, type_, size=1, atomic=False):
-        import sys
+    def pyrex_code(self):
+        return '''
+cdef extern int GC_get_heap_size()
+
+def GC_get_heap_size_wrapper():
+    return GC_get_heap_size()
+'''
+
+    def _malloc(self, codewriter, targetvar, size=1, atomic=False):
+        """ assumes malloc of word size """
+        # XXX Boehm aligns on 8 byte boundaries
     	if sys.platform == 'linux2' and sys.maxint == 2**63-1:
             boundary_size = 8
 	else:
-            boundary_size = 0            
+            boundary_size = 0
 
-        is_atomic = atomic
         uword = self.db.get_machine_uword()
-        s = str(size)
+        fnname = '%pypy_malloc' + (atomic and '_atomic' or '')
+        codewriter.call(targetvar, 'sbyte*', fnname, [uword], [size])
+        
+        if atomic:
+            codewriter.call(None, 'void', '%llvm.memset',
+                            ['sbyte*', 'ubyte', uword, uword],
+                            [targetvar, 0, size, boundary_size],
+                            cconv='ccc')        
+
+    def malloc(self, codewriter, targetvar, type_, size=1, atomic=False):
+        uword = self.db.get_machine_uword()
         self.n_malloced += 1
-        cnt = '.%d' % self.n_malloced
-        atomic = is_atomic and '_atomic' or ''
-        t = '''
-%%malloc_Size%(cnt)s  = getelementptr %(type_)s null, %(uword)s %(s)s
-%%malloc_SizeU%(cnt)s = cast %(type_)s %%malloc_Size%(cnt)s to %(uword)s
-%%malloc_Ptr%(cnt)s   = call fastcc sbyte* %%pypy_malloc%(atomic)s(%(uword)s %%malloc_SizeU%(cnt)s)
-%(targetvar)s = cast sbyte* %%malloc_Ptr%(cnt)s to %(type_)s
-''' % locals()
-
-        if is_atomic:   #Boehm aligns on 8 byte boundaries
-            t += '''
-        call ccc void %%llvm.memset(sbyte* %%malloc_Ptr%(cnt)s, ubyte 0, %(uword)s %%malloc_SizeU%(cnt)s, %(uword)s %(boundary_size)s)
-        ''' % locals()
-        codewriter.write_lines(t)
+        cnt = '_%d' % self.n_malloced
+        malloc_ptr = '%malloc_ptr' + cnt
+        malloc_size = '%malloc_size' + cnt
+        malloc_sizeu = '%malloc_sizeu' + cnt
+        
+        codewriter.getelementptr(malloc_size, type_, 'null',
+                                 [(uword, size)], getptr=False)
+        codewriter.cast(malloc_sizeu, type_, malloc_size, uword)
+        self._malloc(codewriter, malloc_ptr, malloc_sizeu, atomic)
+        codewriter.cast(targetvar, 'sbyte*', malloc_ptr, type_)            
 
+    def var_malloc(self, codewriter, targetvar,
+                   type_, node, len, atomic=False):
 
-    def pyrex_code(self):
-        return '''
-cdef extern int GC_get_heap_size()
+        word = lentype = self.db.get_machine_word()
+        uword = self.db.get_machine_uword()
+        self.n_malloced += 1
+        cnt = '_%d' % self.n_malloced
+        malloc_ptr = '%malloc_ptr' + cnt
+        malloc_size = '%malloc_size' + cnt
+        malloc_sizeu = '%malloc_sizeu' + cnt
+        actuallen = '%actuallen' + cnt
+        arraylength = '%arraylength' + cnt
+        
+        ARRAY, indices_to_array = node.var_malloc_info()
+        
+        #varsized arrays and structs look like this: 
+        #Array: {int length , elemtype*}
+        #Struct: {...., Array}
+        
+        # the following indices access the last element in the array
+        elemtype = self.db.repr_type(ARRAY.OF)
+        word = lentype = self.db.get_machine_word()
+        uword = self.db.get_machine_uword()
+        
+        # need room for NUL terminator
+        if ARRAY is STR.chars:
+            codewriter.binaryop('add', actuallen, lentype, len, 1)
+        else:
+            codewriter.cast(actuallen, lentype, len, lentype)
+            
+        elemindices = list(indices_to_array)
+        elemindices += [('uint', 1), (lentype, actuallen)]
+        codewriter.getelementptr(malloc_size, type_, 'null', elemindices) 
+        codewriter.cast(malloc_sizeu, elemtype + '*', malloc_size, uword)
+        
+        self._malloc(codewriter, malloc_ptr, malloc_sizeu, atomic=atomic)
 
-def GC_get_heap_size_wrapper():
-    return GC_get_heap_size()
-'''
+        indices_to_arraylength = tuple(indices_to_array) + (('uint', 0),)
+
+        codewriter.cast(targetvar, 'sbyte*', malloc_ptr, type_)
 
+        # the following accesses the length field of the array 
+        codewriter.getelementptr(arraylength, type_, 
+                                 targetvar,  indices_to_arraylength)
+        codewriter.store(lentype, len, arraylength)
 
 class RefcountingGcPolicy(GcPolicy):
-    def __init__(self):
+    def __init__(self, db):
         raise NotImplementedError, 'RefcountingGcPolicy'

Modified: pypy/dist/pypy/translator/llvm/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/opwriter.py	(original)
+++ pypy/dist/pypy/translator/llvm/opwriter.py	Wed Jan 18 22:20:33 2006
@@ -269,7 +269,7 @@
 
     def malloc_varsize(self, opr):
 
-        # XXX transformation
+        # XXX transformation perhaps?
         arg_type = opr.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
@@ -277,9 +277,14 @@
             self.malloc(opr)
             return
 
-        self.codewriter.call(opr.retref, opr.rettype,
-                             self.db.repr_constructor(arg_type),
-                             opr.argtypes[1:], opr.argrefs[1:])
+        node = self.db.obj2node[arg_type]
+        self.db.gcpolicy.var_malloc(self.codewriter, opr.retref, opr.rettype,
+                                    node, opr.argrefs[1],
+                                    atomic=arg_type._is_atomic())
+        #XXX tmp?
+        #self.codewriter.call(opr.retref, opr.rettype,
+        #                     self.db.repr_constructor(arg_type),
+        #                     opr.argtypes[1:], opr.argrefs[1:])
 
     def flavored_malloc(self, opr):
         flavor = opr.op.args[0].value

Modified: pypy/dist/pypy/translator/llvm/structnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/structnode.py	(original)
+++ pypy/dist/pypy/translator/llvm/structnode.py	Wed Jan 18 22:20:33 2006
@@ -55,29 +55,37 @@
 
     def writedecl(self, codewriter): 
         # declaration for constructor
+        return #XXX
+
         codewriter.declare(self.constructor_decl)
 
     def writeimpl(self, codewriter):
+        return #XXX
+
         log.writeimpl(self.ref)
+        current, indices_to_array = self.var_malloc_info()
+        gp = self.db.gcpolicy
+        gp.write_constructor(codewriter, 
+                             self.ref,
+                             self.constructor_decl,
+                             current, 
+                             indices_to_array,
+                             self.struct._is_atomic())
 
+    def var_malloc_info(self):
         # build up a list of indices to get to the last 
         # var-sized struct (or rather the according array) 
         indices_to_array = []
         current = self.struct
         while isinstance(current, lltype.Struct):
             last_pos = len(current._names_without_voids()) - 1
-            indices_to_array.append(("uint", last_pos)) #struct requires uint consts
+            # struct requires uint consts
+            indices_to_array.append(("uint", last_pos))
             name = current._names_without_voids()[-1]
             current = current._flds[name]
         assert isinstance(current, lltype.Array)
-        gp = self.db.gcpolicy
-        gp.write_constructor(codewriter, 
-                             self.ref,
-                             self.constructor_decl,
-                             current, 
-                             indices_to_array,
-                             self.struct._is_atomic(),
-                             is_str=self.struct._name == "rpy_string")
+
+        return current, indices_to_array
 
 class StructNode(ConstantLLVMNode):
     """ A struct constant.  Can simply contain



More information about the Pypy-commit mailing list