[pypy-svn] r16262 - pypy/dist/pypy/translator/c

pedronis at codespeak.net pedronis at codespeak.net
Tue Aug 23 14:02:24 CEST 2005


Author: pedronis
Date: Tue Aug 23 14:02:22 2005
New Revision: 16262

Modified:
   pypy/dist/pypy/translator/c/database.py
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/gc.py
   pypy/dist/pypy/translator/c/node.py
Log:
reorganized code in node.py in preparation to move the refcounting logic
to the respective policy through hooks

(cfbolz, pedronis)



Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py	(original)
+++ pypy/dist/pypy/translator/c/database.py	Tue Aug 23 14:02:22 2005
@@ -74,7 +74,7 @@
             argtypes = ', '.join(argtypes) or 'void'
             return resulttype.replace('@', '(@)(%s)' % argtypes)
         elif isinstance(T, OpaqueType):
-            if T == RuntimeTypeInfo:
+            if T == RuntimeTypeInfo: # xxx -> gc
                 return 'void (@)(void *)'   # void dealloc_xx(struct xx *)
             elif hasattr(T, '_exttypeinfo'):
                 # for external types (pypy.rpython.extfunctable.declaretype())
@@ -128,8 +128,8 @@
                 return 'Py_XINCREF(%s);' % expr
             else:
                 defnode = self.gettypedefnode(T.TO)
-                if defnode.refcount is not None:
-                    return 'if (%s) %s->%s++;' % (expr, expr, defnode.refcount)
+                if defnode.gcheader is not None:
+                    return 'if (%s) %s->%s++;' % (expr, expr, defnode.gcheader)
         return ''
 
     def cdecrefstmt(self, expr, T):
@@ -138,10 +138,13 @@
                 return 'Py_XDECREF(%s);' % expr
             else:
                 defnode = self.gettypedefnode(T.TO)
-                if defnode.refcount is not None:
+                if defnode.gcheader is not None:
+                    dealloc = 'OP_FREE'
+                    if defnode.gcinfo:
+                        dealloc = defnode.gcinfo.deallocator or dealloc
                     return 'if (%s && !--%s->%s) %s(%s);' % (expr, expr,
-                                                             defnode.refcount,
-                                               defnode.deallocator or 'OP_FREE',
+                                                             defnode.gcheader,
+                                                             dealloc,
                                                              expr)
         return ''
 

Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Tue Aug 23 14:02:22 2005
@@ -397,8 +397,7 @@
         T = self.lltypemap(op.result)
         newvalue = self.expr(op.result, special_case_void=False)
         result = ['%s = %s;' % (newvalue, sourceexpr)]
-        # need to adjust the refcount of the result
-
+        # need to adjust the refcount of the result only for PyObjects
         line = self.pyobj_incref_expr(newvalue, T)
         if line:
             result.append(line)
@@ -480,7 +479,7 @@
                                                            eresult,
                                                            err),
                   '%s->%s = 0;' % (eresult, # xxx the incref is generically done on the results
-                                   self.db.gettypedefnode(TYPE).refcount),
+                                   self.db.gettypedefnode(TYPE).gcheader),
                   ]
         return '\t'.join(result)
 
@@ -509,7 +508,7 @@
                   '%s->%s = %s;' % (eresult, lenfld,
                                     elength),
                   '%s->%s = 0;' % (eresult,             # xxx the incref is generically done on the results
-                                   nodedef.refcount),
+                                   nodedef.gcheader),
                   ]
         return '\t'.join(result)
 

Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Tue Aug 23 14:02:22 2005
@@ -39,15 +39,18 @@
 
     def push_alive_nopyobj(self, expr, T):
         defnode = self.db.gettypedefnode(T.TO)
-        if defnode.refcount is not None:
-            return 'if (%s) %s->%s++;' % (expr, expr, defnode.refcount)
+        if defnode.gcheader is not None:
+            return 'if (%s) %s->%s++;' % (expr, expr, defnode.gcheader)
 
     def pop_alive_nopyobj(self, expr, T):
         defnode = self.db.gettypedefnode(T.TO)
