[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