[pypy-svn] r44994 - in pypy/dist: lib-python/2.4.1/test pypy/annotation pypy/lib pypy/module/pypyjit/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/memory pypy/rpython/memory/gctransform pypy/rpython/memory/gctransform/test pypy/translator/c pypy/translator/c/src pypy/translator/c/test

mwh at codespeak.net mwh at codespeak.net
Fri Jul 13 09:21:04 CEST 2007


Author: mwh
Date: Fri Jul 13 09:21:00 2007
New Revision: 44994

Modified:
   pypy/dist/lib-python/2.4.1/test/test_threading.py
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/policy.py
   pypy/dist/pypy/lib/_structseq.py
   pypy/dist/pypy/module/pypyjit/test/test_pypy_c.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform/boehm.py
   pypy/dist/pypy/rpython/memory/gctransform/framework.py
   pypy/dist/pypy/rpython/memory/gctransform/refcounting.py
   pypy/dist/pypy/rpython/memory/gctransform/test/test_boehm.py
   pypy/dist/pypy/rpython/memory/gctransform/test/test_refcounting.py
   pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py
   pypy/dist/pypy/rpython/memory/gctransform/transform.py
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/gc.py
   pypy/dist/pypy/translator/c/src/mem.h
   pypy/dist/pypy/translator/c/support.py
   pypy/dist/pypy/translator/c/test/test_boehm.py
Log:
(pedronis, mwh)
Merge our emptying-the-malloc-zoo-2 branch.

We simplified and reduced the memory operations a backend needs to
implement, especially when using Boehm.

  ------------------------------------------------------------------------
  r44950 | mwh | 2007-07-12 15:08:18 +0300 (Thu, 12 Jul 2007) | 3 lines

  (pedronis, mwh)
  new branch for merge forward

  ------------------------------------------------------------------------
  r44952 | mwh | 2007-07-12 15:15:34 +0300 (Thu, 12 Jul 2007) | 3 lines

  (pedronis, mwh and his Bazaar T-shirt)
  merge changes from emptying-the-malloc-zoo

  ------------------------------------------------------------------------
  r44962 | mwh | 2007-07-12 16:14:13 +0300 (Thu, 12 Jul 2007) | 3 lines

  (mwh, pedronis)
  cruft-- (in very small units)

  ------------------------------------------------------------------------
  r44963 | mwh | 2007-07-12 16:21:12 +0300 (Thu, 12 Jul 2007) | 1 line

  (pedronis, mwh) these lines were useless and confusing
  ------------------------------------------------------------------------
  r44966 | mwh | 2007-07-12 16:40:21 +0300 (Thu, 12 Jul 2007) | 2 lines

  move BasicGcPolicy fractionally towards being complete

  ------------------------------------------------------------------------
  r44967 | mwh | 2007-07-12 16:43:43 +0300 (Thu, 12 Jul 2007) | 6 lines

  (pedronis, mwh)
  make the boehm gc transformer do most of the things that are now done in the
  backend.
  add more tests for the boehm gc transformer, and support for a couple of new
  operations to the llinterp.

  ------------------------------------------------------------------------
  r44968 | mwh | 2007-07-12 16:46:24 +0300 (Thu, 12 Jul 2007) | 3 lines

  (mwh, pedronis)
  don't inline the varsize malloc helpers

  ------------------------------------------------------------------------
  r44977 | mwh | 2007-07-12 18:33:45 +0300 (Thu, 12 Jul 2007) | 4 lines

  (mwh, pedronis)
  make the boehm gc transformer do way more and the boehm gcpolicy in genc do way
  less

  ------------------------------------------------------------------------
  r44981 | mwh | 2007-07-12 19:30:21 +0300 (Thu, 12 Jul 2007) | 2 lines

  *coughcoughcough*

  ------------------------------------------------------------------------


Modified: pypy/dist/lib-python/2.4.1/test/test_threading.py
==============================================================================
--- pypy/dist/lib-python/2.4.1/test/test_threading.py	(original)
+++ pypy/dist/lib-python/2.4.1/test/test_threading.py	Fri Jul 13 09:21:00 2007
@@ -2,54 +2,61 @@
 
 # Create a bunch of threads, let each do some work, wait until all are done
 
+print 'a'
 from test.test_support import verbose
+print 'a'
 import random
+print 'a'
 import threading
+print 'a'
 import time
+print 'a'
 
-# This takes about n/3 seconds to run (about n/3 clumps of tasks, times
-# about 1 second per clump).
-numtasks = 10
-
-# no more than 3 of the 10 can run at once
-sema = threading.BoundedSemaphore(value=3)
-mutex = threading.RLock()
-running = 0
-
-class TestThread(threading.Thread):
-    def run(self):
-        global running
-        delay = random.random() * 2
-        if verbose:
-            print 'task', self.getName(), 'will run for', delay, 'sec'
-        sema.acquire()
-        mutex.acquire()
-        running = running + 1
-        if verbose:
-            print running, 'tasks are running'
-        mutex.release()
-        time.sleep(delay)
-        if verbose:
-            print 'task', self.getName(), 'done'
-        mutex.acquire()
-        running = running - 1
-        if verbose:
-            print self.getName(), 'is finished.', running, 'tasks are running'
-        mutex.release()
-        sema.release()
-
-threads = []
-def starttasks():
-    for i in range(numtasks):
-        t = TestThread(name="<thread %d>"%i)
-        threads.append(t)
-        t.start()
-
-starttasks()
-
-if verbose:
-    print 'waiting for all tasks to complete'
-for t in threads:
-    t.join()
-if verbose:
-    print 'all tasks done'
+print 'a'
+def test_main():
+    # This takes about n/3 seconds to run (about n/3 clumps of tasks, times
+    # about 1 second per clump).
+    numtasks = 10
+
+    # no more than 3 of the 10 can run at once
+    sema = threading.BoundedSemaphore(value=3)
+    mutex = threading.RLock()
+    running = 0
+
+    class TestThread(threading.Thread):
+        def run(self):
+            global running
+            delay = random.random() * 2
+            if verbose:
+                print 'task', self.getName(), 'will run for', delay, 'sec'
+            sema.acquire()
+            mutex.acquire()
+            running = running + 1
+            if verbose:
+                print running, 'tasks are running'
+            mutex.release()
+            time.sleep(delay)
+            if verbose:
+                print 'task', self.getName(), 'done'
+            mutex.acquire()
+            running = running - 1
+            if verbose:
+                print self.getName(), 'is finished.', running, 'tasks are running'
+            mutex.release()
+            sema.release()
+
+    threads = []
+    def starttasks():
+        for i in range(numtasks):
+            t = TestThread(name="<thread %d>"%i)
+            threads.append(t)
+            t.start()
+
+    starttasks()
+
+    if verbose:
+        print 'waiting for all tasks to complete'
+    for t in threads:
+        t.join()
+    if verbose:
+        print 'all tasks done'

Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Fri Jul 13 09:21:00 2007
@@ -229,6 +229,8 @@
                     if clsdef.issubclass(clsdef2) and clsdef is not clsdef2:
                         del self.needs_hash_support[clsdef]
                         break