-        if defnode.refcount is not None:
+        if defnode.gcheader is not None:
+            dealloc = 'OP_FREE'
+            if defnode.gcinfo:
+                dealloc = defnode.gcinfo.deallocator or dealloc
             return 'if (%s && !--%s->%s) %s(%s);' % (expr, expr,
-                                                     defnode.refcount,
-                                                     defnode.deallocator or 'OP_FREE',
+                                                     defnode.gcheader,
+                                                     dealloc,
                                                      expr)
 
     def push_alive_op_result(self, opname, expr, T):

Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py	(original)
+++ pypy/dist/pypy/translator/c/node.py	Tue Aug 23 14:02:22 2005
@@ -12,20 +12,27 @@
 from pypy.rpython.rstr import STR
 
 
-def needs_refcount(T):
+def needs_gcheader(T):
     if not isinstance(T, GC_CONTAINER):
         return False
     if isinstance(T, GcStruct):
         if T._names and isinstance(T._flds[T._names[0]], GC_CONTAINER):
-            return False   # refcount already in the first field
+            return False   # gcheader already in the first field
     return True
 
-
-class StructDefNode:
-    refcount = None
+class GcInfo:
     deallocator = None
     static_deallocator = None
 
+
+class StructDefNode:
+    gcheader = None
+
+    gcinfo = None
+
+    #deallocator = None
+    #static_deallocator = None
+
     def __init__(self, db, STRUCT, varlength=1):
         self.db = db
         self.STRUCT = STRUCT
@@ -44,18 +51,19 @@
         self.dependencies = {}
         self.prefix = somelettersfrom(STRUCT._name) + '_'
 
-        # look up the reference counter field
-        if needs_refcount(STRUCT):
-            self.refcount = 'refcount'
+        # look up the gcheader field
+        if needs_gcheader(STRUCT):
+            self.gcheader = 'refcount'
         elif isinstance(STRUCT, GcStruct):
-            # refcount in the first field
+            # gcheader in the first field
             T = self.c_struct_field_type(STRUCT._names[0])
             assert isinstance(T, GC_CONTAINER)
             firstdefnode = db.gettypedefnode(T)
             firstfieldname = self.c_struct_field_name(STRUCT._names[0])
-            self.refcount = '%s.%s' % (firstfieldname, firstdefnode.refcount)
+            self.gcheader = '%s.%s' % (firstfieldname, firstdefnode.gcheader)
             # check here that there is enough run-time type information to
             # handle this case
+            # xxx -> gc hook
             getRuntimeTypeInfo(STRUCT)
             getRuntimeTypeInfo(T)
 
@@ -74,34 +82,38 @@
                 typename = db.gettype(T, who_asks=self)
             self.fields.append((self.c_struct_field_name(name), typename))
 
+        rtti = None
+        if isinstance(STRUCT, GcStruct):
+            try:
+                rtti = getRuntimeTypeInfo(STRUCT)
+            except ValueError:
+                pass
+
         # do we need deallocator(s)?
-        if self.refcount and varlength == 1:
-            self.deallocator = db.namespace.uniquename('dealloc_'+self.barename)
+        if varlength == 1:
+            if self.gcheader: # xxx -> gc
+                gcinfo = self.gcinfo = GcInfo()
 
-            # are two deallocators needed (a dynamic one for DECREF, which checks
-            # the real type of the structure and calls the static deallocator) ?
-            rtti = None
-            if isinstance(STRUCT, GcStruct):
-                try:
-                    rtti = getRuntimeTypeInfo(STRUCT)
-                except ValueError:
-                    pass
-            if rtti is not None:
-                self.static_deallocator = db.namespace.uniquename(
-                    'staticdealloc_'+self.barename)
-                fnptr = rtti._obj.query_funcptr
-                if fnptr is None:
-                    raise NotImplementedError(
-                        "attachRuntimeTypeInfo(): please provide a function")
-                self.rtti_query_funcptr = db.get(fnptr)
-                T = typeOf(fnptr).TO.ARGS[0]
-                self.rtti_query_funcptr_argtype = db.gettype(T)
-            else:
-                # is a deallocator really needed, or would it be empty?
-                if list(self.deallocator_lines('')):
-                    self.static_deallocator = self.deallocator
+                gcinfo.deallocator = db.namespace.uniquename('dealloc_'+self.barename)
+
+                # are two deallocators needed (a dynamic one for DECREF, which checks
+                # the real type of the structure and calls the static deallocator) ?
+                if rtti is not None:
+                    gcinfo.static_deallocator = db.namespace.uniquename(
+                        'staticdealloc_'+self.barename)
+                    fnptr = rtti._obj.query_funcptr
+                    if fnptr is None:
+                        raise NotImplementedError(
+                            "attachRuntimeTypeInfo(): please provide a function")
+                    gcinfo.rtti_query_funcptr = db.get(fnptr)
+                    T = typeOf(fnptr).TO.ARGS[0]
+                    gcinfo.rtti_query_funcptr_argtype = db.gettype(T)
                 else:
