[pypy-svn] r12205 - pypy/dist/pypy/translator/genc

arigo at codespeak.net arigo at codespeak.net
Thu May 12 01:22:17 CEST 2005


Author: arigo
Date: Thu May 12 01:22:17 2005
New Revision: 12205

Modified:
   pypy/dist/pypy/translator/genc/ctyper.py
   pypy/dist/pypy/translator/genc/ll_include.h
   pypy/dist/pypy/translator/genc/lltype.py
Log:
Added reference counting to GenC/LowLevelTypes.  Becomes quite
obscure.  Probably soon time to refactor CTyper around the idea that only
LowLevelTypes are needed.



Modified: pypy/dist/pypy/translator/genc/ctyper.py
==============================================================================
--- pypy/dist/pypy/translator/genc/ctyper.py	(original)
+++ pypy/dist/pypy/translator/genc/ctyper.py	Thu May 12 01:22:17 2005
@@ -132,14 +132,32 @@
             # XXX move me elsewhere
             func = op.args[0].value
             if func is lltypes.malloc:
-                assert len(op.args) == 2   # for now
                 s_result = self.annotator.binding(op.result)
-                ct = self.annotator.translator.getconcretetype(CLiteralTypeName)
-                return [
-                    self.typed_op(SpaceOperation('malloc', [op.args[1]],
-                                                 op.result),
-                                  [ct], self.annotation2concretetype(s_result))
-                    ]
+                ctliteral = self.annotator.translator.getconcretetype(
+                    CLiteralTypeName)
+                ct = op.args[1]
+                if len(op.args) == 2:
+                    return [
+                        self.typed_op(SpaceOperation('malloc', [ct], op.result),
+                            [ctliteral], self.annotation2concretetype(s_result))
+                        ]
+                else:
+                    if isinstance(ct, lltypes.Struct):
+                        assert ct._arrayfld is not None
+                        sizefield = ct._arrayfld + '.size'
+                        varstruct = ct._flds[ct._arrayfld].OF
+                    else:
+                        assert isinstance(ct, lltypes.Array)
+                        sizefield = 'size'
+                        varstruct = ct.OF
+                        
+                    return [
+                        self.typed_op(SpaceOperation('malloc_varsize',
+                            [ct, varstruct, Constant(sizefield), op.args[2]],
+                                                     op.result),
+                            [ctliteral, ctliteral, ctliteral, self.TInt],
+                                      self.annotation2concretetype(s_result))
+                        ]
         if op.opname in ('newtuple', 'newlist'):
             # operations that are controlled by their return type
             s_binding = self.annotator.binding(op.result, True)

Modified: pypy/dist/pypy/translator/genc/ll_include.h
==============================================================================
--- pypy/dist/pypy/translator/genc/ll_include.h	(original)
+++ pypy/dist/pypy/translator/genc/ll_include.h	Thu May 12 01:22:17 2005
@@ -3,12 +3,41 @@
  /***  C header subsection: operations on LowLevelTypes    ***/
 
 