+
+            self.annotator.policy.compute_at_fixpoint(self.annotator)
         finally:
             self.leave()
 
@@ -531,6 +533,9 @@
             return result
 
     def see_mutable(self, x):
+        if x.__class__.__name__ == 'ExecutionContext':
+            import pdb
+            pdb.set_trace()
         if x in self.seen_mutable:
             return
         clsdef = self.getuniqueclassdef(x.__class__)        

Modified: pypy/dist/pypy/annotation/policy.py
==============================================================================
--- pypy/dist/pypy/annotation/policy.py	(original)
+++ pypy/dist/pypy/annotation/policy.py	Fri Jul 13 09:21:00 2007
@@ -13,6 +13,9 @@
 class BasicAnnotatorPolicy(object):
     allow_someobjects = True
 
+    def compute_at_fixpoint(self, annotator):
+        pass
+
     def event(pol, bookkeeper, what, *args):
         pass
 

Modified: pypy/dist/pypy/lib/_structseq.py
==============================================================================
--- pypy/dist/pypy/lib/_structseq.py	(original)
+++ pypy/dist/pypy/lib/_structseq.py	Fri Jul 13 09:21:00 2007
@@ -23,7 +23,7 @@
         if obj is None:
             return self
         if self.index is None:
-            return obj.__dict__[self.__name__]
+            return getattr(obj, 'data_' + self.__name__)
         else:
             return obj[self.index]
 
@@ -36,11 +36,13 @@
     def __new__(metacls, classname, bases, dict):
         assert not bases
         fields_by_index = {}
+        slots = []
         for name, field in dict.items():
             if isinstance(field, structseqfield):
                 assert field._index not in fields_by_index
                 fields_by_index[field._index] = field
                 field.__name__ = name
+                slots.append('data_' + name)
         dict['n_fields'] = len(fields_by_index)
 
         extra_fields = fields_by_index.items()
@@ -60,6 +62,7 @@
         dict['_extra_fields'] = tuple(extra_fields)
         dict['__new__'] = structseq_new
         dict['__reduce__'] = structseq_reduce
+        dict['__slots__'] = tuple(slots)
         return type.__new__(metacls, classname, (tuple,), dict)
 
 
@@ -91,11 +94,12 @@
             dict[name] = value
         sequence = sequence[:N]
     result = tuple.__new__(cls, sequence)
-    result.__dict__ = dict
     for field in cls._extra_fields:
         name = field.__name__
         if name not in dict:
             dict[name] = field._default(result)
+    for k, v in dict.iteritems():
+        setattr(result, k, v)
     return result
 
 def structseq_reduce(self):

Modified: pypy/dist/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/dist/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/dist/pypy/module/pypyjit/test/test_pypy_c.py	Fri Jul 13 09:21:00 2007
@@ -38,7 +38,7 @@
         child_stdout.close()
         assert result
         assert result.splitlines()[-1].strip() == 'OK :-)'
-        assert logfilepath.check()
+        #assert logfilepath.check()
 
 
     def test_f(self):

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Fri Jul 13 09:21:00 2007
@@ -758,6 +758,8 @@
         assert lltype.typeOf(size) == lltype.Signed
         return self.heap.raw_malloc(size)
 
+    op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc
+
     def op_raw_malloc_usage(self, size):
         assert lltype.typeOf(size) == lltype.Signed
         return self.heap.raw_malloc_usage(size)

Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Fri Jul 13 09:21:00 2007
@@ -22,8 +22,8 @@
             return NotImplemented
         return CompositeOffset(self, other)
 
-    def raw_malloc(self, rest, zero):
-        raise NotImplementedError("raw_malloc(%r, %r)" % (self, rest))
+    def _raw_malloc(self, rest, zero):
+        raise NotImplementedError("_raw_malloc(%r, %r)" % (self, rest))
 
     def raw_memcopy(self, srcadr, dstsrc):
         raise NotImplementedError("raw_memcopy(%r)" % (self,))
@@ -67,7 +67,7 @@
         else:
             raise TypeError('got %r, expected %r' % (A, self.TYPE))
 
-    def raw_malloc(self, rest, zero):
+    def _raw_malloc(self, rest, zero):
         assert not rest
         if (isinstance(self.TYPE, lltype.ContainerType)
             and self.TYPE._gckind == 'gc'):
@@ -118,12 +118,12 @@
         else:
             return lltype.direct_fieldptr(struct, self.fldname)
 
-    def raw_malloc(self, rest, parenttype=None, zero=False):
+    def _raw_malloc(self, rest, parenttype=None, zero=False):
         if self.fldname != self.TYPE._arrayfld:
             # for the error msg
-            return AddressOffset.raw_malloc(self, rest, zero=zero)
+            return AddressOffset._raw_malloc(self, rest, zero=zero)
         assert rest
