[pypy-svn] r32145 - in pypy/dist/pypy: rpython/memory translator/llvm translator/llvm/module

arigo at codespeak.net arigo at codespeak.net
Mon Sep 11 13:58:08 CEST 2006


Author: arigo
Date: Mon Sep 11 13:58:06 2006
New Revision: 32145

Modified:
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/translator/llvm/database.py
   pypy/dist/pypy/translator/llvm/gc.py
   pypy/dist/pypy/translator/llvm/module/genexterns.c
   pypy/dist/pypy/translator/llvm/opwriter.py
   pypy/dist/pypy/translator/llvm/structnode.py
Log:
Started support for --gc=framework in llvm.  Cleaned up and support more
address and offset features.  Always do raisingop2direct_call in the graphs
produced by the GC (because they come after the normal backend_optimize() has
been called).

Now we die in llvm's own optimizers in a failed assertion.  Hard to test our
code now :-(((  It's known to be incomplete, though.


Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Mon Sep 11 13:58:06 2006
@@ -947,7 +947,7 @@
             annmodel.s_None)
 
         annhelper.finish()   # at this point, annotate all mix-level helpers
-        annhelper.backend_optimize()
+        annhelper.backend_optimize(raisingop2direct_call_all=True)
 
         self.collect_analyzer = CollectAnalyzer(self.translator)
         self.collect_analyzer.analyze_all()

Modified: pypy/dist/pypy/translator/llvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/database.py	(original)
+++ pypy/dist/pypy/translator/llvm/database.py	Mon Sep 11 13:58:06 2006
@@ -144,6 +144,11 @@
     def prepare_constant(self, type_, value):
         if isinstance(type_, lltype.Primitive):
             #log.prepareconstant(value, "(is primitive)")
+            if type_ is llmemory.Address:
+                # prepare the constant data which this address references
+                assert isinstance(value, llmemory.fakeaddress)
+                if value.ob is not None:
+                    self.prepare_constant(lltype.typeOf(value.ob), value.ob)
             return
         
         if isinstance(type_, lltype.Ptr):
@@ -229,10 +234,10 @@
                 return self.primitives.repr(arg.concretetype, arg.value)
             else:
                 assert isinstance(arg.value, lltype._ptr)
-                node = self.obj2node.get(arg.value._obj)
-                if node is None:
+                if not arg.value:
                     return 'null'
                 else:
+                    node = self.obj2node[arg.value._obj]
                     return node.get_ref()
         else:
             assert isinstance(arg, Variable)
@@ -405,9 +410,11 @@
         
     def repr(self, type_, value):
         try:
-            return self.reprs[type_](type_, value)
+            reprfn = self.reprs[type_]
         except KeyError:
             raise Exception, "unsupported primitive type %r, value %r" % (type_, value)
+        else:
+            return reprfn(type_, value)
         
     def repr_default(self, type_, value):
         return str(value)
@@ -461,14 +468,22 @@
             from_, indices, to = self.get_offset(value.offset)
             indices_as_str = ", ".join("%s %s" % (w, i) for w, i in indices)
 
-            original_typename = self.database.repr_type(from_)
-            orignal_ref = self.database.repr_name(value.ob._obj)
+            #original_typename = self.database.repr_type(from_)
+            #orignal_ref = self.database.repr_name(value.ob._obj)
+            #
+            #typename = self.database.repr_type(to)
+            #ref = "getelementptr(%s* %s, %s)" % (original_typename,
+            #                                     orignal_ref,
+            #                                     indices_as_str)
+
+            ptrtype = self.database.repr_type(lltype.Ptr(from_))
+            node = self.database.obj2node[value.ob._obj]
+            parentref = node.get_pbcref(ptrtype)
 
             typename = self.database.repr_type(to)
-            ref = "getelementptr(%s* %s, %s)" % (original_typename,
-                                                 orignal_ref,
-                                                 indices_as_str)
-            
+            ref = "getelementptr(%s %s, %s)" % (ptrtype, parentref,
+                                                indices_as_str)
+
         res = "cast(%s* %s to sbyte*)" % (typename, ref)
         return res    
     
@@ -506,42 +521,46 @@
         
         return repr
     
-    def get_offset(self, value, fromoffset=False):
+    def get_offset(self, value, initialindices=None):
         " return (from_type, (indices, ...), to_type) "        
         word = self.database.get_machine_word()
         uword = self.database.get_machine_uword()
-        indices = []
+        indices = initialindices or [(word, 0)]
 
         if isinstance(value, llmemory.ItemOffset):
             # skips over a fixed size item (eg array access)
             from_ = value.TYPE
-            indices.append((word, value.repeat))
+            lasttype, lastvalue = indices[-1]
+            assert lasttype == word
+            indices[-1] = (word, lastvalue + value.repeat)
             to = value.TYPE
         
         elif isinstance(value, llmemory.FieldOffset):
             # jumps to a field position in a struct
             from_ = value.TYPE
             pos = getindexhelper(value.fldname, value.TYPE)
-            if not fromoffset:
-                indices.append((word, 0))
             indices.append((uword, pos))
             to = getattr(value.TYPE, value.fldname)            
-                
+
+        elif isinstance(value, llmemory.ArrayLengthOffset):
+            # jumps to the place where the array length is stored
+            from_ = value.TYPE     # <Array of T> or <GcArray of T>
+            assert isinstance(value.TYPE, lltype.Array)
+            indices.append((uword, 0))
+            to = lltype.Signed
+
         elif isinstance(value, llmemory.ArrayItemsOffset):
             # jumps to the beginning of array area
             from_ = value.TYPE
-            if not fromoffset:
-                indices.append((word, 0))
             if not isinstance(value.TYPE, lltype.FixedSizeArray):
                 indices.append((uword, 1))
+            indices.append((word, 0))    # go to the 1st item
             to = value.TYPE.OF
 
         elif isinstance(value, llmemory.CompositeOffset):
-            from_, indices, to = self.get_offset(value.offsets[0])
-            indices = list(indices)
+            from_, indices, to = self.get_offset(value.offsets[0], indices)
             for item in value.offsets[1:]:
-                _, more, to = self.get_offset(item, fromoffset=True)
-                indices.extend(more)
+                _, indices, to = self.get_offset(item, indices)
 
         else:
             raise Exception("unsupported offset")

Modified: pypy/dist/pypy/translator/llvm/gc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/gc.py	(original)
+++ pypy/dist/pypy/translator/llvm/gc.py	Mon Sep 11 13:58:06 2006
@@ -119,6 +119,8 @@
             gcpolicy = RefcountingGcPolicy(db)
         elif gcpolicy in ('none', 'raw'):
             gcpolicy = RawGcPolicy(db)
+        elif gcpolicy == 'framework':
+            gcpolicy = FrameworkGcPolicy(db)
         else:
             raise Exception, 'unknown gcpolicy: ' + str(gcpolicy)
         return gcpolicy
@@ -186,10 +188,14 @@
         uword = self.db.get_machine_uword()
 
         fnname = '%pypy_malloc' + (atomic and '_atomic' or '')
-        if self.exc_useringbuf and exc_flag:
-            fnname += '_ringbuffer'
-            # dont clear the ringbuffer data
-            atomic = False 
+
+##        XXX (arigo) disabled the ring buffer for comparison purposes
+##        XXX until we know if it's a valid optimization or not
+
+##        if self.exc_useringbuf and exc_flag:
+##            fnname += '_ringbuffer'
+##            # dont clear the ringbuffer data
+##            atomic = False 
 
         # malloc_size is unsigned right now
         sizei = '%malloc_sizei' + self.get_count()        
@@ -218,3 +224,19 @@
     def op_free(self, codewriter, opr):
         assert opr.rettype == 'void' and len(opr.argtypes) == 1
         codewriter.free(opr.argtypes[0], opr.argrefs[0])
+
+class FrameworkGcPolicy(GcPolicy):
+
+    def __init__(self, db):
+        self.db = db
+
+    def genextern_code(self):
+        # XXX
+        # This is not finished: we must call the gc init function!
+        r  = ''
+        r += '#define __GC_STARTUP_CODE__\n'
+        r += '#define __GC_SETUP_CODE__\n'
+        return r
+
+    def gc_libraries(self):
+        return ['pthread']

Modified: pypy/dist/pypy/translator/llvm/module/genexterns.c
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/genexterns.c	(original)
+++ pypy/dist/pypy/translator/llvm/module/genexterns.c	Mon Sep 11 13:58:06 2006
@@ -37,6 +37,10 @@
   memcpy((void *) ptr2, (void *) ptr1, size);
 }
 
+void raw_memclear(void* ptr, long size) {
+  memset(ptr, 0, size);
+}
+
 char *LLVM_RPython_StartupCode();
 
 char *RPython_StartupCode() {

Modified: pypy/dist/pypy/translator/llvm/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/opwriter.py	(original)
+++ pypy/dist/pypy/translator/llvm/opwriter.py	Mon Sep 11 13:58:06 2006
@@ -359,6 +359,8 @@
             self.codewriter.store(opr.argtypes[2], opr.argrefs[2], tmpvar)
         else:
             self._skipped(opr)
+
+    bare_setfield = setfield
             
     def getarrayitem(self, opr):        
         if opr.rettype == "void":
@@ -451,6 +453,10 @@
         self.codewriter.call(opr.retref, opr.rettype, "%raw_malloc",
                              opr.argtypes, opr.argrefs)
 
+    def raw_malloc_usage(self, opr):
+        self.codewriter.cast(opr.retref, opr.argtypes[0], opr.argrefs[0],
+                             opr.rettype)
+
     def raw_free(self, opr):
         self.codewriter.call(opr.retref, opr.rettype, "%raw_free",
                              opr.argtypes, opr.argrefs)
@@ -459,6 +465,10 @@
         self.codewriter.call(opr.retref, opr.rettype, "%raw_memcopy",
                              opr.argtypes, opr.argrefs)
 
+    def raw_memclear(self, opr):
+        self.codewriter.call(opr.retref, opr.rettype, "%raw_memclear",
+                             opr.argtypes, opr.argrefs)
+
     def raw_store(self, opr):
         arg_addr, arg_dummy, arg_incr, arg_value = opr.argrefs
         (argtype_addr, argtype_dummy,
@@ -503,3 +513,6 @@
             cast_addr = incr_addr
 
         self.codewriter.load(opr.retref, opr.rettype, cast_addr) 
+
+    def debug_print(self, opr):
+        pass     # XXX

Modified: pypy/dist/pypy/translator/llvm/structnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/structnode.py	(original)
+++ pypy/dist/pypy/translator/llvm/structnode.py	Mon Sep 11 13:58:06 2006
@@ -259,6 +259,7 @@
                 found = True
                 break
             pos += 1
+        assert found
 
         ref = "getelementptr(%s* %s, int 0, uint %s)" %(
             self.get_typerepr(),



More information about the Pypy-commit mailing list