-                    self.deallocator = None
+                    # is a deallocator really needed, or would it be empty?
+                    if list(self.deallocator_lines('')):
+                        gcinfo.static_deallocator = gcinfo.deallocator
+                    else:
+                        gcinfo.deallocator = None
 
     def c_struct_field_name(self, name):
         return self.prefix + name
@@ -116,7 +128,7 @@
     def definition(self, phase):
         if phase == 1:
             yield 'struct %s {' % self.name
-            if needs_refcount(self.STRUCT):
+            if needs_gcheader(self.STRUCT): # xxx -> gc
                 yield '\tlong refcount;'
             for name, typename in self.fields:
                 line = '%s;' % cdecl(typename, name)
@@ -124,31 +136,35 @@
                     line = '/* %s */' % line
                 yield '\t' + line
             yield '};'
-            if self.deallocator:
-                yield 'void %s(struct %s *);' % (self.deallocator, self.name)
-
-        elif phase == 2:
-            if self.static_deallocator:
-                yield 'void %s(struct %s *p) {' % (self.static_deallocator,
+            if self.gcinfo: # xxx -> gc
+                gcinfo = self.gcinfo
+                if gcinfo.deallocator:
+                    yield 'void %s(struct %s *);' % (gcinfo.deallocator, self.name)
+
+        elif phase == 2: # xxx -> gc
+            if self.gcinfo:
+                gcinfo = self.gcinfo
+                if gcinfo.static_deallocator:
+                    yield 'void %s(struct %s *p) {' % (gcinfo.static_deallocator,
                                                    self.name)
-                for line in self.deallocator_lines('(*p)'):
-                    yield '\t' + line
-                yield '\tOP_FREE(p);'
-                yield '}'
-            if self.deallocator and self.deallocator != self.static_deallocator:
-                yield 'void %s(struct %s *p) {' % (self.deallocator, self.name)
-                yield '\tvoid (*staticdealloc) (void *);'
-                # the refcount should be 0; temporarily bump it to 1
-                yield '\tp->%s = 1;' % (self.refcount,)
-                # cast 'p' to the type expected by the rtti_query function
-                yield '\tstaticdealloc = %s((%s) p);' % (
-                    self.rtti_query_funcptr,
-                    cdecl(self.rtti_query_funcptr_argtype, ''))
-                yield '\tif (!--p->%s)' % (self.refcount,)
-                yield '\t\tstaticdealloc(p);'
-                yield '}'
+                    for line in self.deallocator_lines('(*p)'):
+                        yield '\t' + line
+                    yield '\tOP_FREE(p);'
+                    yield '}'
+                if gcinfo.deallocator and gcinfo.deallocator != gcinfo.static_deallocator:
+                    yield 'void %s(struct %s *p) {' % (gcinfo.deallocator, self.name)
+                    yield '\tvoid (*staticdealloc) (void *);'
+                    # the refcount should be 0; temporarily bump it to 1
+                    yield '\tp->%s = 1;' % (self.gcheader,)
+                    # cast 'p' to the type expected by the rtti_query function
+                    yield '\tstaticdealloc = %s((%s) p);' % (
+                        gcinfo.rtti_query_funcptr,
+                        cdecl(gcinfo.rtti_query_funcptr_argtype, ''))
+                    yield '\tif (!--p->%s)' % (self.gcheader,)
+                    yield '\t\tstaticdealloc(p);'
+                    yield '}'
 
-    def deallocator_lines(self, prefix):
+    def deallocator_lines(self, prefix): # xxx xxx rename, re-factor generic_dealloc use
         STRUCT = self.STRUCT
         for name in STRUCT._names:
             FIELD_T = self.c_struct_field_type(name)
@@ -171,8 +187,8 @@
 
 
 class ArrayDefNode:
-    refcount = None
-    deallocator = None
+    gcheader = None
+    gcinfo = None
 
     def __init__(self, db, ARRAY, varlength=1):
         self.db = db
@@ -195,8 +211,8 @@
         self.dependencies = {}
 
         # look up the reference counter field
-        if needs_refcount(ARRAY):
-            self.refcount = 'refcount'
+        if needs_gcheader(ARRAY):
+            self.gcheader = 'refcount' # xxx -> gc
 
     def setup(self):
         db = self.db
@@ -205,8 +221,10 @@
         self.itemtypename = db.gettype(ARRAY.OF, who_asks=self)
 
         # is a specific deallocator needed?
-        if self.refcount and varlength == 1 and list(self.deallocator_lines('')):
-            self.deallocator = db.namespace.uniquename('dealloc_'+self.barename)
+        if varlength == 1:
+            if self.gcheader and list(self.deallocator_lines('')):
+                gcinfo = self.gcinfo = GcInfo()
+                gcinfo.deallocator = db.namespace.uniquename('dealloc_'+self.barename)
 
     def access_expr(self, baseexpr, index):
         return '%s.items[%d]' % (baseexpr, index)
@@ -214,25 +232,30 @@
     def definition(self, phase):
         if phase == 1:
             yield 'struct %s {' % self.name
-            if needs_refcount(self.ARRAY):
-                yield '\tlong refcount;'
+            if needs_gcheader(self.ARRAY):
+                yield '\tlong refcount;' # xxx -> gc
             yield '\tlong length;'
             line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength)
             if self.ARRAY.OF == Void:    # strange
                 line = '/* %s */' % line
             yield '\t' + line
             yield '};'