-        return rest[0].raw_malloc(rest[1:], parenttype=parenttype or self.TYPE,
+        return rest[0]._raw_malloc(rest[1:], parenttype=parenttype or self.TYPE,
                                             zero=zero)
 
     def raw_memcopy(self, srcadr, dstadr):
@@ -171,8 +171,8 @@
             ptr = item.ref(ptr)
         return ptr
 
-    def raw_malloc(self, rest, zero):
-        return self.offsets[0].raw_malloc(self.offsets[1:] + rest, zero=zero)
+    def _raw_malloc(self, rest, zero):
+        return self.offsets[0]._raw_malloc(self.offsets[1:] + rest, zero=zero)
 
     def raw_memcopy(self, srcadr, dstadr):
         for o in self.offsets[:-1]:
@@ -198,7 +198,7 @@
         else:
             return lltype.direct_arrayitems(arrayptr)
 
-    def raw_malloc(self, rest, parenttype=None, zero=False):
+    def _raw_malloc(self, rest, parenttype=None, zero=False):
         if rest:
             assert len(rest) == 1
             assert isinstance(rest[0], ItemOffset)
@@ -245,11 +245,11 @@
         gcptr = self.gcheaderbuilder.object_from_header(headerptr)
         return gcptr
 
-    def raw_malloc(self, rest, zero):
+    def _raw_malloc(self, rest, zero):
         assert rest
         if isinstance(rest[0], GCHeaderAntiOffset):
-            return rest[1].raw_malloc(rest[2:], zero=zero)    # just for fun
-        gcobjadr = rest[0].raw_malloc(rest[1:], zero=zero)
+            return rest[1]._raw_malloc(rest[2:], zero=zero)    # just for fun
+        gcobjadr = rest[0]._raw_malloc(rest[1:], zero=zero)
         headerptr = self.gcheaderbuilder.new_header(gcobjadr.ptr)
         return cast_ptr_to_adr(headerptr)
 
@@ -271,10 +271,10 @@
         headerptr = self.gcheaderbuilder.header_of_object(gcptr)
         return headerptr
 
-    def raw_malloc(self, rest, zero):
+    def _raw_malloc(self, rest, zero):
         assert len(rest) >= 2
         assert isinstance(rest[0], GCHeaderOffset)
-        return rest[1].raw_malloc(rest[2:], zero=zero)
+        return rest[1]._raw_malloc(rest[2:], zero=zero)
 
 # ____________________________________________________________
 
@@ -543,7 +543,7 @@
 def raw_malloc(size):
     if not isinstance(size, AddressOffset):
         raise NotImplementedError(size)
-    return size.raw_malloc([], zero=False)
+    return size._raw_malloc([], zero=False)
 
 def raw_free(adr):
     # try to free the whole object if 'adr' is the address of the header
@@ -568,7 +568,7 @@
     if not isinstance(size, AddressOffset):
         raise NotImplementedError(size)
     assert lltype.typeOf(adr) == Address
-    zeroadr = size.raw_malloc([], zero=True)
+    zeroadr = size._raw_malloc([], zero=True)
     size.raw_memcopy(zeroadr, adr)
 
 def raw_memcopy(source, dest, size):
@@ -615,7 +615,7 @@
         self.unitsize = unitsize
         self.n = n
 
-    def raw_malloc(self, rest, zero=False):
+    def _raw_malloc(self, rest, zero=False):
         assert not rest
         arena = _arena(self, zero=zero)
         return arena.getitemaddr(0)

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Fri Jul 13 09:21:00 2007
@@ -339,7 +339,10 @@
 
     # __________ address operations __________
 
-    'raw_malloc':           LLOp(canraise=(MemoryError,)),
+    'boehm_malloc':         LLOp(),
+    'boehm_malloc_atomic':  LLOp(),
+    'boehm_register_finalizer': LLOp(),
+    'raw_malloc':           LLOp(),
     'raw_malloc_usage':     LLOp(sideeffects=False),
     'raw_free':             LLOp(),
     'raw_memclear':         LLOp(),

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Fri Jul 13 09:21:00 2007
@@ -4,7 +4,7 @@
 from pypy.rpython.memory.gcheader import GCHeaderBuilder
 from pypy.rpython.memory import lltypesimulation
 from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rlib.objectmodel import free_non_gc_object
+from pypy.rlib.objectmodel import free_non_gc_object, debug_assert
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib.rarithmetic import ovfcheck
 
@@ -97,7 +97,10 @@
         size = self.fixed_size(typeid)
         if self.is_varsize(typeid):
             size += length * self.varsize_item_sizes(typeid)
-        return raw_malloc(size)
+        result = raw_malloc(size)
+        if not result:
+            raise memoryError
+        return result
          
     def collect(self):
         self.get_roots() #this is there so that the annotator thinks get_roots is a function
@@ -182,6 +185,8 @@
         except OverflowError:
             raise memoryError
         result = raw_malloc(tot_size)
+        if not result:
+            raise memoryError
         hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
         hdr.typeid = typeid << 1
         if has_finalizer:
@@ -208,6 +213,8 @@
         except OverflowError:
             raise memoryError
         result = raw_malloc(tot_size)
+        if not result:
+            raise memoryError
         raw_memclear(result, tot_size)
         hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
         hdr.typeid = typeid << 1
@@ -238,6 +245,8 @@
         except OverflowError:
             raise memoryError
         result = raw_malloc(tot_size)
+        if not result:
+            raise memoryError
         (result + size_gc_header + offset_to_length).signed[0] = length
         hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
         hdr.typeid = typeid << 1
@@ -270,6 +279,8 @@
         except OverflowError:
             raise memoryError
         result = raw_malloc(tot_size)
+        if not result:
+            raise memoryError
         raw_memclear(result, tot_size)        
         (result + size_gc_header + offset_to_length).signed[0] = length
         hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
@@ -942,8 +953,10 @@
 
     def setup(self):
         self.tospace = raw_malloc(self.space_size)
+        debug_assert(bool(self.tospace), "couldn't allocate tospace")
         self.top_of_space = self.tospace + self.space_size
         self.fromspace = raw_malloc(self.space_size)
+        debug_assert(bool(self.fromspace), "couldn't allocate fromspace")
         self.free = self.tospace
 
     def free_memory(self):
@@ -1125,6 +1138,8 @@
         size_gc_header = self.size_gc_header()
         result = raw_malloc(size + size_gc_header)
 ##         print "mallocing %s, size %s at %s" % (typeid, size, result)
+        if not result:
+            raise memoryError
         result.signed[0] = 0 # refcount
         result.signed[1] = typeid
         return result + size_gc_header

Modified: pypy/dist/pypy/rpython/memory/gctransform/boehm.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/boehm.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/boehm.py	Fri Jul 13 09:21:00 2007
@@ -3,11 +3,58 @@
      get_rtti, _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython import rmodel
+from pypy.rlib.rarithmetic import ovfcheck
+from pypy.objspace.flow.model import Constant
 
 class BoehmGCTransformer(GCTransformer):
+    FINALIZER_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
+
     def __init__(self, translator, inline=False):
         super(BoehmGCTransformer, self).__init__(translator, inline=inline)
         self.finalizer_funcptrs = {}
+        memoryError = MemoryError()
+
+        def ll_malloc_fixedsize(size, finalizer):
+            result = llop.boehm_malloc(llmemory.Address, size)
+            if not result:
+                raise memoryError
+            if finalizer: # XXX runtime check here is bad?
+                llop.boehm_register_finalizer(lltype.Void, result, finalizer)
+            return result
+        def ll_malloc_fixedsize_atomic(size, finalizer):
+            result = llop.boehm_malloc_atomic(llmemory.Address, size)
+            if not result:
+                raise memoryError
+            if finalizer: # XXX runtime check here is bad?
+                llop.boehm_register_finalizer(lltype.Void, result, finalizer)
+            return result
+        # XXX, do we need/want an atomic version of this function?
+        def ll_malloc_varsize_no_length(length, size, itemsize):
+            try:
+                varsize = ovfcheck(itemsize * length)
+                tot_size = ovfcheck(size + varsize)
+            except OverflowError:
+                raise memoryError
+            result = llop.boehm_malloc(llmemory.Address, tot_size)
+            if not result:
+                raise memoryError
+            return result
+        def ll_malloc_varsize(length, size, itemsize, lengthoffset):
+            result = ll_malloc_varsize_no_length(length, size, itemsize)
+            (result + lengthoffset).signed[0] = length
+            return result
+
+        if self.translator:
+            self.malloc_fixedsize_ptr = self.inittime_helper(
+                ll_malloc_fixedsize, [lltype.Signed, self.FINALIZER_PTR], llmemory.Address)
+            self.malloc_fixedsize_atomic_ptr = self.inittime_helper(
+                ll_malloc_fixedsize_atomic, [lltype.Signed, self.FINALIZER_PTR], llmemory.Address)
+            self.malloc_varsize_no_length_ptr = self.inittime_helper(
+                ll_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address, inline=False)
+            self.malloc_varsize_ptr = self.inittime_helper(
+                ll_malloc_varsize, [lltype.Signed]*4, llmemory.Address, inline=False)
+            self.mixlevelannotator.finish()   # for now
 
     def push_alive_nopyobj(self, var, llops):
         pass
@@ -23,6 +70,62 @@
         """ for boehm it is enough to do nothing"""
         pass
 
+    def gct_malloc(self, hop):
+        TYPE = hop.spaceop.result.concretetype.TO
+        assert not TYPE._is_varsize()
+        c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE))
+        if TYPE._is_atomic():
+            funcptr = self.malloc_fixedsize_atomic_ptr
+        else:
+            funcptr = self.malloc_fixedsize_ptr
+        c_finalizer_ptr = Constant(self.finalizer_funcptr_for_type(TYPE), self.FINALIZER_PTR)
+        v_raw = hop.genop("direct_call",
+                          [funcptr, c_size, c_finalizer_ptr],
+                          resulttype=llmemory.Address)
+        hop.cast_result(v_raw)
+
+    # XXX In theory this is wrong:
+    gct_zero_malloc = gct_malloc
+
+    def gct_malloc_varsize(self, hop):
+        def intconst(c): return rmodel.inputconst(lltype.Signed, c)
+
+        op = hop.spaceop
+        TYPE = op.result.concretetype.TO
+        assert TYPE._is_varsize()
+
+        assert not self.finalizer_funcptr_for_type(TYPE)
+
+        if isinstance(TYPE, lltype.Struct):
+            ARRAY = TYPE._flds[TYPE._arrayfld]
+        else:
+            ARRAY = TYPE
+        assert isinstance(ARRAY, lltype.Array)
+        if ARRAY._hints.get('isrpystring', False):
+            c_const_size = intconst(llmemory.sizeof(TYPE, 1))
+        else:
+            c_const_size = intconst(llmemory.sizeof(TYPE, 0))
+        c_item_size = intconst(llmemory.sizeof(ARRAY.OF))
+
+        if ARRAY._hints.get("nolength", False):
+            v_raw = hop.genop("direct_call",
+                               [self.malloc_varsize_no_length_ptr, op.args[-1],
+                                c_const_size, c_item_size],
+                               resulttype=llmemory.Address)
+        else:
+            if isinstance(TYPE, lltype.Struct):
+                offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \
+                                   llmemory.ArrayLengthOffset(ARRAY)
+            else:
+                offset_to_length = llmemory.ArrayLengthOffset(ARRAY)
+            v_raw = hop.genop("direct_call",
+                               [self.malloc_varsize_ptr, op.args[-1],
+                                c_const_size, c_item_size, intconst(offset_to_length)],
+                               resulttype=llmemory.Address)
+        hop.cast_result(v_raw)
+
+    gct_zero_malloc_varsize = gct_malloc_varsize
+
     def finalizer_funcptr_for_type(self, TYPE):
         if TYPE in self.finalizer_funcptrs:
             return self.finalizer_funcptrs[TYPE]