-/* XXX no reference counting */
+#define GCSTRUCT_TO_STRUCT(typename, p)   (&(p)->data)
+
+#define STRUCT_TO_GCSTRUCT(typename, p)   \
+    ((typename##_gc*) (((char*)(p)) - offsetof(typename##_gc, data)))
+
+#define REFCNT(typename, p)     STRUCT_TO_GCSTRUCT(typename, p)->refcount
+
+/* ____________________________________________________________ */
+
+
+#define OP_MALLOC(typename, r, err)  {                                  \
+    typename##_gc *__block = (typename##_gc*) PyObject_Malloc(          \
+                                                sizeof(typename##_gc)); \
+    printf("allocated %d bytes at %p\n", sizeof(typename##_gc), __block); \
+    if (__block == NULL) { PyErr_NoMemory(); FAIL(err) }                \
+    __block->refcount = 1;                                              \
+    r = GCSTRUCT_TO_STRUCT(typename, __block);                          \
+    memset((void*) r, 0, sizeof(typename));                             \
+  }
+
+#define OP_MALLOC_VARSIZE(typename, vartypename, sizefield, nsize, r, err)  {  \
+    size_t memsize = sizeof(typename##_gc) + (nsize-1)*sizeof(vartypename);    \
+    typename##_gc *__block = (typename##_gc*) PyObject_Malloc(memsize);        \
+    printf("var-allocated %d bytes at %p\n", memsize, __block); \
+    if (__block == NULL) { PyErr_NoMemory(); FAIL(err) }                       \
+    memset((void*) __block, 0, memsize);                                       \
+    __block->refcount = 1;                                                     \
+    r = GCSTRUCT_TO_STRUCT(typename, __block);                                 \
+    r->sizefield = nsize;                                                      \
+  }
+#define STRUCTFREE(typename, p) {                               \
+    printf("freeing %p\n", STRUCT_TO_GCSTRUCT(typename, p));    \
+    PyObject_Free(STRUCT_TO_GCSTRUCT(typename, p));             \
+  }
 
-#define OP_MALLOC(typename, r, err)                     \
-    r = PyObject_Malloc(sizeof(typename));              \
-    if (r == NULL) { PyErr_NoMemory(); FAIL(err) }      \
-    memset((void*) r, 0, sizeof(typename));
 
 #define OP_GETFIELD(x, fieldname, r, err)         r = x->fieldname;
 #define OP_SETFIELD(x, fieldname, val, r, err)    x->fieldname = val;

Modified: pypy/dist/pypy/translator/genc/lltype.py
==============================================================================
--- pypy/dist/pypy/translator/genc/lltype.py	(original)
+++ pypy/dist/pypy/translator/genc/lltype.py	Thu May 12 01:22:17 2005
@@ -22,16 +22,20 @@
     def __init__(self, translator, lltype):
         super(CLLType, self).__init__(translator)
         self.lltype = lltype
-##        self.globaldecl = []
+        self.globaldecl = []
 
     def debugname(self):
         # a nice textual name for debugging...
         return str(self.lltype)
 
-##    def collect_globals(self, genc):
-##        result = self.globaldecl
-##        self.globaldecl = []
-##        return result
+    def collect_globals(self, genc):
+        result = self.globaldecl
+        self.globaldecl = []
+        return result
+
+
+def needs_refcount(ct):
+    return isinstance(ct, CPtrType) and 'gc' in ct.lltype.flags
 
 
 class CPtrType(CLLType):
@@ -48,8 +52,14 @@
     def init_globals(self, genc):
         ct = ll2concretetype(genc.translator, self.lltype.TO)
         yield 'typedef %s* %s;' % (ct.typename, self.typename)
-        yield '#define OP_DECREF_%s(x)  /* XXX nothing for now */' % (
-            self.typename)
+        if 'gc' in self.lltype.flags:
+            yield '#define OP_INCREF_%s(p) if (p) REFCNT(%s, p)++;' % (
+                self.typename, ct.typename)
+            yield '#define OP_DECREF_%s(p) if (p && !--REFCNT(%s, p)) %s(p);' %(
+                self.typename, ct.typename, ct.destructorname)
+        else:
+            yield '#define OP_INCREF_%s(p)  /* no ref */' % self.typename
+            yield '#define OP_DECREF_%s(p)  /* no ref */' % self.typename
 
     def spec_getattr(self, typer, op):
         v_ptr, v_attrname = op.args
@@ -65,8 +75,13 @@
         else:
             yield typer.typed_op(op, [self, cliteral], ctresult,
                                  newopname='getfield')
+        if needs_refcount(ctresult):
+            v = Variable()
+            yield typer.typed_op(SpaceOperation('incref', [op.result], v),
+                                 [ctresult], typer.TNone)
 
     def spec_setattr(self, typer, op):
+        # XXX refcounting
         v_ptr, v_attrname, v_value = op.args
         assert isinstance(v_attrname, Constant)
         attrname = v_attrname.value
@@ -86,20 +101,47 @@
         super(CStructType, self).__init__(translator, lltype)
         basename = lltype._name.translate(C_IDENTIFIER)
         self.typename = 'struct ll_%s%d' % (basename, CStructType.Counter)
+        self.destructorname = 'lldel_%s%d' % (basename, CStructType.Counter)
         CStructType.Counter += 1
 
     def init_globals(self, genc):
         # make sure that the field types are defined before we use them
         lines = ['%s {' % self.typename]
+        destructorlines = []
         for fieldname in self.lltype._names:
             T = self.lltype._flds[fieldname]
             ct = ll2concretetype(genc.translator, T)
             for line in genc.need_typedecl_now(ct):
                 yield line
             lines.append('\t%s %s;' % (ct.typename, fieldname))
+            if isinstance(ct, (CStructType, CArrayType)):
+                destructorlines.append('\tsubstruct_%s(&p->%s);' % (
+                                       ct.destructorname, fieldname))
+            elif needs_refcount(ct):
+                destructorlines.append('\tOP_DECREF_%s((p->%s))' % (
+                    ct.typename, fieldname))
         lines.append('};')
         for line in lines:
             yield line
+        # declare the wrapper structure used by gc pointers
+        yield '%s_gc { int refcount; %s data; };' % (
+            self.typename, self.typename)
+        # declare the destructor function
+        yield 'static void substruct_%s(%s *p);' % (
+            self.destructorname, self.typename)
+        yield 'static void %s(%s *p);' % (self.destructorname, self.typename)
+        def gen():
+            yield 'static void substruct_%s(%s *p) {' % (
+                self.destructorname, self.typename)
+            for line in destructorlines:
+                yield line
+            yield '}'
+            yield 'static void %s(%s *p) {' % (
+                self.destructorname, self.typename)
+            yield '\tsubstruct_%s(p);' % self.destructorname
+            yield '\tSTRUCTFREE(%s, p)' % self.typename
+            yield '}'
+        self.globaldecl += list(gen())
 
 
 class CArrayType(CLLType):
@@ -107,7 +149,8 @@
 
     def __init__(self, translator, lltype):
         super(CArrayType, self).__init__(translator, lltype)
-        self.typename = 'struct array%d ' % CArrayType.Counter
+        self.typename = 'struct array%d' % CArrayType.Counter
+        self.destructorname = 'lldelarray%d' % CArrayType.Counter
         CArrayType.Counter += 1
 
     def init_globals(self, genc):
@@ -120,6 +163,26 @@
         yield '\tlong size;'
         yield '\t%s items[1];  /* variable-sized */' % ct.typename
         yield '};'
+        # declare the wrapper structure used by gc pointers
+        yield '%s_gc { int refcount; %s data; };' % (
+            self.typename, self.typename)
+        # declare the destructor function
+        yield 'static void substruct_%s(%s *p);' % (
+            self.destructorname, self.typename)
+        yield 'static void %s(%s *p);' % (self.destructorname, self.typename)
+        def gen():
+            yield 'static void substruct_%s(%s *p) {' % (
+                self.destructorname, self.typename)
+            yield '\tint i = p->size;'
+            yield '\twhile (i--) {'
+            yield '\t\tsubstruct_%s(p->items+i);' % ct.destructorname
+            yield '\t}'
+            yield 'static void %s(%s *p) {' % (
+                self.destructorname, self.typename)
+            yield '\tsubstruct_%s(p);' % self.destructorname
+            yield '\tSTRUCTFREE(%s, p)' % self.typename
+            yield '}'
+        self.globaldecl += list(gen())
 
 
 # ____________________________________________________________



More information about the Pypy-commit mailing list