[pypy-svn] r45487 - in pypy/dist/pypy: jit/codegen/llgraph jit/hintannotator jit/timeshifter rlib rpython rpython/lltypesystem rpython/memory rpython/memory/gctransform rpython/memory/gctransform/test rpython/rctypes rpython/test translator/backendopt translator/backendopt/test translator/c translator/c/src translator/stackless

pedronis at codespeak.net pedronis at codespeak.net
Sun Aug 5 00:42:14 CEST 2007


Author: pedronis
Date: Sun Aug  5 00:42:12 2007
New Revision: 45487

Modified:
   pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
   pypy/dist/pypy/jit/hintannotator/annotator.py
   pypy/dist/pypy/jit/timeshifter/hrtyper.py
   pypy/dist/pypy/rlib/rgc.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/lltypesystem/rtuple.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/stacklessframework.py
   pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py
   pypy/dist/pypy/rpython/memory/gctransform/transform.py
   pypy/dist/pypy/rpython/memory/lltypesimulation.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/rctypes/astringbuf.py
   pypy/dist/pypy/rpython/rctypes/rmodel.py
   pypy/dist/pypy/rpython/test/test_llinterp.py
   pypy/dist/pypy/translator/backendopt/escape.py
   pypy/dist/pypy/translator/backendopt/malloc.py
   pypy/dist/pypy/translator/backendopt/mallocprediction.py
   pypy/dist/pypy/translator/backendopt/test/test_escape.py
   pypy/dist/pypy/translator/c/exceptiontransform.py
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/src/mem.h
   pypy/dist/pypy/translator/stackless/transform.py
Log:
kill flavor_malloc_*, zero_malloc_*

now only malloc_* operations should be present in graphs until gc transform

malloc and malloc_varsize now always carry a dictionary of flags as second operand, the 'flavor' key must always be set
in this dict

the flavored_free operation is now just free(p, flavor), flavor is just the flavor string

the base gc transform class has now more responsabilities, subclasses need to care only about 'gc' flavor operations,
using the gct_fv_gc_malloc* hooks

backends need to support only raw/boehm memory operations (and the oddballs op stack_malloc, and cpy_* )

I have run quite a lot of tests and some translation, may stil have missed something, we'll see



Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py	Sun Aug  5 00:42:12 2007
@@ -43,6 +43,7 @@
 gv_Signed = gv_TYPE(lltype.Signed)
 gv_Bool = gv_TYPE(lltype.Bool)
 gv_dummy_placeholder = LLConst(llimpl.dummy_placeholder)
+gv_flavor_gc = LLConst(llimpl.placeholder({'flavor': 'gc'}))
 
 gv_Address = gv_TYPE(llmemory.Address)
 
@@ -209,14 +210,14 @@
     def genop_malloc_fixedsize(self, (gv_TYPE, gv_PTRTYPE)):
         debug_assert(self.rgenop.currently_writing is self,
                      "genop_malloc_fixedsize: bad currently_writing")
-        vars_gv = [gv_TYPE.v]
+        vars_gv = [gv_TYPE.v, gv_flavor_gc.v]
         return LLVar(llimpl.genop(self.b, 'malloc', vars_gv,
                                   gv_PTRTYPE.v))
 
     def genop_malloc_varsize(self, (gv_TYPE, gv_PTRTYPE), gv_length):
         debug_assert(self.rgenop.currently_writing is self,
                      "genop_malloc_varsize: bad currently_writing")
-        vars_gv = [gv_TYPE.v, gv_length.v]
+        vars_gv = [gv_TYPE.v, gv_flavor_gc.v, gv_length.v]
         return LLVar(llimpl.genop(self.b, 'malloc_varsize', vars_gv,
                                   gv_PTRTYPE.v))
 

Modified: pypy/dist/pypy/jit/hintannotator/annotator.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/annotator.py	(original)
+++ pypy/dist/pypy/jit/hintannotator/annotator.py	Sun Aug  5 00:42:12 2007
@@ -28,26 +28,26 @@
     def getuserclassdefinitions(self):
         return []
 
-    def consider_op_malloc(self, hs_TYPE):
+    def consider_op_malloc(self, hs_TYPE, hs_flags):
         TYPE = hs_TYPE.const
+        flags = hs_flags.const
+        assert flags['flavor'] == 'gc'
         if self.policy.novirtualcontainer:
             return hintmodel.SomeLLAbstractVariable(lltype.Ptr(TYPE))
         else:
             vstructdef = self.bookkeeper.getvirtualcontainerdef(TYPE)
             return hintmodel.SomeLLAbstractContainer(vstructdef)
 
-    consider_op_zero_malloc = consider_op_malloc
-
-    def consider_op_malloc_varsize(self, hs_TYPE, hs_length):
+    def consider_op_malloc_varsize(self, hs_TYPE, hs_flags, hs_length):
         TYPE = hs_TYPE.const
+        flags = hs_flags.const
+        assert flags['flavor'] == 'gc'        
         if self.policy.novirtualcontainer:
             return hintmodel.SomeLLAbstractVariable(lltype.Ptr(TYPE))
         else:
             vcontainerdef = self.bookkeeper.getvirtualcontainerdef(TYPE)
             return hintmodel.SomeLLAbstractContainer(vcontainerdef)
 
-    consider_op_zero_malloc_varsize = consider_op_malloc_varsize
-
     def consider_op_zero_gc_pointers_inside(self, hs_v):
         pass
 

Modified: pypy/dist/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/hrtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/hrtyper.py	Sun Aug  5 00:42:12 2007
@@ -889,7 +889,7 @@
         assert isinstance(hop.r_result, RedRepr)
         PTRTYPE = originalconcretetype(hop.s_result)
         TYPE = PTRTYPE.TO
-        v_size = hop.inputarg(self.getredrepr(lltype.Signed), arg=1)
+        v_size = hop.inputarg(self.getredrepr(lltype.Signed), arg=2)
         if isinstance(TYPE, lltype.Struct):
             return hop.r_result.create_varsize(hop, v_size)
         

Modified: pypy/dist/pypy/rlib/rgc.py
==============================================================================
--- pypy/dist/pypy/rlib/rgc.py	(original)
+++ pypy/dist/pypy/rlib/rgc.py	Sun Aug  5 00:42:12 2007
@@ -105,13 +105,14 @@
         r_tuple = hop.r_result
 
         c_CLONE       = hop.inputconst(lltype.Void, X_CLONE)
+        c_flags       = hop.inputconst(lltype.Void, {'flavor': 'gc'})
         c_gcobjectptr = hop.inputconst(lltype.Void, "gcobjectptr")
         c_pool        = hop.inputconst(lltype.Void, "pool")
 
         v_gcobject, v_pool = hop.inputargs(hop.args_r[0], r_pool_ptr)
         v_gcobjectptr = hop.genop('cast_opaque_ptr', [v_gcobject],
                                   resulttype = llmemory.GCREF)