@@ -57,7 +160,7 @@
                 llop.gc_restore_exception(lltype.Void, exc_instance)
             fptr = self.annotate_helper(ll_finalizer, [llmemory.Address], lltype.Void)
         else:
-            fptr = None
+            fptr = lltype.nullptr(self.FINALIZER_PTR.TO)
 
         self.finalizer_funcptrs[TYPE] = fptr
         return fptr

Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/framework.py	Fri Jul 13 09:21:00 2007
@@ -6,6 +6,7 @@
 from pypy.rpython.memory import gc, lladdress
 from pypy.rpython.memory.gcheader import GCHeaderBuilder
 from pypy.rlib.rarithmetic import ovfcheck
+from pypy.rlib.objectmodel import debug_assert
 from pypy.translator.backendopt import graphanalyze
 from pypy.annotation import model as annmodel
 from pypy.rpython import annlowlevel
@@ -251,6 +252,7 @@
             _alloc_flavor_ = 'raw'
             def setup_root_stack():
                 stackbase = lladdress.raw_malloc(rootstacksize)
+                debug_assert(bool(stackbase), "could not allocate root stack")
                 lladdress.raw_memclear(stackbase, rootstacksize)
                 gcdata.root_stack_top  = stackbase
                 gcdata.root_stack_base = stackbase

Modified: pypy/dist/pypy/rpython/memory/gctransform/refcounting.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/refcounting.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/refcounting.py	Fri Jul 13 09:21:00 2007
@@ -45,7 +45,9 @@
 
         # create incref, etc  graph
 
+        memoryError = MemoryError()
         HDRPTR = lltype.Ptr(self.HDR)