-            if self.deallocator:
-                yield 'void %s(struct %s *a);' % (self.deallocator, self.name)
+            if self.gcinfo: # xxx -> gc
+                gcinfo = self.gcinfo
+                if gcinfo.deallocator:   
+                    yield 'void %s(struct %s *a);' % (gcinfo.deallocator, self.name)
 
-        elif phase == 2 and self.deallocator:
-            yield 'void %s(struct %s *a) {' % (self.deallocator, self.name)
-            for line in self.deallocator_lines('(*a)'):
-                yield '\t' + line
-            yield '\tOP_FREE(a);'
-            yield '}'
+        elif phase == 2:
+            if self.gcinfo:  # xxx -> gc
+                gcinfo = self.gcinfo
+                if gcinfo.deallocator:
+                    yield 'void %s(struct %s *a) {' % (gcinfo.deallocator, self.name)
+                    for line in self.deallocator_lines('(*a)'):
+                        yield '\t' + line
+                    yield '\tOP_FREE(a);'
+                    yield '}'
 
-    def deallocator_lines(self, prefix):
+    def deallocator_lines(self, prefix): # xxx xxx rename, re-factor generic_dealloc use
         ARRAY = self.ARRAY
         # we need a unique name for this C variable, or at least one that does
         # not collide with the expression in 'prefix'
@@ -287,7 +310,7 @@
         return []
 
 
-def generic_dealloc(db, expr, T):
+def generic_dealloc(db, expr, T): # xxx -> gc, refactor PyObjPtr case
     if isinstance(T, Ptr) and T._needsgc():
         line = db.cdecrefstmt(expr, T)
         if line:
@@ -367,7 +390,7 @@
 
     def initializationexpr(self, decoration=''):
         yield '{'
-        if needs_refcount(self.T):
+        if needs_gcheader(self.T): # xxx -> gc
             yield '\tREFCOUNT_IMMORTAL,'
         defnode = self.db.gettypedefnode(self.T)
         for name in self.T._names:
@@ -396,7 +419,7 @@
 
     def initializationexpr(self, decoration=''):
         yield '{'
-        if needs_refcount(self.T):
+        if needs_gcheader(self.T): # xxx -> gc
             yield '\tREFCOUNT_IMMORTAL,'
         if self.T.OF == Void or len(self.obj.items) == 0:
             yield '\t%d' % len(self.obj.items)
@@ -552,7 +575,7 @@
     typename = 'void (@)(void *)'
     includes = ()
 
-    def __init__(self, db, T, obj):
+    def __init__(self, db, T, obj): # xxx this supplies rtti value -> gc
         assert T == RuntimeTypeInfo
         assert isinstance(obj.about, GcStruct)
         self.db = db
@@ -561,7 +584,7 @@
         defnode = db.gettypedefnode(obj.about)
         self.implementationtypename = 'void (@)(struct %s *)' % (
             defnode.name,)
-        self.name = defnode.static_deallocator
+        self.name = defnode.gcinfo.static_deallocator
         self.ptrname = '((void (*)(void *)) %s)' % (self.name,)
 
     def enum_dependencies(self):



More information about the Pypy-commit mailing list