-        v_clonedata = hop.genop('malloc', [c_CLONE],
+        v_clonedata = hop.genop('malloc', [c_CLONE, c_flags],
                                 resulttype = X_CLONE_PTR)
         hop.genop('setfield', [v_clonedata, c_gcobjectptr, v_gcobjectptr])
         hop.genop('setfield', [v_clonedata, c_pool, v_pool])

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Sun Aug  5 00:42:12 2007
@@ -613,53 +613,48 @@
         return lltype._cast_whatever(TGT, result)
     op_adr_call.need_result_type = True
 
-    def op_malloc(self, obj):
-        if self.llinterpreter.gc is not None:
+    def op_malloc(self, obj, flags):
+        flavor = flags['flavor']
+        zero = flags.get('zero', False)
+        if self.llinterpreter.gc is not None and flavor == 'gc':
+            assert not zero
             args = self.llinterpreter.gc.get_arg_malloc(obj)
             malloc = self.llinterpreter.gc.get_funcptr_malloc()
             result = self.op_direct_call(malloc, *args)
             return self.llinterpreter.gc.adjust_result_malloc(result, obj)
-        else:
-            return self.heap.malloc(obj)
-
-    def op_zero_malloc(self, obj):
-        assert self.llinterpreter.gc is None
-        return self.heap.malloc(obj, zero=True)
-
-    def op_malloc_varsize(self, obj, size):
-        if self.llinterpreter.gc is not None:
-            args = self.llinterpreter.gc.get_arg_malloc(obj, size)
-            malloc = self.llinterpreter.gc.get_funcptr_malloc()
-            result = self.op_direct_call(malloc, *args)
-            return self.llinterpreter.gc.adjust_result_malloc(result, obj, size)
-        else:
-            try:
-                return self.heap.malloc(obj, size)
-            except MemoryError:
-                self.make_llexception()
-
-    def op_zero_malloc_varsize(self, obj, size):
-        assert self.llinterpreter.gc is None
-        return self.heap.malloc(obj, size, zero=True)
-
-    def op_flavored_malloc_varsize(self, flavor, obj, size):
-        # XXX should we keep info about all mallocs for later checks of
-        # frees?
-        assert flavor == 'raw'
-        return self.heap.malloc(obj, size, flavor=flavor)
-
-    def op_flavored_malloc(self, flavor, obj):
-        assert isinstance(flavor, str)
-        if flavor == "stack":
+        elif flavor == "stack":
             if isinstance(obj, lltype.Struct) and obj._arrayfld is None:
                 result = self.heap.malloc(obj)
                 self.alloca_objects.append(result)
                 return result
             else:
                 raise ValueError("cannot allocate variable-sized things on the stack")
-        return self.heap.malloc(obj, flavor=flavor)
+            
+        return self.heap.malloc(obj, zero=zero, flavor=flavor)
+
+    # only after gc transform
+    def op_cpy_malloc(self, obj, cpytype): # xxx
+        return self.heap.malloc(obj, flavor='cpy', extra_args=(cpytype,))
+
+    def op_cpy_free(self, obj):
+        return self.heap.free(obj, flavor='cpy') # xxx ?
+
+    def op_malloc_varsize(self, obj, flags, size):
+        flavor = flags['flavor']
+        zero = flags.get('zero', False)
+        if self.llinterpreter.gc is not None and flavor == 'gc':
+            assert not zero
+            args = self.llinterpreter.gc.get_arg_malloc(obj, size)
+            malloc = self.llinterpreter.gc.get_funcptr_malloc()
+            result = self.op_direct_call(malloc, *args)
+            return self.llinterpreter.gc.adjust_result_malloc(result, obj, size)
+        assert flavor in ('gc', 'raw')
+        try:
+            return self.heap.malloc(obj, size, zero=zero, flavor=flavor)
+        except MemoryError:
+            self.make_llexception()
 
-    def op_flavored_free(self, flavor, obj):
+    def op_free(self, obj, flavor):
         assert isinstance(flavor, str)
         self.heap.free(obj, flavor=flavor)
 
@@ -791,6 +786,9 @@
         assert lltype.typeOf(value) == typ
         getattr(addr, str(typ).lower())[offset] = value
 
+    def op_stack_malloc(self, size): # mmh
+        raise NotImplementedError("backend only")
+
     # ______ for the JIT ____________
     def op_call_boehm_gc_alloc(self):
         raise NotImplementedError("call_boehm_gc_alloc")

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Sun Aug  5 00:42:12 2007
@@ -309,13 +309,9 @@
     # __________ pointer operations __________
 
     'malloc':               LLOp(canraise=(MemoryError,), canunwindgc=True),
-    'zero_malloc':          LLOp(canraise=(MemoryError,), canunwindgc=True),
     'malloc_varsize':       LLOp(canraise=(MemoryError,), canunwindgc=True),
-    'zero_malloc_varsize':  LLOp(canraise=(MemoryError,), canunwindgc=True),
     'zero_gc_pointers_inside': LLOp(),
-    'flavored_malloc':      LLOp(canraise=(MemoryError,)),
-    'flavored_malloc_varsize' : LLOp(canraise=(MemoryError,)),
-    'flavored_free':        LLOp(),
+    'free':                 LLOp(),
     'getfield':             LLOp(sideeffects=False, canrun=True),
     'getarrayitem':         LLOp(sideeffects=False, canrun=True),
     'getarraysize':         LLOp(canfold=True),
@@ -349,6 +345,9 @@
     'raw_memcopy':          LLOp(),
     'raw_load':             LLOp(sideeffects=False),
     'raw_store':            LLOp(),
+    'stack_malloc':         LLOp(), # mmh
+    'cpy_malloc':           LLOp(), # xxx
+    'cpy_free':             LLOp(), # xxx
     'adr_add':              LLOp(canfold=True),
     'adr_sub':              LLOp(canfold=True),
     'adr_delta':            LLOp(canfold=True),

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Sun Aug  5 00:42:12 2007
@@ -504,21 +504,19 @@
 
     def new_instance(self, llops, classcallhop=None, v_cpytype=None):
         """Build a new instance, without calling __init__."""
-        mallocop = 'malloc'
+        flavor = self.gcflavor
+        flags = {'flavor': flavor }
         ctype = inputconst(Void, self.object_type)
-        vlist = [ctype]
+        cflags = inputconst(Void, flags)
+        vlist = [ctype, cflags]
         if self.classdef is not None:
-            flavor = self.gcflavor
-            if flavor != 'gc': # not default flavor
-                mallocop = 'flavored_malloc'
-                vlist.insert(0, inputconst(Void, flavor))
-                if flavor == 'cpy':
-                    if v_cpytype is None:
-                        from pypy.rpython import rcpy
-                        cpytype = rcpy.build_pytypeobject(self)
-                        v_cpytype = inputconst(Ptr(PyObject), cpytype)
-                    vlist.append(v_cpytype)
-        vptr = llops.genop(mallocop, vlist,
+            if flavor == 'cpy':
+                if v_cpytype is None:
+                    from pypy.rpython import rcpy
+                    cpytype = rcpy.build_pytypeobject(self)
+                    v_cpytype = inputconst(Ptr(PyObject), cpytype)
+                vlist.append(v_cpytype)
+        vptr = llops.genop('malloc', vlist,
                            resulttype = Ptr(self.object_type))
         ctypeptr = inputconst(CLASSTYPE, self.rclass.getvtable())
         self.setfield(vptr, '__class__', ctypeptr, llops)

Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Sun Aug  5 00:42:12 2007
@@ -84,7 +84,8 @@
     def convert_from_to((r_from, r_to), v, llops):
         v_len = llops.gencapicall('PyString_Size', [v], resulttype=Signed)
         cstr = inputconst(Void, STR)
-        v_result = llops.genop('malloc_varsize', [cstr, v_len],
+        cflags = inputconst(Void, {'flavor': 'gc'})
+        v_result = llops.genop('malloc_varsize', [cstr, cflags, v_len],
                                resulttype=Ptr(STR))
         cchars = inputconst(Void, "chars")
         v_chars = llops.genop('getsubstruct', [v_result, cchars],
@@ -707,7 +708,8 @@
         things = cls.parse_fmt_string(s)
         size = inputconst(Signed, len(things)) # could be unsigned?
         cTEMP = inputconst(Void, TEMP)
-        vtemp = hop.genop("malloc_varsize", [cTEMP, size],
+        cflags = inputconst(Void, {'flavor': 'gc'})
+        vtemp = hop.genop("malloc_varsize", [cTEMP, cflags, size],
                           resulttype=Ptr(TEMP))
         # XXX hash
         r_tuple = hop.args_r[1]

Modified: pypy/dist/pypy/rpython/lltypesystem/rtuple.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rtuple.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rtuple.py	Sun Aug  5 00:42:12 2007
@@ -30,7 +30,9 @@
         if len(r_tuple.items_r) == 0:
             return inputconst(Void, ())    # a Void empty tuple
         c1 = inputconst(Void, r_tuple.lowleveltype.TO)
-        v_result = llops.genop('malloc', [c1], resulttype = r_tuple.lowleveltype)
+        cflags = inputconst(Void, {'flavor': 'gc'})
+        v_result = llops.genop('malloc', [c1, cflags],
+                                         resulttype = r_tuple.lowleveltype)
         for i in range(len(r_tuple.items_r)):
             cname = inputconst(Void, r_tuple.fieldnames[i])
             llops.genop('setfield', [v_result, cname, items_v[i]])

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	Sun Aug  5 00:42:12 2007
@@ -1,11 +1,11 @@
-from pypy.rpython.memory.gctransform.transform import GCTransformer
+from pypy.rpython.memory.gctransform.transform import GCTransformer, mallocHelpers
 from pypy.rpython.memory.gctransform.support import type_contains_pyobjs, \
      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
+from pypy.rpython.lltypesystem.lloperation import llop
 
 class BoehmGCTransformer(GCTransformer):
     FINALIZER_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
@@ -13,37 +13,25 @@
     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
+        atomic_mh = mallocHelpers()
+        atomic_mh.allocate = lambda size: llop.boehm_malloc_atomic(llmemory.Address, size)
+        def ll_malloc_fixedsize_atomic(size, finalizer):
+            result = atomic_mh._ll_malloc_fixedsize(size)
             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
+
+        mh = mallocHelpers()
+        mh.allocate = lambda size: llop.boehm_malloc(llmemory.Address, size)
+        def ll_malloc_fixedsize(size, finalizer):
+            result = mh._ll_malloc_fixedsize(size)
             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
+        ll_malloc_varsize_no_length = mh.ll_malloc_varsize_no_length
+        ll_malloc_varsize = mh.ll_malloc_varsize
 
         if self.translator:
             self.malloc_fixedsize_ptr = self.inittime_helper(
@@ -71,10 +59,8 @@
         """ 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))
+    def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size):
+        # XXX same behavior for zero=True: in theory that's wrong
         if TYPE._is_atomic():
             funcptr = self.malloc_fixedsize_atomic_ptr
         else:
@@ -83,49 +69,23 @@
         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()
+        return v_raw
 
-        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):
+    def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size,
+                                                                   c_offset_to_length):
+        # XXX same behavior for zero=True: in theory that's wrong        
+        if c_offset_to_length is None:
             v_raw = hop.genop("direct_call",
-                               [self.malloc_varsize_no_length_ptr, op.args[-1],
+                               [self.malloc_varsize_no_length_ptr, v_length,
                                 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)],
+                               [self.malloc_varsize_ptr, v_length,
+                                c_const_size, c_item_size, c_offset_to_length],
                                resulttype=llmemory.Address)
-        hop.cast_result(v_raw)
-
-    gct_zero_malloc_varsize = gct_malloc_varsize
+        return v_raw
 
     def finalizer_funcptr_for_type(self, TYPE):
         if TYPE in self.finalizer_funcptrs:

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	Sun Aug  5 00:42:12 2007
@@ -16,8 +16,11 @@
 
 class CollectAnalyzer(graphanalyze.GraphAnalyzer):
     def operation_is_true(self, op):
-        return op.opname in ("malloc", "malloc_varsize", "gc__collect",
-                             "gc_x_become", "zero_malloc_varsize", "zero_malloc")
+        if op.opname in ('gc__collect', 'gc_x_become'):
+            return True
+        if op.opname in ('malloc', 'malloc_varsize'):
+            flags = op.args[1].value
+            return flags['flavor'] == 'gc' and not flags.get('nocollect', False)
 
 ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
 
@@ -479,22 +482,11 @@
 
     gct_indirect_call = gct_direct_call
 
-    def gct_malloc(self, hop):
+    def gct_fv_gc_malloc(self, hop, flags, TYPE, *args):
         op = hop.spaceop
+        flavor = flags['flavor']
+        c_can_collect = rmodel.inputconst(lltype.Bool, not flags.get('nocollect', False))
 
-        if op.opname.startswith('flavored_'):
-            flavor = op.args[0].value
-            TYPE = op.args[1].value
-        else:
-            flavor = 'gc'
-            TYPE = op.args[0].value
-
-        if not flavor.startswith('gc'):
-            self.default(hop)
-            return
-
-        c_can_collect = rmodel.inputconst(lltype.Bool,
-                                          flavor != 'gc_nocollect')
         PTRTYPE = op.result.concretetype
         assert PTRTYPE.TO == TYPE
         type_id = self.get_type_id(TYPE)
@@ -504,7 +496,8 @@
         c_size = rmodel.inputconst(lltype.Signed, info["fixedsize"])
         if not op.opname.endswith('_varsize'):
             #malloc_ptr = self.malloc_fixedsize_ptr
-            if op.opname.startswith('zero'):
+            zero = flags.get('zero', False)
+            if zero:
                 malloc_ptr = self.malloc_fixedsize_clear_ptr
             else:
                 malloc_ptr = self.malloc_fixedsize_ptr
@@ -528,13 +521,9 @@
         v_result = hop.genop("direct_call", [malloc_ptr] + args,
                              resulttype=llmemory.GCREF)
         self.pop_roots(hop)
-        hop.cast_result(v_result)
+        return v_result
 
-    gct_zero_malloc = gct_malloc
-    gct_malloc_varsize = gct_malloc
-    gct_zero_malloc_varsize = gct_malloc
-    gct_flavored_malloc = gct_malloc
-    gct_flavored_malloc_varsize = gct_malloc
+    gct_fv_gc_malloc_varsize = gct_fv_gc_malloc
 
     def gct_gc__collect(self, hop):
         op = hop.spaceop

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	Sun Aug  5 00:42:12 2007
@@ -1,5 +1,5 @@
 import py
-from pypy.rpython.memory.gctransform.transform import GCTransformer
+from pypy.rpython.memory.gctransform.transform import GCTransformer, mallocHelpers
 from pypy.rpython.memory.gctransform.support import find_gc_ptrs_in_type, \
      get_rtti, _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor
 from pypy.rpython.lltypesystem import lltype, llmemory
@@ -70,11 +70,11 @@
         def ll_no_pointer_dealloc(adr):
             llop.gc_free(lltype.Void, adr)
 
+        mh = mallocHelpers()
+        mh.allocate = lladdress.raw_malloc
         def ll_malloc_fixedsize(size):
             size = gc_header_offset + size
-            result = lladdress.raw_malloc(size)
-            if not result:
-                raise memoryError
+            result = mh._ll_malloc_fixedsize(size)
             lladdress.raw_memclear(result, size)
             result += gc_header_offset
             return result
@@ -84,17 +84,13 @@
                 varsize = ovfcheck(itemsize * length)
                 tot_size = ovfcheck(fixsize + varsize)
             except OverflowError:
-                raise memoryError
-            result = lladdress.raw_malloc(tot_size)
-            if not result:
-                raise memoryError
+                raise MemoryError()
+            result = mh._ll_malloc_fixedsize(tot_size)
             lladdress.raw_memclear(result, tot_size)
             result += gc_header_offset
             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
+        mh.ll_malloc_varsize_no_length = ll_malloc_varsize_no_length
+        ll_malloc_varsize = mh.ll_malloc_varsize
 
         if self.translator:
             self.increfptr = self.inittime_helper(
@@ -112,7 +108,8 @@
                 ll_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address)
             self.malloc_varsize_ptr = self.inittime_helper(
                 ll_malloc_varsize, [lltype.Signed]*4, llmemory.Address)
-            self.mixlevelannotator.finish()   # for now
+            self.mixlevelannotator.finish()
+            self.mixlevelannotator.backend_optimize()
         # cache graphs:
         self.decref_funcptrs = {}
         self.static_deallocator_funcptrs = {}
@@ -147,52 +144,24 @@
         """ get this object back into gc control """
         self.pop_alive(hop.spaceop.args[0])
 
-    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))
+    def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size):
         v_raw = hop.genop("direct_call", [self.malloc_fixedsize_ptr, c_size],
                           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)
-
-        op = hop.spaceop
-        TYPE = op.result.concretetype.TO
-        assert TYPE._is_varsize()
+        return v_raw
 
-        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):
+    def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size,
+                                                                   c_offset_to_length):
+        if c_offset_to_length is None:
             v_raw = hop.genop("direct_call",
-                               [self.malloc_varsize_no_length_ptr, op.args[-1],
+                               [self.malloc_varsize_no_length_ptr, v_length,
                                 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)],
+                               [self.malloc_varsize_ptr, v_length,
+                                c_const_size, c_item_size, c_offset_to_length],
                                resulttype=llmemory.Address)
-        hop.cast_result(v_raw)
-
-    gct_zero_malloc_varsize = gct_malloc_varsize
+        return v_raw
 
     def gct_gc_deallocate(self, hop):
         TYPE = hop.spaceop.args[0].value

Modified: pypy/dist/pypy/rpython/memory/gctransform/stacklessframework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/stacklessframework.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/stacklessframework.py	Sun Aug  5 00:42:12 2007
@@ -1,23 +1,11 @@
-from pypy.rpython.memory.gctransform.transform import \
-     MinimalGCTransformer, var_ispyobj
-from pypy.rpython.memory.gctransform.framework import \
-     FrameworkGCTransformer
+from pypy.rpython.memory.gctransform.transform import var_ispyobj
+from pypy.rpython.memory.gctransform.framework import FrameworkGCTransformer
 from pypy.rpython.lltypesystem import lltype, llmemory
 
-class StacklessFrameworkMinimalGCTransformer(MinimalGCTransformer):
-    def gct_flavored_malloc(self, hop):
-        flavor = hop.spaceop.args[0].value
-        if flavor == 'gc_nocollect':
-            return self.parenttransformer.gct_flavored_malloc(hop)
-        else:
-            self.default(hop)
-    gct_flavored_malloc_varsize = gct_flavored_malloc
-
 
 class StacklessFrameworkGCTransformer(FrameworkGCTransformer):
     use_stackless = True
     extra_static_slots = 1     # for the stack_capture()'d frame
-    MinimalGCTransformer = StacklessFrameworkMinimalGCTransformer
 
     def __init__(self, translator):
         FrameworkGCTransformer.__init__(self, translator)

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	Sun Aug  5 00:42:12 2007
@@ -1,4 +1,4 @@
-from pypy.rpython.memory.gctransform.transform import GCTransformer
+from pypy.rpython.memory.gctransform.transform import BaseGCTransformer
 from pypy.objspace.flow.model import c_last_exception, Variable
 from pypy.rpython.memory.gctransform.support import var_ispyobj
 from pypy.translator.backendopt.support import var_needsgc
@@ -87,7 +87,7 @@
         res = llinterp.eval_graph(graph, [cc('brrrrrr')])
         assert res == f('brrrrrr')
 
-class _TestGCTransformer(GCTransformer):
+class _TestGCTransformer(BaseGCTransformer):
 
     def push_alive_nopyobj(self, var, llops):
         llops.genop("gc_push_alive", [var])

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	Sun Aug  5 00:42:12 2007
@@ -12,12 +12,14 @@
 from pypy.translator.backendopt.ssa import DataFlowFamilyBuilder
 from pypy.annotation import model as annmodel
 from pypy.rpython import rmodel, annlowlevel
-from pypy.rpython.memory import gc, lladdress
+from pypy.rpython.memory import gc
 from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
 from pypy.rpython.rtyper import LowLevelOpList
 from pypy.rpython.rbuiltin import gen_cast
 from pypy.rlib.rarithmetic import ovfcheck
 import sets, os, sys
+from pypy.rpython.memory import lladdress
+from pypy.rpython.lltypesystem.lloperation import llop
 
 def var_ispyobj(var):
     if hasattr(var, 'concretetype'):
@@ -83,8 +85,9 @@
             assert v_new != var
             self.llops[-1].result = v_result
 
+# ________________________________________________________________
 
-class GCTransformer(object):
+class BaseGCTransformer(object):
     finished_helpers = False
 
     def __init__(self, translator, inline=False):
@@ -103,7 +106,7 @@
             self.minimalgctransformer = self.MinimalGCTransformer(self)
         else:
             self.minimalgctransformer = None
-
+            
     def get_lltype_of_exception_value(self):
         if self.translator is not None:
             exceptiondata = self.translator.rtyper.getexceptiondata()
@@ -189,6 +192,7 @@
         if graph in self.seen_graphs:
             return
         self.seen_graphs[graph] = True
+
         self.links_to_split = {} # link -> vars to pop_alive across the link
 
         # for sanity, we need an empty block at the start of the graph
@@ -323,9 +327,10 @@
     def gct_zero_gc_pointers_inside(self, hop):
         pass
 
-class MinimalGCTransformer(GCTransformer):
+
+class MinimalGCTransformer(BaseGCTransformer):
     def __init__(self, parenttransformer):
-        GCTransformer.__init__(self, parenttransformer.translator)
+        BaseGCTransformer.__init__(self, parenttransformer.translator)
         self.parenttransformer = parenttransformer
 
     def push_alive(self, var, llops=None):
@@ -334,5 +339,174 @@
     def pop_alive(self, var, llops=None):
         pass
 
-GCTransformer.MinimalGCTransformer = MinimalGCTransformer
+    def gct_malloc(self, hop):
+        flags = hop.spaceop.args[1].value
+        flavor = flags['flavor']
+        assert flavor == 'raw'
+        return self.parenttransformer.gct_malloc(hop)
+
+    def gct_malloc_varsize(self, hop):
+        flags = hop.spaceop.args[1].value
+        flavor = flags['flavor']
+        assert flavor == 'raw'
+        return self.parenttransformer.gct_malloc_varsize(hop)
+    
+    def gct_free(self, hop):
+        flavor = hop.spaceop.args[1].value
+        assert flavor == 'raw'
+        return self.parenttransformer.gct_free(hop)
+
+BaseGCTransformer.MinimalGCTransformer = MinimalGCTransformer
 MinimalGCTransformer.MinimalGCTransformer = None
+
+# ________________________________________________________________
+
+def mallocHelpers():
+    class _MallocHelpers(object):
+        def _freeze_(self):
+            return True
+    mh = _MallocHelpers()
+
+    def _ll_malloc_fixedsize(size):
+        result = mh.allocate(size)
+        if not result:
+            raise MemoryError()
+        return result
+    mh._ll_malloc_fixedsize = _ll_malloc_fixedsize
+    
+    def _ll_malloc_varsize_no_length(length, size, itemsize):
+        try:
+            varsize = ovfcheck(itemsize * length)
+            tot_size = ovfcheck(size + varsize)
+        except OverflowError:
+            raise MemoryError()
+        result = mh.allocate(tot_size)
+        if not result:
+            raise MemoryError()
+        return result
+    mh._ll_malloc_varsize_no_length = _ll_malloc_varsize_no_length
+    mh.ll_malloc_varsize_no_length = _ll_malloc_varsize_no_length
+
+    def ll_malloc_varsize(length, size, itemsize, lengthoffset):
+        result = mh.ll_malloc_varsize_no_length(length, size, itemsize)
+        (result + lengthoffset).signed[0] = length
+        return result
+    mh.ll_malloc_varsize = ll_malloc_varsize
+
+    return mh
+
+class GCTransformer(BaseGCTransformer):
+
+    def __init__(self, translator, inline=False):
+        super(GCTransformer, self).__init__(translator, inline=inline)
+
+        mh = mallocHelpers()
+        mh.allocate = lladdress.raw_malloc
+        ll_raw_malloc_fixedsize = mh._ll_malloc_fixedsize
+        ll_raw_malloc_varsize_no_length = mh.ll_malloc_varsize_no_length
+        ll_raw_malloc_varsize = mh.ll_malloc_varsize
+
+        stack_mh = mallocHelpers()
+        stack_mh.allocate = lambda size: llop.stack_malloc(llmemory.Address, size)
+        ll_stack_malloc_fixedsize = stack_mh._ll_malloc_fixedsize
+        
+        if self.translator:
+            self.raw_malloc_fixedsize_ptr = self.inittime_helper(
+                ll_raw_malloc_fixedsize, [lltype.Signed], llmemory.Address)
+            self.raw_malloc_varsize_no_length_ptr = self.inittime_helper(
+                ll_raw_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address, inline=False)
+            self.raw_malloc_varsize_ptr = self.inittime_helper(
+                ll_raw_malloc_varsize, [lltype.Signed]*4, llmemory.Address, inline=False)
+
+            self.stack_malloc_fixedsize_ptr = self.inittime_helper(
+                ll_stack_malloc_fixedsize, [lltype.Signed], llmemory.Address)
+
+    def gct_malloc(self, hop):
+        TYPE = hop.spaceop.result.concretetype.TO
+        assert not TYPE._is_varsize()
+        flags = hop.spaceop.args[1].value
+        flavor = flags['flavor']
+        meth = getattr(self, 'gct_fv_%s_malloc' % flavor, None)
+        assert meth, "%s has no support for malloc with flavor %r" % (self, flavor) 
+        c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE))
+        v_raw = meth(hop, flags, TYPE, c_size)
+        hop.cast_result(v_raw)
+
+    def gct_fv_raw_malloc(self, hop, flags, TYPE, c_size):
+        v_raw = hop.genop("direct_call", [self.raw_malloc_fixedsize_ptr, c_size],
+                          resulttype=llmemory.Address)
+        return v_raw
+
+    def gct_fv_stack_malloc(self, hop, flags, TYPE, c_size):
+        v_raw = hop.genop("direct_call", [self.stack_malloc_fixedsize_ptr, c_size],
+                          resulttype=llmemory.Address)
+        return v_raw        
+
+    def gct_fv_cpy_malloc(self, hop, flags, TYPE, c_size): # xxx
+        op = hop.spaceop
+        args = op.args[:]
+        del args[1]
+        return hop.genop('cpy_malloc', args, resulttype=op.result.concretetype)
+
+    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()
+        flags = hop.spaceop.args[1].value
+        flavor = flags['flavor']
+        meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None)
+        assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) 
+
+        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):
+            c_offset_to_length = None
+        else:
+            if isinstance(TYPE, lltype.Struct):
+                offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \
+                                   llmemory.ArrayLengthOffset(ARRAY)
+            else:
+                offset_to_length = llmemory.ArrayLengthOffset(ARRAY)
+            c_offset_to_length = intconst(offset_to_length)
+
+        v_raw = meth(hop, flags, TYPE, op.args[-1], c_const_size, c_item_size,
+                                                    c_offset_to_length)
+
+        hop.cast_result(v_raw)
+
+    def gct_fv_raw_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size,
+                                                                    c_offset_to_length):
+        if c_offset_to_length is None:
+            v_raw = hop.genop("direct_call",
+                               [self.raw_malloc_varsize_no_length_ptr, v_length,
+                                c_const_size, c_item_size],
+                               resulttype=llmemory.Address)
+        else:
+            v_raw = hop.genop("direct_call",
+                               [self.raw_malloc_varsize_ptr, v_length,
+                                c_const_size, c_item_size, c_offset_to_length],
+                               resulttype=llmemory.Address)
+        return v_raw
+
+    def gct_free(self, hop):
+        op = hop.spaceop
+        flavor = op.args[1].value
+        v = op.args[0]
+        if flavor == 'raw':
+            v = hop.genop("cast_ptr_to_adr", [v], resulttype=llmemory.Address)
+            hop.genop('raw_free', [v])
+        elif flavor == 'cpy':
+            hop.genop('cpy_free', [v]) # xxx
+        else:
+            assert False, "%s has no support for free with flavor %r" % (self, flavor)           

Modified: pypy/dist/pypy/rpython/memory/lltypesimulation.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lltypesimulation.py	(original)
+++ pypy/dist/pypy/rpython/memory/lltypesimulation.py	Sun Aug  5 00:42:12 2007
@@ -194,7 +194,7 @@
         return self._address
 
 # for now use the simulators raw_malloc
-def malloc(T, n=None, immortal=False, flavor='gc'):
+def malloc(T, n=None, immortal=False, flavor='gc', zero=True):
     fixedsize = get_fixed_size(T)
     varsize = get_variable_size(T)
     if n is None:

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Sun Aug  5 00:42:12 2007
@@ -330,12 +330,15 @@
     v_flavor, v_extra_args, v_zero = parse_kwds(hop, (i_flavor, lltype.Void),
                                                      (i_extra_args, None),
                                                      (i_zero, None))
+
+    flags = {'flavor': 'gc'}
     if v_flavor is not None:
-        vlist.insert(0, v_flavor)
-        opname = 'flavored_' + opname
+        flags['flavor'] = v_flavor.value
     if i_zero is not None:
         assert i_extra_args is i_flavor is None
-        opname = 'zero_' + opname
+        flags['zero'] = v_zero.value
+    vlist.append(hop.inputconst(lltype.Void, flags))
+        
     if hop.nb_args == 2:
         vlist.append(hop.inputarg(lltype.Signed, arg=1))
         opname += '_varsize'
@@ -355,8 +358,7 @@
     assert i_flavor == 1
     hop.exception_cannot_occur()
     vlist = hop.inputargs(hop.args_r[0], lltype.Void)
-    vlist.reverse()   # just for confusion
-    hop.genop('flavored_free', vlist)
+    hop.genop('free', vlist)
 
 def rtype_const_result(hop):
     return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const)
@@ -595,9 +597,9 @@
 def rtype_free_non_gc_object(hop):
     vinst, = hop.inputargs(hop.args_r[0])
     flavor = hop.args_r[0].gcflavor
-    assert not flavor.startswith('gc')
+    assert flavor != 'gc'
     cflavor = hop.inputconst(lltype.Void, flavor)
-    return hop.genop('flavored_free', [cflavor, vinst])
+    return hop.genop('free', [vinst, cflavor])
     
 BUILTIN_TYPER[objectmodel.free_non_gc_object] = rtype_free_non_gc_object
 

Modified: pypy/dist/pypy/rpython/rctypes/astringbuf.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/astringbuf.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/astringbuf.py	Sun Aug  5 00:42:12 2007
@@ -34,8 +34,9 @@
         [v_length] = hop.inputargs(lltype.Signed)
         r_stringbuf = hop.r_result
         hop.exception_cannot_occur()
-        return hop.genop("zero_malloc_varsize", [
+        return hop.genop("malloc_varsize", [
             hop.inputconst(lltype.Void, r_stringbuf.lowleveltype.TO),
+            hop.inputconst(lltype.Void, {'flavor': 'gc', 'zero': True}),
             v_length,
             ], resulttype=r_stringbuf.lowleveltype,
         )

Modified: pypy/dist/pypy/rpython/rctypes/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rmodel.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rmodel.py	Sun Aug  5 00:42:12 2007
@@ -123,14 +123,16 @@
         if TYPE._is_varsize():
             raise TyperError("allocating array with unknown length")
         c1 = inputconst(lltype.Void, TYPE)
-        return llops.genop("zero_malloc", [c1], resulttype=self.lowleveltype)
+        cflags = inputconst(lltype.Void, {'flavor': 'gc', 'zero': True})
+        return llops.genop("malloc", [c1, cflags], resulttype=self.lowleveltype)
 
     def allocate_instance_varsize(self, llops, v_length):
         TYPE = self.lowleveltype.TO
         if not TYPE._is_varsize():
             raise TyperError("allocating non-array with a specified length")
         c1 = inputconst(lltype.Void, TYPE)
-        return llops.genop("zero_malloc_varsize", [c1, v_length],
+        cflags = inputconst(lltype.Void, {'flavor': 'gc', 'zero': True})
+        return llops.genop("malloc_varsize", [c1, cflags, v_length],
                            resulttype=self.lowleveltype)
 
     def allocate_instance_ref(self, llops, v_c_data, v_c_data_owner=None):

Modified: pypy/dist/pypy/rpython/test/test_llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_llinterp.py	(original)
+++ pypy/dist/pypy/rpython/test/test_llinterp.py	Sun Aug  5 00:42:12 2007
@@ -410,8 +410,7 @@
         a.i = 1
         return a.i
     interp, graph = get_interpreter(f, [])
-    graph.startblock.operations[0].opname = "flavored_malloc"
-    graph.startblock.operations[0].args.insert(0, inputconst(Void, "stack"))
+    graph.startblock.operations[0].args[1] = inputconst(Void, {'flavor': "stack"})
     result = interp.eval_graph(graph, [])
     assert result == 1
 
@@ -432,8 +431,7 @@
         return globala.next.i
     interp, graph = get_interpreter(h, [])
     fgraph = graph.startblock.operations[0].args[0].value._obj.graph
-    fgraph.startblock.operations[0].opname = "flavored_malloc"
-    fgraph.startblock.operations[0].args.insert(0, inputconst(Void, "stack"))
+    fgraph.startblock.operations[0].args[1] = inputconst(Void, {'flavor': "stack"})
     py.test.raises(AttributeError, "interp.eval_graph(graph, [])")
 
 #__________________________________________________________________

Modified: pypy/dist/pypy/translator/backendopt/escape.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/escape.py	(original)
+++ pypy/dist/pypy/translator/backendopt/escape.py	Sun Aug  5 00:42:12 2007
@@ -185,19 +185,21 @@
         args = self.getstates(op.args)
         #print "args:", args
         opimpl = getattr(self, 'op_'+op.opname, None)
-        if opimpl is None:
-            if isonheap(op.result) or filter(None, args):
-                for arg in args:
-                    if arg is not None:
-                        changed = arg.setchanges()
-                        self.handle_changed(changed)
-                        changed = arg.setescapes()
-                        self.handle_changed(changed)
-                #raise NotImplementedError("can't handle %s" % (op.opname, ))
+        if opimpl is not None:
+            res = opimpl(op, *args)
+            if res is not NotImplemented:
+                self.setstate(op.result, res)
+                return
+            
+        if isonheap(op.result) or filter(None, args):
+            for arg in args:
+                if arg is not None:
+                    changed = arg.setchanges()
+                    self.handle_changed(changed)
+                    changed = arg.setescapes()
+                    self.handle_changed(changed)
+            #raise NotImplementedError("can't handle %s" % (op.opname, ))
             #print "assuming that '%s' is irrelevant" % op
-            return
-        res = opimpl(op, *args)
-        self.setstate(op.result, res)
         
     def complete(self):
         while self.scheduled:
@@ -235,10 +237,18 @@
     # _____________________________________________________________________
     # operation implementations
 
-    def op_malloc(self, op, typestate):
+    def op_malloc(self, op, typestate, flagsstate):
+        assert flagsstate is None
+        flags = op.args[1].value
+        if flags != {'flavor': 'gc'}:
+            return NotImplemented
         return VarState(self.get_creationpoint(op.result, "malloc"))
 
-    def op_malloc_varsize(self, op, typestate, lengthstate):
+    def op_malloc_varsize(self, op, typestate, flagsstate, lengthstate):
+        assert flagsstate is None
+        flags = op.args[1].value
+        if flags != {'flavor': 'gc'}:
+            return NotImplemented
         return VarState(self.get_creationpoint(op.result, "malloc_varsize"))
 
     def op_keepalive(self, op, state):
@@ -391,8 +401,9 @@
                 if not crep.escapes:
                     if block not in loop_blocks:
                         print "moving object from heap to stack %s in %s" % (op, graph.name)
-                        op.opname = 'flavored_malloc'
-                        op.args.insert(0, inputconst(lltype.Void, 'stack'))
+                        flags = op.args[1].value
+                        assert flags == {'flavor': 'gc'}
+                        op.args[1] = Constant({'flavor': 'stack'}, lltype.Void)
                     else:
                         print "%s in %s is a non-escaping malloc in a loop" % (op, graph.name)
 

Modified: pypy/dist/pypy/translator/backendopt/malloc.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/malloc.py	(original)
+++ pypy/dist/pypy/translator/backendopt/malloc.py	Sun Aug  5 00:42:12 2007
@@ -32,6 +32,12 @@
     def __init__(self, verbose=True):
         self.verbose = verbose
 
+    def check_malloc(self, op):
+        return op.opname == self.MALLOC_OP
+
+    def recreate_malloc(self, c, v):
+        return SpaceOperation(self.MALLOC_OP, [c], v)
+
     def get_STRUCT(self, TYPE):
         raise NotImplementedError
 
@@ -89,7 +95,7 @@
                     if c.value == op.args[0].value:
                         progress = False   # replacing a malloc with
                                            # the same malloc!
-                    newop = SpaceOperation(self.MALLOC_OP, [c], v)
+                    newop = self.recreate_malloc(c, v)
                     self.newops.append(newop)
                     newvarsmap[key] = v
                 count[0] += progress
@@ -191,7 +197,7 @@
             if cp[0] != "op":
                 return False
             op = cp[2]
-            if op.opname != self.MALLOC_OP:
+            if not self.check_malloc(op):
                 return False
             if not self.inline_type(op.args[0].value):
                 return False
@@ -282,7 +288,7 @@
             # look for variables created inside the block by a malloc
             vars_created_here = []
             for op in block.operations:
-                if op.opname == self.MALLOC_OP and op.result in vars:
+                if self.check_malloc(op) and op.result in vars:
                     vars_created_here.append(op.result)
             for var in vars_created_here:
                 self.flowin(block, count, var, newvarsmap=None)
@@ -333,6 +339,19 @@
                                        "setarrayitem",
                                        "getarraysubstruct"])
 
+    def check_malloc(self, op):
+        if op.opname == 'malloc':
+            flags = op.args[1].value
+            if flags == {'flavor': 'gc'}:
+                return True
+        return False
+
+    def recreate_malloc(self, c, v):
+        return SpaceOperation(self.MALLOC_OP, [c,
+                                               Constant({'flavor': 'gc'},
+                                                        lltype.Void)],
+                              v)
+
     def get_STRUCT(self, TYPE):
         STRUCT = TYPE.TO
         assert isinstance(STRUCT, lltype.GcStruct)

Modified: pypy/dist/pypy/translator/backendopt/mallocprediction.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/mallocprediction.py	(original)
+++ pypy/dist/pypy/translator/backendopt/mallocprediction.py	Sun Aug  5 00:42:12 2007
@@ -17,6 +17,9 @@
         if op.opname == 'malloc':
             STRUCT = op.args[0].value
             # must not remove mallocs of structures that have a RTTI with a destructor
+            flags = op.args[1].value
+            if flags != {'flavor': 'gc'}:
+                continue
             try:
                 destr_ptr = lltype.getRuntimeTypeInfo(
                     STRUCT)._obj.destructor_funcptr

Modified: pypy/dist/pypy/translator/backendopt/test/test_escape.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_escape.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_escape.py	Sun Aug  5 00:42:12 2007
@@ -4,6 +4,8 @@
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rlib.objectmodel import instantiate
 
+import py
+
 def build_adi(function, types):
     t = TranslationContext()
     t.buildannotator().build_types(function, types)
@@ -26,7 +28,8 @@
     if must_remove:
         for block in graph.iterblocks():
             for op in block.operations:
-                assert op.opname != "malloc"
+                if op.opname == "malloc":
+                    assert op.args[1].value['flavor'] == 'stack'
     res = interp.eval_graph(graph, args)
     assert res == expected_result
     return t
@@ -382,6 +385,7 @@
     t, adi, graph = build_adi(entrypoint, [int])
 
 def test_extfunc_onheaparg():
+    py.test.skip("not a valid test anymore")
     import os
     def f(i):
         s = str(i)

Modified: pypy/dist/pypy/translator/c/exceptiontransform.py
==============================================================================
--- pypy/dist/pypy/translator/c/exceptiontransform.py	(original)
+++ pypy/dist/pypy/translator/c/exceptiontransform.py	Sun Aug  5 00:42:12 2007
@@ -355,10 +355,8 @@
 
         insert_zeroing_op = False
         if spaceop.opname == 'malloc':
-            insert_zeroing_op = True
-        elif spaceop.opname == 'flavored_malloc':
-            flavor = spaceop.args[0].value
-            if flavor.startswith('gc'):
+            flavor = spaceop.args[1].value['flavor']
+            if flavor == 'gc':
                 insert_zeroing_op = True
 
         if insert_zeroing_op:

Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Sun Aug  5 00:42:12 2007
@@ -527,90 +527,21 @@
         esize = self.expr(op.args[0])
         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)
+    def OP_STACK_MALLOC(self, op):
         eresult = self.expr(op.result)
-        esize = 'sizeof(%s)' % cdecl(typename, '')
-        erestype = cdecl(typename, '*')
-        flavor = op.args[0].value
-        if flavor == "raw": 
-            return "OP_RAW_MALLOC(%s, %s, %s);" % (esize, eresult, erestype)
-        elif flavor == "stack": 
-            return "OP_STACK_MALLOC(%s, %s, %s);" % (esize, eresult, erestype)
-        elif flavor == "cpy":
-            cpytype = self.expr(op.args[2])
-            return "OP_CPY_MALLOC(%s, %s, %s);" % (cpytype, eresult, erestype)
-        else:
-            raise NotImplementedError
+        esize = self.expr(op.args[0])
+        return "OP_STACK_MALLOC(%s, %s, void *);" % (esize, eresult)
 
-    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
-        assert flavor == 'raw'
+    def OP_CPY_MALLOC(self, op):
         TYPE = self.lltypemap(op.result).TO
-        assert isinstance(TYPE, Array)
-        assert TYPE._hints.get('nolength', False)
-        # </obscure hack>
         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[2])
-        eresult = self.expr(op.result)
         erestype = cdecl(typename, '*')
-        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)
-
-        # ctypes Arrays have no length field
-        if not VARPART._hints.get('nolength', False):
-            result += '\nif(%s) %s->%s = %s;' % (eresult, eresult, lenfld, elength)
-        if flavor == "raw": 
-            result += "OP_RAW_MALLOC(%s, %s, %s);" % (esize, eresult, erestype)
-        elif flavor == "stack": 
-            result += "OP_STACK_MALLOC(%s, %s, %s);" % (esize, eresult, erestype)
-        elif flavor == "cpy":
-            xxx # this will never work, as I don't know which arg it would be
-            # tests, tests, tests....
-            cpytype = self.expr(op.args[2])
-            result += "OP_CPY_MALLOC(%s, %s, %s);" % (cpytype, eresult, erestype)
-        else:
-            raise NotImplementedError
-        
-        result += '\n}'
-        return result
-
-    def OP_FLAVORED_FREE(self, op):
-        flavor = op.args[0].value
-        if flavor == "raw":
-            return "OP_RAW_FREE(%s, %s)" % (self.expr(op.args[1]),
-                                            self.expr(op.result))
-        elif flavor == "cpy":
-            return "OP_CPY_FREE(%s)" % (self.expr(op.args[1]),)
-        else:
-            raise NotImplementedError
+        eresult = self.expr(op.result)
+        cpytype = self.expr(op.args[1])
+        return "OP_CPY_MALLOC(%s, %s, %s);" % (cpytype, eresult, erestype)
+
+    def OP_CPY_FREE(self, op):
+        return "OP_CPY_FREE(%s)" % (self.expr(op.args[1]),)
 
     def OP_DIRECT_FIELDPTR(self, op):
         return self.OP_GETFIELD(op, ampersand='&')

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	Sun Aug  5 00:42:12 2007
@@ -43,39 +43,12 @@
 
 #define OP_STACK_MALLOC(size,r,restype)                                 \
     r = (restype) alloca(size);                                         \
-    if (r == NULL) FAIL_EXCEPTION(PyExc_MemoryError, "out of memory");  \
-    memset((void*) r, 0, size);
-
+    if (r != NULL) memset((void*) r, 0, size);
+    
 #define OP_RAW_MEMCOPY(x,y,size,r) memcpy(y,x,size);
 
 /************************************************************/
 
-/* a reasonably safe bound on the largest allowed argument value
-   that we can pass to malloc.  This is used for var-sized mallocs
-   to compute the largest allowed number of items in the array. */
-#define MAXIMUM_MALLOCABLE_SIZE   (LONG_MAX-4096)
-
-#define IF_VARSIZE_OVERFLOW(numitems, itemtype, r)			\
-    if (((unsigned long)(numitems)) >					\
-		(MAXIMUM_MALLOCABLE_SIZE / sizeof(itemtype))) {		\
-        FAIL_EXCEPTION(PyExc_MemoryError, "addr space overflow");	\
-	r = NULL;							\
-    }
-/*  else { ...}  -- generated by funcgen.py */
-
-#if RAW_MALLOC_ZERO_FILLED
-
-#define OP_ZERO_MALLOC OP_RAW_MALLOC
-
-#else
-
-#define OP_ZERO_MALLOC(size, r, restype)  {				\
-		OP_RAW_MALLOC(size, r, restype);			\
-		if (r != NULL) OP_RAW_MEMCLEAR(r, size, /* */);		\
-	}
-
-#endif
-
 #define OP_FREE(p)	OP_RAW_FREE(p, do_not_use)
 
 /*------------------------------------------------------------*/

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Sun Aug  5 00:42:12 2007
@@ -152,10 +152,8 @@
     def __init__(self, stackless_gc=False, transformer=None):
         self.frametypes = {}
         self.stackless_gc = stackless_gc
-        self.c_gc_nocollect = model.Constant("gc_nocollect", lltype.Void)
         self.transformer = transformer
         
-
     def _key_for_types(self, TYPES):
         counts = {}
         for EXACT_TYPE in TYPES:
@@ -173,16 +171,13 @@
         save_block = model.Block([v_exception, v_restart])
         
         llops = LowLevelOpList()
+        flags = {'flavor': 'gc'}
         if self.stackless_gc:
-            v_state = llops.genop(
-                'flavored_malloc',
-                [self.c_gc_nocollect, model.Constant(FRAME_TYPE, lltype.Void)],
-                resulttype=lltype.Ptr(FRAME_TYPE))
-        else:
-            v_state = llops.genop(
-                'malloc',
-                [model.Constant(FRAME_TYPE, lltype.Void)],
-                resulttype=lltype.Ptr(FRAME_TYPE))
+            flags['nocollect'] = True
+        v_state = llops.genop('malloc',
+                              [model.Constant(FRAME_TYPE, lltype.Void),
+                               model.Constant(flags, lltype.Void)],
+                              resulttype=lltype.Ptr(FRAME_TYPE))
 
         for fieldname in FRAME_TYPE._names[1:]: # skip the 'header' field
             v_arg = varoftype(FRAME_TYPE._flds[fieldname])
@@ -263,7 +258,12 @@
             return True
         elif op.opname == 'resume_state_create':
             return True
-        return self.stackless_gc and LL_OPERATIONS[op.opname].canunwindgc
+        if self.stackless_gc:
+            if op.opname in ('malloc', 'malloc_varsize'):
+                flags = op.args[1].value
+                return flags['flavor'] == 'gc' and not flags.get('nocollect', False)
+            return  LL_OPERATIONS[op.opname].canunwindgc
+        return False
 
     def analyze_external_call(self, op):
         callable = op.args[0].value._obj._callable
@@ -452,7 +452,7 @@
         self.c_minus_one = model.Constant(-1, lltype.Signed)
         self.c_null_state = model.Constant(null_state,
                                            lltype.typeOf(null_state))
-        self.c_gc_nocollect = model.Constant("gc_nocollect", lltype.Void)
+        self.c_gc_nocollect = model.Constant({'flavor': 'gc', 'nocollect': True}, lltype.Void)
 
         self.is_finished = False
 
@@ -662,7 +662,8 @@
         # it to the saving function, then read the thus created state
         # out of and then clear global_state.top
         c_EXC = model.Constant(self.unwind_exception_type.TO, lltype.Void)
-        v_exc = llops.genop('malloc', [c_EXC],
+        c_flags = model.Constant({'flavor': 'gc'}, lltype.Void)
+        v_exc = llops.genop('malloc', [c_EXC, c_flags],
                             resulttype = self.unwind_exception_type)
 
         realvarsforcall = []
@@ -1177,7 +1178,7 @@
         for block in graph.iterblocks():
             for i, op in enumerate(block.operations):
                 if op.opname.startswith('malloc'):
-                    newop = model.SpaceOperation('flavored_' + op.opname,
-                                                 [self.c_gc_nocollect]+op.args,
-                                                 op.result)
+                    newargs = op.args[:]
+                    newargs[1] = self.c_gc_nocollect
+                    newop = model.SpaceOperation(op.opname, newargs, op.result)
                     block.operations[i] = newop



More information about the Pypy-commit mailing list