+
         def ll_incref(adr):
             if adr:
                 gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, HDRPTR)
@@ -71,6 +73,8 @@
         def ll_malloc_fixedsize(size):
             size = gc_header_offset + size
             result = lladdress.raw_malloc(size)
+            if not result:
+                raise memoryError
             lladdress.raw_memclear(result, size)
             result += gc_header_offset
             return result
@@ -80,8 +84,10 @@
                 varsize = ovfcheck(itemsize * length)
                 tot_size = ovfcheck(fixsize + varsize)
             except OverflowError:
-                raise MemoryError
+                raise memoryError
             result = lladdress.raw_malloc(tot_size)
+            if not result:
+                raise memoryError
             lladdress.raw_memclear(result, tot_size)
             result += gc_header_offset
             return result
@@ -149,6 +155,8 @@
                           resulttype=llmemory.Address)
         hop.cast_result(v_raw)
 
+    gct_zero_malloc = gct_malloc
+
     def gct_malloc_varsize(self, hop):
         def intconst(c): return rmodel.inputconst(lltype.Signed, c)
 
@@ -184,6 +192,8 @@
                                resulttype=llmemory.Address)
         hop.cast_result(v_raw)
 
+    gct_zero_malloc_varsize = gct_malloc_varsize
+
     def gct_gc_deallocate(self, hop):
         TYPE = hop.spaceop.args[0].value
         v_addr = hop.spaceop.args[1]

Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_boehm.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/test/test_boehm.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/test/test_boehm.py	Fri Jul 13 09:21:00 2007
@@ -3,9 +3,14 @@
 from pypy.rpython.memory.gctransform.test.test_refcounting import make_deallocator
 from pypy.rpython.lltypesystem import lltype
 from pypy.translator.translator import graphof
+from pypy.translator.c.gc import BoehmGcPolicy
+from pypy.rpython.memory.gctransform.test.test_transform import LLInterpedTranformerTests
 from pypy import conftest
 import py
 
+class TestLLInterpedBoehm(LLInterpedTranformerTests):
+    gcpolicy = BoehmGcPolicy
+
 def make_boehm_finalizer(TYPE):
     return make_deallocator(TYPE, attr="finalizer_funcptr_for_type",
                             cls=BoehmGCTransformer)

Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_refcounting.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/test/test_refcounting.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/test/test_refcounting.py	Fri Jul 13 09:21:00 2007
@@ -1,124 +1,47 @@
 from pypy.rpython.memory.gctransform.test.test_transform import rtype, rtype_and_transform, getops
+from pypy.rpython.memory.gctransform.test.test_transform import LLInterpedTranformerTests
 from pypy.rpython.memory.gctransform.refcounting import RefcountingGCTransformer
 from pypy.rpython.lltypesystem import lltype
-from pypy.translator.c.gc import RefcountingGcPolicy
 from pypy.translator.translator import TranslationContext, graphof
+from pypy.translator.c.gc import RefcountingGcPolicy
 from pypy import conftest
 
-class RefcountingGcPolicy2(RefcountingGcPolicy):
-    transformerclass = RefcountingGCTransformer
-
-def llinterpreter_for_refcounted_graph(f, args_s):
-    from pypy.rpython.llinterp import LLInterpreter
-    from pypy.translator.c.genc import CStandaloneBuilder
-    from pypy.translator.c import gc
-
-    t = rtype(f, args_s)
-    cbuild = CStandaloneBuilder(t, f, t.config, gcpolicy=RefcountingGcPolicy2)
-    db = cbuild.generate_graphs_for_llinterp()
-    graph = cbuild.getentrypointptr()._obj.graph
-    llinterp = LLInterpreter(t.rtyper)
-    if conftest.option.view:
-        t.view()
-    return llinterp, graph
-    res = llinterp.eval_graph(graph, [0])
-    assert res == f(0)
-    res = llinterp.eval_graph(graph, [1])
-    assert res == f(1)
-
-
-def test_llinterp_refcounted_graph():
-    from pypy.annotation.model import SomeInteger
-
-    class C:
-        pass
-    c = C()
-    c.x = 1
-    def g(x):
-        if x:
-            return c
-        else:
-            d = C()
-            d.x = 2
-            return d
-    def f(x):
-        return g(x).x
-
-    llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeInteger()])
-
-    res = llinterp.eval_graph(graph, [0])
-    assert res == f(0)
-    res = llinterp.eval_graph(graph, [1])
-    assert res == f(1)
-
-def test_llinterp_refcounted_graph_varsize():
-    from pypy.annotation.model import SomeInteger
+class TestLLInterpedRefcounting(LLInterpedTranformerTests):
+    gcpolicy = RefcountingGcPolicy
 
-    def f(x):
-        r = []
-        for i in range(x):
-            if i % 2:
-                r.append(x)
-        return len(r)
-
-
-    llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeInteger()])
-
-    res = llinterp.eval_graph(graph, [0])
-    assert res == f(0)
-    res = llinterp.eval_graph(graph, [10])
-    assert res == f(10)
-
-def test_llinterp_refcounted_graph_str():
-    from pypy.annotation.model import SomeString
-    from pypy.rpython.lltypesystem.rstr import string_repr
-
-    def f(x):
-        return len(x + 'a')
-
-
-    llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeString()])
-
-    cc = string_repr.convert_const
-
-    res = llinterp.eval_graph(graph, [cc('a')])
-    assert res == f('a')
-    res = llinterp.eval_graph(graph, [cc('brrrrrr')])
-    assert res == f('brrrrrr')
-
-def test_llinterp_refcounted_graph_with_del():
-    from pypy.annotation.model import SomeInteger
-
-    class D:
-        pass
-
-    delcounter = D()
-    delcounter.dels = 0
-
-    class C:
-        def __del__(self):
-            delcounter.dels += 1
-    c = C()
-    c.x = 1
-    def h(x):
-        if x:
-            return c
-        else:
-            d = C()
-            d.x = 2
-            return d
-    def g(x):
-        return h(x).x
-    def f(x):
-        r = g(x)
-        return r + delcounter.dels
+    def test_llinterp_refcounted_graph_with_del(self):
+        from pypy.annotation.model import SomeInteger
 
-    llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeInteger()])
+        class D:
+            pass
 
-    res = llinterp.eval_graph(graph, [1])
-    assert res == 1
-    res = llinterp.eval_graph(graph, [0])
-    assert res == 3
+        delcounter = D()
+        delcounter.dels = 0
+
+        class C:
+            def __del__(self):
+                delcounter.dels += 1
+        c = C()
+        c.x = 1
+        def h(x):
+            if x:
+                return c
+            else:
+                d = C()
+                d.x = 2
+                return d
+        def g(x):
+            return h(x).x
+        def f(x):
+            r = g(x)
+            return r + delcounter.dels
+
+        llinterp, graph = self.llinterpreter_for_transformed_graph(f, [SomeInteger()])
+
+        res = llinterp.eval_graph(graph, [1])
+        assert res == 1
+        res = llinterp.eval_graph(graph, [0])
+        assert res == 3
 
 def test_simple_barrier():
     S = lltype.GcStruct("S", ('x', lltype.Signed))

Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py	Fri Jul 13 09:21:00 2007
@@ -10,6 +10,83 @@
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy import conftest
 
+class LLInterpedTranformerTests:
+
+    def llinterpreter_for_transformed_graph(self, f, args_s):
+        from pypy.rpython.llinterp import LLInterpreter
+        from pypy.translator.c.genc import CStandaloneBuilder
+        from pypy.translator.c import gc
+
+        t = rtype(f, args_s)
+        # XXX we shouldn't need an actual gcpolicy here.
+        cbuild = CStandaloneBuilder(t, f, t.config, gcpolicy=self.gcpolicy)
+        db = cbuild.generate_graphs_for_llinterp()
+        graph = cbuild.getentrypointptr()._obj.graph
+        llinterp = LLInterpreter(t.rtyper)
+        if conftest.option.view:
+            t.view()
+        return llinterp, graph
+
+
+    def test_simple(self):
+        from pypy.annotation.model import SomeInteger
+
+        class C:
+            pass
+        c = C()
+        c.x = 1
+        def g(x):
+            if x:
+                return c
+            else:
+                d = C()
+                d.x = 2
+                return d
+        def f(x):
+            return g(x).x
+
+        llinterp, graph = self.llinterpreter_for_transformed_graph(f, [SomeInteger()])
+
+        res = llinterp.eval_graph(graph, [0])
+        assert res == f(0)
+        res = llinterp.eval_graph(graph, [1])
+        assert res == f(1)
+
+    def test_simple_varsize(self):
+        from pypy.annotation.model import SomeInteger
+
+        def f(x):
+            r = []
+            for i in range(x):
+                if i % 2:
+                    r.append(x)
+            return len(r)
+
+
+        llinterp, graph = self.llinterpreter_for_transformed_graph(f, [SomeInteger()])
+
+        res = llinterp.eval_graph(graph, [0])
+        assert res == f(0)
+        res = llinterp.eval_graph(graph, [10])
+        assert res == f(10)
+
+    def test_str(self):
+        from pypy.annotation.model import SomeString
+        from pypy.rpython.lltypesystem.rstr import string_repr
+
+        def f(x):
+            return len(x + 'a')
+
+
+        llinterp, graph = self.llinterpreter_for_transformed_graph(f, [SomeString()])
+
+        cc = string_repr.convert_const
+
+        res = llinterp.eval_graph(graph, [cc('a')])
+        assert res == f('a')
+        res = llinterp.eval_graph(graph, [cc('brrrrrr')])
+        assert res == f('brrrrrr')
+
 class _TestGCTransformer(GCTransformer):
 
     def push_alive_nopyobj(self, var, llops):

Modified: pypy/dist/pypy/rpython/memory/gctransform/transform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/transform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/transform.py	Fri Jul 13 09:21:00 2007
@@ -243,8 +243,8 @@
             self.graphs_to_inline[graph] = True
         return self.mixlevelannotator.graph2delayed(graph)
 
-    def inittime_helper(self, ll_helper, ll_args, ll_result):
-        ptr = self.annotate_helper(ll_helper, ll_args, ll_result, inline=True)
+    def inittime_helper(self, ll_helper, ll_args, ll_result, inline=True):
+        ptr = self.annotate_helper(ll_helper, ll_args, ll_result, inline=inline)
         return Constant(ptr, lltype.typeOf(ptr))
 
     def finish_helpers(self):

Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Fri Jul 13 09:21:00 2007
@@ -510,62 +510,17 @@
                                      self.expr(op.args[0]),
                                      self.expr(op.args[1]))
 
-    def OP_ZERO_MALLOC(self, op):
-        TYPE = self.lltypemap(op.result).TO
-        typename = self.db.gettype(TYPE)
-        eresult = self.expr(op.result)
-        esize = 'sizeof(%s)' % cdecl(typename, '')
-
-        return self.gcpolicy.zero_malloc(TYPE, esize, eresult)
-
-    def OP_MALLOC(self, op):
-        TYPE = self.lltypemap(op.result).TO
-        typename = self.db.gettype(TYPE)
-        eresult = self.expr(op.result)
-        esize = 'sizeof(%s)' % cdecl(typename, '')
-
-        return self.gcpolicy.malloc(TYPE, esize, eresult)
-
-    OP_ZERO_MALLOC = OP_MALLOC
-    
-    def OP_MALLOC_VARSIZE(self, op):
-        TYPE = self.lltypemap(op.result).TO
-        typename = self.db.gettype(TYPE)
-        lenfld = 'length'
-        nodedef = self.db.gettypedefnode(TYPE)
-        if isinstance(TYPE, Struct):
-            arfld = TYPE._arrayfld
-            lenfld = "%s.length" % nodedef.c_struct_field_name(arfld)
-            VARPART = TYPE._flds[TYPE._arrayfld]
-        else:
-            VARPART = TYPE
-        assert isinstance(VARPART, Array)
-        itemtypename = self.db.gettype(VARPART.OF)
-        elength = self.expr(op.args[1])
-        eresult = self.expr(op.result)
-        if VARPART.OF is Void:    # strange
-            esize = 'sizeof(%s)' % (cdecl(typename, ''),)
-            result = '{\n'
-        else:
-            itemtype = cdecl(itemtypename, '')
-            result = 'IF_VARSIZE_OVERFLOW(%s, %s, %s)\nelse {\n' % (
-                elength,
-                itemtype,
-                eresult)
-            esize = 'sizeof(%s)-sizeof(%s)+%s*sizeof(%s)' % (
-                cdecl(typename, ''),
-                itemtype,
-                elength,
-                itemtype)
-        result += self.gcpolicy.zero_malloc(TYPE, esize, eresult)
-
-        # ctypes Arrays have no length field
-        if not VARPART._hints.get('nolength', False):
-            result += '\nif(%s) %s->%s = %s;' % (eresult, eresult, lenfld, elength)
-        result += '\n}'
-        return result
-    
-    OP_ZERO_MALLOC_VARSIZE = OP_MALLOC_VARSIZE
+    def OP_BOEHM_MALLOC(self, op):
+        return 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, 0, 0);' % (self.expr(op.args[0]),
+                                                               self.expr(op.result))
+
+    def OP_BOEHM_MALLOC_ATOMIC(self, op):
+        return 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, 1, 0);' % (self.expr(op.args[0]),
+                                                               self.expr(op.result))
+
+    def OP_BOEHM_REGISTER_FINALIZER(self, op):
+        return 'GC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);' \
+               % (self.expr(op.args[0]), self.expr(op.args[1]))
 
     def OP_RAW_MALLOC(self, op):
         eresult = self.expr(op.result)
@@ -573,6 +528,7 @@
         return "OP_RAW_MALLOC(%s, %s, void *);" % (esize, eresult)
 
     def OP_FLAVORED_MALLOC(self, op):
+        # XXX this function should DIE!
         TYPE = self.lltypemap(op.result).TO
         typename = self.db.gettype(TYPE)
         eresult = self.expr(op.result)
@@ -590,6 +546,7 @@
             raise NotImplementedError
 
     def OP_FLAVORED_MALLOC_VARSIZE(self, op):
+        # XXX this function should DIE!, at least twice over
         # XXX I know this working in just one case, probably makes
         # sense to assert it here, rest is just copied
         flavor = op.args[0].value

Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Fri Jul 13 09:21:00 2007
@@ -48,6 +48,15 @@
     def gc_startup_code(self):
         return []
 
+    def struct_setup(self, structdefnode, rtti):
+        return None
+
+    def array_setup(self, arraydefnode):
+        return None
+
+    def rtti_type(self):
+        return ''
+
     def OP_GC_PUSH_ALIVE_PYOBJ(self, funcgen, op):
         expr = funcgen.expr(op.args[0])
         if expr == 'NULL':
@@ -108,14 +117,6 @@
 
     # zero malloc impl
 
-    def zero_malloc(self, TYPE, esize, eresult):
-        assert TYPE._gckind == 'gc'   # we don't really support this
-        typename = self.db.gettype(TYPE)
-        erestype = cdecl(typename, '*')
-        return 'OP_ZERO_MALLOC(%s, %s, %s);' % (esize, eresult, erestype)
-
-    malloc = zero_malloc
-
     def OP_GC_CALL_RTTI_DESTRUCTOR(self, funcgen, op):
         args = [funcgen.expr(v) for v in op.args]
         line = '%s(%s);' % (args[0], ', '.join(args[1:]))
@@ -171,18 +172,11 @@
 class BoehmGcPolicy(BasicGcPolicy):
     transformerclass = boehm.BoehmGCTransformer
 
-    def setup_gcinfo(self, defnode):
-        transformer = defnode.db.gctransformer
-        fptr = transformer.finalizer_funcptr_for_type(defnode.LLTYPE)
-        if fptr:
-            defnode.gcinfo = BoehmInfo()
-            defnode.gcinfo.finalizer = defnode.db.get(fptr)
-
     def array_setup(self, arraydefnode):
-        self.setup_gcinfo(arraydefnode)
+        pass
 
     def struct_setup(self, structdefnode, rtti):
-        self.setup_gcinfo(structdefnode)
+        pass
 
     def rtti_type(self):
         return BoehmGcRuntimeTypeInfo_OpaqueNode.typename
@@ -190,25 +184,6 @@
     def rtti_node_factory(self):
         return BoehmGcRuntimeTypeInfo_OpaqueNode
 
-    def zero_malloc(self, TYPE, esize, eresult):
-        gcinfo = self.db.gettypedefnode(TYPE).gcinfo
-        assert TYPE._gckind == 'gc'   # _is_atomic() depends on this!
-        is_atomic = TYPE._is_atomic()
-        is_varsize = TYPE._is_varsize()
-        typename = self.db.gettype(TYPE)
-        erestype = cdecl(typename, '*')
-        result = 'OP_BOEHM_ZERO_MALLOC(%s, %s, %s, %d, %d);' % (esize,
-                                                            eresult,
-                                                            erestype,
-                                                            is_atomic,
-                                                            is_varsize)
-        if gcinfo and gcinfo.finalizer:
-            result += ('\nGC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);'
-                       % (eresult, gcinfo.finalizer))
-        return result
-
-    malloc = zero_malloc
-
     def gc_libraries(self):
         if sys.platform == 'win32':
             return ['gc_pypy']
@@ -292,7 +267,6 @@
         yield "#include <gc/gc_typed.h>"
 
     def struct_setup(self, structdefnode, rtti):
-        self.setup_gcinfo(structdefnode)
         T = structdefnode.STRUCT
         if T._is_atomic():
             malloc_exact = False
@@ -327,37 +301,11 @@
                 self.get_descr_name(defnode), T)
             yield "}"
 
-    def zero_malloc(self, TYPE, esize, eresult):
-        defnode = self.db.gettypedefnode(TYPE)
-        gcinfo = defnode.gcinfo
-        if gcinfo:
-            if not gcinfo.malloc_exact:
-                assert TYPE._gckind == 'gc'   # _is_atomic() depends on this!
-                is_atomic = TYPE._is_atomic()
-                is_varsize = TYPE._is_varsize()
-                typename = self.db.gettype(TYPE)
-                erestype = cdecl(typename, '*')
-                result = 'OP_BOEHM_ZERO_MALLOC(%s, %s, %s, %d, %d);' % (
-                    esize, eresult, erestype, is_atomic, is_varsize)
-            else:
-                result = '%s = GC_MALLOC_EXPLICITLY_TYPED(%s, %s);' % (
-                    eresult, esize, self.get_descr_name(defnode))
-            if gcinfo.finalizer:
-                result += ('\nGC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);'
-                       % (eresult, gcinfo.finalizer))
-        else:
-            return super(MoreExactBoehmGcPolicy, self).zero_malloc(
-                TYPE, esize, eresult)
-        return result
-
-    malloc = zero_malloc
 
 # to get an idea how it looks like with no refcount/gc at all
 
 class NoneGcPolicy(BoehmGcPolicy):
 
-    zero_malloc = RefcountingGcPolicy.zero_malloc.im_func
-    malloc = RefcountingGcPolicy.malloc.im_func
     gc_libraries = RefcountingGcPolicy.gc_libraries.im_func
     gc_startup_code = RefcountingGcPolicy.gc_startup_code.im_func
 
@@ -412,11 +360,6 @@
         o = top_container(defnode.obj)
         return defnode.db.gctransformer.gc_field_values_for(o)
 
-    def zero_malloc(self, TYPE, esize, eresult):
-        assert False, "a malloc operation in a framework build??"
-
-    malloc = zero_malloc
-
 class StacklessFrameworkGcPolicy(FrameworkGcPolicy):
     transformerclass = stacklessframework.StacklessFrameworkGCTransformer
     requires_stackless = True

Modified: pypy/dist/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/mem.h	(original)
+++ pypy/dist/pypy/translator/c/src/mem.h	Fri Jul 13 09:21:00 2007
@@ -8,11 +8,7 @@
 
 #define OP_RAW_MALLOC(size, r, restype)  {				\
 		r = (restype) PyObject_Malloc(size);			\
-		if (r == NULL) {					\
-			FAIL_EXCEPTION(PyExc_MemoryError,		\
-				       "out of memory");		\
-		} 							\
-		else {							\
+		if (r != NULL) {					\
 			memset((void*)r, 0, size);			\
 			COUNT_MALLOC;					\
 		}							\
@@ -22,13 +18,9 @@
 
 #define OP_RAW_MALLOC(size, r, restype)  {				\
 		r = (restype) PyObject_Malloc(size);			\
-		if (r == NULL) {					\
-			FAIL_EXCEPTION(PyExc_MemoryError,		\
-				       "out of memory");		\
-		} 							\
-		else {							\
+		if (r != NULL) {					\
 			COUNT_MALLOC;					\
-		}							\
+		} 							\
 	}
 
 #endif
@@ -124,11 +116,8 @@
 
 #define OP_BOEHM_ZERO_MALLOC(size, r, restype, is_atomic, is_varsize)   {             \
 	r = (restype) BOEHM_MALLOC_ ## is_atomic ## _ ## is_varsize (size);    \
-	if (r == NULL) {FAIL_EXCEPTION(PyExc_MemoryError, "out of memory");}  \
-        else {                                                               \
-            if (is_atomic)  /* the non-atomic versions return cleared memory */  \
-                memset((void*) r, 0, size);                                   \
-        }                                                                     \
+	if (r && is_atomic)  /* the non-atomic versions return cleared memory */ \
+                memset((void*) r, 0, size);				\
   }
 
 /* as we said in rbuiltin.py: 

Modified: pypy/dist/pypy/translator/c/support.py
==============================================================================
--- pypy/dist/pypy/translator/c/support.py	(original)
+++ pypy/dist/pypy/translator/c/support.py	Fri Jul 13 09:21:00 2007
@@ -52,6 +52,10 @@
     else:
         return s[:2].lower()
 
+def is_pointer_to_forward_ref(T):
+    if not isinstance(T, lltype.Ptr):
+        return False
+    return isinstance(T.TO, lltype.ForwardReference)
 
 def llvalue_from_constant(c):
     try:
@@ -64,7 +68,12 @@
         if T == lltype.Void:
             return None
         else:
-            assert lltype.typeOf(c.value) == T
+            ACTUAL_TYPE = lltype.typeOf(c.value)
+            # If the type is still uncomputed, we can't make this
+            # check.  Something else will blow up instead, probably
+            # very confusingly.
+            if not is_pointer_to_forward_ref(ACTUAL_TYPE):
+                assert ACTUAL_TYPE == T
             return c.value
 
 

Modified: pypy/dist/pypy/translator/c/test/test_boehm.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_boehm.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_boehm.py	Fri Jul 13 09:21:00 2007
@@ -1,6 +1,6 @@
 import py
 from pypy.translator.translator import TranslationContext
-from pypy.rpython.lltypesystem.lltype import Void
+from pypy.rpython.lltypesystem import lltype
 from pypy.translator.tool.cbuild import check_boehm_presence
 from pypy.translator.c.genc import CExtModuleBuilder
 from pypy import conftest
@@ -62,7 +62,6 @@
 
     def test__del__(self):
         from pypy.rpython.lltypesystem.lloperation import llop
-        from pypy.rpython.lltypesystem import lltype
         class State:
             pass
         s = State()
@@ -98,7 +97,6 @@
 
     def test_weakgcaddress_is_weak(self):
         from pypy.rpython.lltypesystem.lloperation import llop
-        from pypy.rpython.lltypesystem import lltype
         from pypy.rlib.objectmodel import cast_object_to_weakgcaddress
         class State:
             pass
@@ -130,7 +128,6 @@
 
     def test_del_raises(self):
         from pypy.rpython.lltypesystem.lloperation import llop
-        from pypy.rpython.lltypesystem import lltype
         import os
         class A(object):
             def __del__(self):
@@ -160,7 +157,6 @@
         assert res > 0
 
     def test_memory_error_varsize(self):
-        from pypy.rpython.lltypesystem import lltype
         N = int(2**31-1)
         A = lltype.GcArray(lltype.Char)
         def alloc(n):
@@ -183,7 +179,7 @@
         def prob_with_pyobj(b):
             return 3, b
         def collect():
-            llop.gc__collect(Void)
+            llop.gc__collect(lltype.Void)
         f = self.getcompiled(prob_with_pyobj, [object])
         c = self.getcompiled(collect, [])
         from sys import getrefcount as g
@@ -202,6 +198,23 @@
         after = g(obj)
         assert abs(before - after) < 5
 
+    def test_zero_malloc(self):
+        T = lltype.GcStruct("C", ('x', lltype.Signed))
+        def fixed_size():
+            t = lltype.malloc(T, zero=True)
+            return t.x
+        c_fixed_size = self.getcompiled(fixed_size, [])
+        res = c_fixed_size()
+        assert res == 0
+        A = lltype.GcArray(lltype.Signed)
+        def var_size():
+            a = lltype.malloc(A, 1, zero=True)
+            return a[0]
+        c_var_size = self.getcompiled(var_size, [])
+        res = c_var_size()
+        assert res == 0
+
+
 
 class TestUsingExactBoehm(TestUsingBoehm):
     gcpolicy = "exact_boehm"



More information about the Pypy-commit mailing list