[pypy-svn] r67471 - in pypy/branch/weakdict/pypy: config config/test doc/config jit/backend/llsupport jit/backend/llsupport/test jit/metainterp jit/tl objspace/std rpython rpython/memory/gc rpython/memory/gctransform rpython/memory/test translator/goal

arigo at codespeak.net arigo at codespeak.net
Fri Sep 4 14:28:06 CEST 2009


Author: arigo
Date: Fri Sep  4 14:28:03 2009
New Revision: 67471

Added:
   pypy/branch/weakdict/pypy/doc/config/translation.norweakarray.txt   (contents, props changed)
   pypy/branch/weakdict/pypy/doc/config/translation.norweakref.txt
      - copied unchanged from r67470, pypy/branch/weakdict/pypy/doc/config/translation.rweakref.txt
Removed:
   pypy/branch/weakdict/pypy/doc/config/translation.rweakref.txt
Modified:
   pypy/branch/weakdict/pypy/config/pypyoption.py
   pypy/branch/weakdict/pypy/config/test/test_pypyoption.py
   pypy/branch/weakdict/pypy/config/translationoption.py
   pypy/branch/weakdict/pypy/jit/backend/llsupport/gc.py
   pypy/branch/weakdict/pypy/jit/backend/llsupport/test/test_gc.py
   pypy/branch/weakdict/pypy/jit/metainterp/codewriter.py
   pypy/branch/weakdict/pypy/jit/tl/targetpypyjit.py
   pypy/branch/weakdict/pypy/objspace/std/typeobject.py
   pypy/branch/weakdict/pypy/rpython/memory/gc/base.py
   pypy/branch/weakdict/pypy/rpython/memory/gc/generation.py
   pypy/branch/weakdict/pypy/rpython/memory/gc/hybrid.py
   pypy/branch/weakdict/pypy/rpython/memory/gc/markcompact.py
   pypy/branch/weakdict/pypy/rpython/memory/gc/marksweep.py
   pypy/branch/weakdict/pypy/rpython/memory/gc/semispace.py
   pypy/branch/weakdict/pypy/rpython/memory/gctransform/framework.py
   pypy/branch/weakdict/pypy/rpython/memory/test/test_gc.py
   pypy/branch/weakdict/pypy/rpython/rweakref.py
   pypy/branch/weakdict/pypy/translator/goal/targetpreimportedpypy.py
   pypy/branch/weakdict/pypy/translator/goal/targetpypystandalone.py
Log:
Intermediate check-in.  Hugeish.  Add the "contains_weakptr" flag
to all malloc_varsize() around, and fix the gc transformer.
Add "norweakarray" as a translation option, forced to True by the
GCs that don't support it.  Rename the translation option "rweakref"
into "norweakref" so that it can, if set to True, force
"norweakarray" to be True too.  Tons of fun, not really tested so far.


Modified: pypy/branch/weakdict/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/weakdict/pypy/config/pypyoption.py	(original)
+++ pypy/branch/weakdict/pypy/config/pypyoption.py	Fri Sep  4 14:28:03 2009
@@ -269,7 +269,7 @@
                    cmdline=None,
                    default=False,
                    # weakrefs needed, because of get_subclasses()
-                   requires=[("translation.rweakref", True)]),
+                   requires=[("translation.norweakref", False)]),
 
         BoolOption("withshadowtracking",
                    "track whether an instance attribute shadows a type"
@@ -277,12 +277,12 @@
                    default=False,
                    requires=[("objspace.std.withmultidict", True),
                              ("objspace.std.withtypeversion", True),
-                             ("translation.rweakref", True)]),
+                             ("translation.norweakref", False)]),
         BoolOption("withmethodcache",
                    "try to cache method lookups",
                    default=False,
                    requires=[("objspace.std.withtypeversion", True),
-                             ("translation.rweakref", True)]),
+                             ("translation.norweakref", False)]),
         BoolOption("withmethodcachecounter",
                    "try to cache methods and provide a counter in __pypy__. "
                    "for testing purposes only.",

Modified: pypy/branch/weakdict/pypy/config/test/test_pypyoption.py
==============================================================================
--- pypy/branch/weakdict/pypy/config/test/test_pypyoption.py	(original)
+++ pypy/branch/weakdict/pypy/config/test/test_pypyoption.py	Fri Sep  4 14:28:03 2009
@@ -54,7 +54,7 @@
 
 def test_rweakref_required():
     conf = get_pypy_config()
-    conf.translation.rweakref = False
+    conf.translation.norweakref = True
     set_pypy_opt_level(conf, '3')
 
     assert not conf.objspace.std.withtypeversion

Modified: pypy/branch/weakdict/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/weakdict/pypy/config/translationoption.py	(original)
+++ pypy/branch/weakdict/pypy/config/translationoption.py	Fri Sep  4 14:28:03 2009
@@ -47,17 +47,21 @@
                  ["boehm", "ref", "marksweep", "semispace", "statistics",
                   "generation", "hybrid", "markcompact", "none"],
                   "ref", requires={
-                     "ref": [("translation.rweakref", False), # XXX
+                     "ref": [("translation.norweakref", True), # XXX
                              ("translation.gctransformer", "ref")],
-                     "none": [("translation.rweakref", False), # XXX
+                     "none": [("translation.norweakref", True), # XXX
                              ("translation.gctransformer", "none")],
                      "semispace": [("translation.gctransformer", "framework")],
-                     "marksweep": [("translation.gctransformer", "framework")],
-                     "statistics": [("translation.gctransformer", "framework")],
+                     "marksweep": [("translation.gctransformer", "framework"),
+                                   ("translation.norweakarray", True)],
+                     "statistics": [("translation.gctransformer", "framework"),
+                                    ("translation.norweakarray", True)],
                      "generation": [("translation.gctransformer", "framework")],
                      "hybrid": [("translation.gctransformer", "framework")],
-                     "boehm": [("translation.gctransformer", "boehm")],
-                     "markcompact": [("translation.gctransformer", "framework")],
+                     "boehm": [("translation.gctransformer", "boehm"),
+                               ("translation.norweakarray", True)],
+                     "markcompact": [("translation.gctransformer", "framework"),
+                                     ("translation.norweakarray", True)],
                      },
                   cmdline="--gc"),
     ChoiceOption("gctransformer", "GC transformer that is used - internal",
@@ -91,8 +95,11 @@
                default=False, cmdline="--sandbox",
                requires=[("translation.thread", False)],
                suggests=[("translation.gc", "generation")]),
-    BoolOption("rweakref", "The backend supports RPython-level weakrefs",
-               default=True),
+    BoolOption("norweakref", "No support for RPython-level weakrefs",
+               default=False,
+               requires=[("translation.norweakarray", True)]),
+    BoolOption("norweakarray", "No support for RPython-level weak arrays",
+               default=False),
 
     # JIT generation: use -Ojit to enable it
     BoolOption("jit", "generate a JIT",

Added: pypy/branch/weakdict/pypy/doc/config/translation.norweakarray.txt
==============================================================================
--- (empty file)
+++ pypy/branch/weakdict/pypy/doc/config/translation.norweakarray.txt	Fri Sep  4 14:28:03 2009
@@ -0,0 +1,2 @@
+This indicates if the backend and GC policy support "weak arrays".
+These arrays are used by pypy.rlib.rweakref.RWeakValueDictionary.

Modified: pypy/branch/weakdict/pypy/jit/backend/llsupport/gc.py
==============================================================================
--- pypy/branch/weakdict/pypy/jit/backend/llsupport/gc.py	(original)
+++ pypy/branch/weakdict/pypy/jit/backend/llsupport/gc.py	Fri Sep  4 14:28:03 2009
@@ -343,7 +343,7 @@
             return llop1.do_malloc_varsize_clear(
                 llmemory.GCREF,
                 type_id, num_elem, self.array_basesize, itemsize,
-                self.array_length_ofs, True)
+                self.array_length_ofs, True, False)
         self.malloc_array = malloc_array
         self.GC_MALLOC_ARRAY = lltype.Ptr(lltype.FuncType(
             [lltype.Signed] * 3, llmemory.GCREF))
@@ -359,12 +359,12 @@
             return llop1.do_malloc_varsize_clear(
                 llmemory.GCREF,
                 str_type_id, length, str_basesize, str_itemsize,
-                str_ofs_length, True)
+                str_ofs_length, True, False)
         def malloc_unicode(length):
             return llop1.do_malloc_varsize_clear(
                 llmemory.GCREF,
                 unicode_type_id, length, unicode_basesize, unicode_itemsize,
-                unicode_ofs_length, True)
+                unicode_ofs_length, True, False)
         self.malloc_str = malloc_str
         self.malloc_unicode = malloc_unicode
         self.GC_MALLOC_STR_UNICODE = lltype.Ptr(lltype.FuncType(

Modified: pypy/branch/weakdict/pypy/jit/backend/llsupport/test/test_gc.py
==============================================================================
--- pypy/branch/weakdict/pypy/jit/backend/llsupport/test/test_gc.py	(original)
+++ pypy/branch/weakdict/pypy/jit/backend/llsupport/test/test_gc.py	Fri Sep  4 14:28:03 2009
@@ -124,8 +124,10 @@
         return p
 
     def do_malloc_varsize_clear(self, RESTYPE, type_id, length, size,
-                                itemsize, offset_to_length, can_collect):
+                                itemsize, offset_to_length, can_collect,
+                                contains_weakptr):
         assert can_collect
+        assert not contains_weakptr
         p = llmemory.raw_malloc(size + itemsize * length)
         (p + offset_to_length).signed[0] = length
         p = llmemory.cast_adr_to_ptr(p, RESTYPE)

Modified: pypy/branch/weakdict/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/weakdict/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/branch/weakdict/pypy/jit/metainterp/codewriter.py	Fri Sep  4 14:28:03 2009
@@ -737,6 +737,8 @@
         else:
             # XXX only strings or simple arrays for now
             ARRAY = op.args[0].value
+            assert isinstance(ARRAY, lltype.GcArray)
+            assert not isinstance(ARRAY.OF, lltype.Struct)
             arraydescr = self.cpu.arraydescrof(ARRAY)
             self.emit('new_array')
             self.emit(self.get_position(arraydescr))

Modified: pypy/branch/weakdict/pypy/jit/tl/targetpypyjit.py
==============================================================================
--- pypy/branch/weakdict/pypy/jit/tl/targetpypyjit.py	(original)
+++ pypy/branch/weakdict/pypy/jit/tl/targetpypyjit.py	Fri Sep  4 14:28:03 2009
@@ -39,7 +39,7 @@
 
 def handle_config(config, translateconfig):
     config.translation.backendopt.inline_threshold = 0   # XXX
-    config.translation.rweakref = False     # XXX
+    config.translation.norweakref = True     # XXX
     # set up the objspace optimizations based on the --opt argument
     from pypy.config.pypyoption import set_pypy_opt_level
     set_pypy_opt_level(config, translateconfig.opt)

Modified: pypy/branch/weakdict/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/branch/weakdict/pypy/objspace/std/typeobject.py	(original)
+++ pypy/branch/weakdict/pypy/objspace/std/typeobject.py	Fri Sep  4 14:28:03 2009
@@ -285,7 +285,7 @@
 
     def add_subclass(w_self, w_subclass):
         space = w_self.space
-        if not space.config.translation.rweakref:
+        if space.config.translation.norweakref:
             return    # no weakref support, don't keep track of subclasses
         import weakref
         assert isinstance(w_subclass, W_TypeObject)
@@ -300,7 +300,7 @@
 
     def remove_subclass(w_self, w_subclass):
         space = w_self.space
-        if not space.config.translation.rweakref:
+        if space.config.translation.norweakref:
             return    # no weakref support, don't keep track of subclasses
         for i in range(len(w_self.weak_subclasses)):
             ref = w_self.weak_subclasses[i]
@@ -310,7 +310,7 @@
 
     def get_subclasses(w_self):
         space = w_self.space
-        if not space.config.translation.rweakref:
+        if space.config.translation.norweakref:
             msg = ("this feature requires weakrefs, "
                    "which are not available in this build of PyPy")
             raise OperationError(space.w_RuntimeError,

Modified: pypy/branch/weakdict/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/weakdict/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/branch/weakdict/pypy/rpython/memory/gc/base.py	Fri Sep  4 14:28:03 2009
@@ -99,7 +99,6 @@
         contains_weakptr = self.weakpointer_offset(typeid) >= 0
         assert not (needs_finalizer and contains_weakptr)
         if self.is_varsize(typeid):
-            assert not contains_weakptr
             assert not needs_finalizer
             itemsize = self.varsize_item_sizes(typeid)
             offset_to_length = self.varsize_offset_to_length(typeid)
@@ -108,7 +107,7 @@
             else:
                 malloc_varsize = self.malloc_varsize
             ref = malloc_varsize(typeid, length, size, itemsize,
-                                 offset_to_length, True)
+                                 offset_to_length, True, contains_weakptr)
         else:
             if zero or not hasattr(self, 'malloc_fixedsize'):
                 malloc_fixedsize = self.malloc_fixedsize_clear

Modified: pypy/branch/weakdict/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/weakdict/pypy/rpython/memory/gc/generation.py	(original)
+++ pypy/branch/weakdict/pypy/rpython/memory/gc/generation.py	Fri Sep  4 14:28:03 2009
@@ -28,6 +28,7 @@
     old objects that contain pointers to young objects are recorded in
     a list.
     """
+    gcname = "generation"
     inline_simple_malloc = True
     inline_simple_malloc_varsize = True
     needs_write_barrier = True
@@ -160,7 +161,8 @@
         return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
 
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
-                             offset_to_length, can_collect):
+                             offset_to_length, can_collect,
+                             contains_weakptr):
         # Only use the nursery if there are not too many items.
         if not raw_malloc_usage(itemsize):
             too_many_items = False
@@ -179,7 +181,7 @@
             maxlength = maxlength_for_minimal_nursery << self.nursery_scale
             too_many_items = length > maxlength
 
-        if (not can_collect or
+        if (contains_weakptr or not can_collect or
             too_many_items or
             (raw_malloc_usage(size) > self.lb_young_var_basesize and
              raw_malloc_usage(size) > self.largest_young_var_basesize)):
@@ -189,7 +191,8 @@
             #     second comparison as well.
             return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size,
                                                     itemsize, offset_to_length,
-                                                    can_collect)
+                                                    can_collect,
+                                                    contains_weakptr)
         # with the above checks we know now that totalsize cannot be more
         # than about half of the nursery size; in particular, the + and *
         # cannot overflow

Modified: pypy/branch/weakdict/pypy/rpython/memory/gc/hybrid.py
==============================================================================
--- pypy/branch/weakdict/pypy/rpython/memory/gc/hybrid.py	(original)
+++ pypy/branch/weakdict/pypy/rpython/memory/gc/hybrid.py	Fri Sep  4 14:28:03 2009
@@ -78,6 +78,7 @@
     except that objects above a certain size are handled separately:
     they are allocated via raw_malloc/raw_free in a mark-n-sweep fashion.
     """
+    gcname = "hybrid"
     first_unused_gcflag = _gcflag_next_bit
     prebuilt_gc_objects_are_static_roots = True
     can_realloc = False
@@ -132,11 +133,12 @@
     # 'large'.
 
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
-                             offset_to_length, can_collect):
-        if not can_collect:
+                             offset_to_length, can_collect, contains_weakptr):
+        if contains_weakptr or not can_collect:
             return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size,
                                                     itemsize, offset_to_length,
-                                                    can_collect)
+                                                    can_collect,
+                                                    contains_weakptr)
         size_gc_header = self.gcheaderbuilder.size_gc_header
         nonvarsize = size_gc_header + size
 

Modified: pypy/branch/weakdict/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/branch/weakdict/pypy/rpython/memory/gc/markcompact.py	(original)
+++ pypy/branch/weakdict/pypy/rpython/memory/gc/markcompact.py	Fri Sep  4 14:28:03 2009
@@ -69,6 +69,7 @@
 BYTES_PER_TID = rffi.sizeof(TID_TYPE)
 
 class MarkCompactGC(MovingGCBase):
+    gcname = "markcompact"
     HDR = lltype.Struct('header', ('forward_ptr', llmemory.Address))
     TID_BACKUP = lltype.Array(TID_TYPE, hints={'nolength':True})
     WEAKREF_OFFSETS = lltype.Array(lltype.Signed)

Modified: pypy/branch/weakdict/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/branch/weakdict/pypy/rpython/memory/gc/marksweep.py	(original)
+++ pypy/branch/weakdict/pypy/rpython/memory/gc/marksweep.py	Fri Sep  4 14:28:03 2009
@@ -21,6 +21,7 @@
 
 memoryError = MemoryError()
 class MarkSweepGC(GCBase):
+    gcname = "marksweep"
     HDR = lltype.ForwardReference()
     HDRPTR = lltype.Ptr(HDR)
     # need to maintain a linked list of malloced objects, since we used the
@@ -151,7 +152,8 @@
     malloc_fixedsize_clear._dont_inline_ = True
 
     def malloc_varsize(self, typeid, length, size, itemsize, offset_to_length,
-                       can_collect):
+                       can_collect, contains_weakptr):
+        assert not contains_weakptr
         if can_collect:
             self.maybe_collect()
         size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -183,7 +185,8 @@
     malloc_varsize._dont_inline_ = True
 
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
-                             offset_to_length, can_collect):
+                             offset_to_length, can_collect, contains_weakptr):
+        assert not contains_weakptr
         if can_collect:
             self.maybe_collect()
         size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -293,7 +296,6 @@
             size = self.fixed_size(typeid)
             estimate = raw_malloc_usage(size_gc_header + size)
             if hdr.typeid & 1:
-                typeid = hdr.typeid >> 1
                 offset = self.weakpointer_offset(typeid)
                 hdr.typeid = hdr.typeid & (~1)
                 gc_info = llmemory.cast_ptr_to_adr(hdr)
@@ -687,6 +689,7 @@
 
 class PrintingMarkSweepGC(MarkSweepGC):
     _alloc_flavor_ = "raw"
+    gcname = "statistics"
     COLLECT_EVERY = 2000
 
     def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE, start_heap_size=4096):

Modified: pypy/branch/weakdict/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/weakdict/pypy/rpython/memory/gc/semispace.py	(original)
+++ pypy/branch/weakdict/pypy/rpython/memory/gc/semispace.py	Fri Sep  4 14:28:03 2009
@@ -25,6 +25,7 @@
 
 class SemiSpaceGC(MovingGCBase):
     _alloc_flavor_ = "raw"
+    gcname = "semispace"
     inline_simple_malloc = True
     inline_simple_malloc_varsize = True
     malloc_zero_filled = True
@@ -83,7 +84,8 @@
         return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
 
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
-                             offset_to_length, can_collect):
+                             offset_to_length, can_collect,
+                             contains_weakptr=False):
         size_gc_header = self.gcheaderbuilder.size_gc_header
         nonvarsize = size_gc_header + size
         try:
@@ -100,6 +102,8 @@
         self.init_gc_object(result, typeid)
         (result + size_gc_header + offset_to_length).signed[0] = length
         self.free = result + llarena.round_up_for_allocation(totalsize)
+        if contains_weakptr:
+            self.objects_with_weakrefs.append(result + size_gc_header)
         return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
 
     def obtain_free_space(self, needed):
@@ -516,18 +520,45 @@
             if not self.surviving(obj):
                 continue # weakref itself dies
             obj = self.get_forwarding_address(obj)
-            offset = self.weakpointer_offset(self.get_type_id(obj))
-            pointing_to = (obj + offset).address[0]
-            # XXX I think that pointing_to cannot be NULL here
+            tid = self.get_type_id(obj)
+            offset = self.weakpointer_offset(tid)
+            if self.is_varsize(tid):
+                self.invalidate_weakarray(obj, tid, offset)
+                new_with_weakref.append(obj)
+            else:
+                # a weakref object, with a single weak pointer
+                pointing_to = (obj + offset).address[0]
+                # XXX I think that pointing_to cannot be NULL here
+                if pointing_to:
+                    if self.surviving(pointing_to):
+                        (obj + offset).address[0] = \
+                             self.get_forwarding_address(pointing_to)
+                        new_with_weakref.append(obj)
+                    else:
+                        (obj + offset).address[0] = NULL
+        self.objects_with_weakrefs.delete()
+        self.objects_with_weakrefs = new_with_weakref
+
+    def invalidate_weakarray(self, obj, typeid, weakoffset):
+        # a weakarray: walk over all entries
+        item = obj + self.varsize_offset_to_variable_part(typeid)
+        length = (obj + self.varsize_offset_to_length(typeid)).signed[0]
+        offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
+        itemlength = self.varsize_item_sizes(typeid)
+        while length > 0:
+            pointing_to = (item + weakoffset).address[0]
             if pointing_to:
                 if self.surviving(pointing_to):
-                    (obj + offset).address[0] = self.get_forwarding_address(
-                        pointing_to)
-                    new_with_weakref.append(obj)
+                    (item + weakoffset).address[0] = \
+                          self.get_forwarding_address(pointing_to)
                 else:
-                    (obj + offset).address[0] = NULL
-        self.objects_with_weakrefs.delete()
-        self.objects_with_weakrefs = new_with_weakref
+                    (item + weakoffset).address[0] = NULL
+                    j = 0
+                    while j < len(offsets):
+                        (item + offsets[j]).address[0] = NULL
+                        j += 1
+            item += itemlength
+            length -= 1
 
     def update_run_finalizers(self):
         # we are in an inner collection, caused by a finalizer

Modified: pypy/branch/weakdict/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/weakdict/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/branch/weakdict/pypy/rpython/memory/gctransform/framework.py	Fri Sep  4 14:28:03 2009
@@ -621,12 +621,12 @@
         # used by the JIT (see pypy.jit.backend.llsupport.gc)
         op = hop.spaceop
         [v_typeid, v_length, v_size, v_itemsize,
-         v_offset_to_length, v_can_collect] = op.args
+         v_offset_to_length, v_can_collect, v_contains_weakptr] = op.args
         livevars = self.push_roots(hop)
         hop.genop("direct_call",
                   [self.malloc_varsize_clear_ptr, self.c_const_gc,
                    v_typeid, v_length, v_size, v_itemsize,
-                   v_offset_to_length, v_can_collect],
+                   v_offset_to_length, v_can_collect, v_contains_weakptr],
                   resultvar=op.result)
         self.pop_roots(hop, livevars)
 

Modified: pypy/branch/weakdict/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/weakdict/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/branch/weakdict/pypy/rpython/memory/test/test_gc.py	Fri Sep  4 14:28:03 2009
@@ -33,6 +33,13 @@
     def teardown_class(cls):
         py.log._setstate(cls._saved_logstate)
 
+    def get_config(self):
+        from pypy.config.translationoption import \
+               get_combined_translation_config
+        config = get_combined_translation_config()
+        config.translation.gc = self.GCClass.gcname
+        return config
+
     def interpret(self, func, values, **kwds):
         interp, graph = get_interpreter(func, values, **kwds)
         gcwrapper.prepare_graphs_and_create_gc(interp, self.GCClass,
@@ -262,6 +269,47 @@
         res = self.interpret(f, [])
         assert res
 
+    def test_weakarray(self):
+        if self.get_config().translation.norweakarray:
+            py.test.skip("no weak arrays on this GC")
+        OBJ = lltype.GcStruct('OBJ', ('x', lltype.Signed))
+        prebuilt_obj = lltype.malloc(OBJ, zero=True)
+        S = lltype.Struct('S', ('foo', lltype.Ptr(OBJ)),
+                               ('bar', lltype.Ptr(OBJ)))
+        A = lltype.GcArray(S, hints={'weakarray': 'bar'})
+        #
+        def set(d, n):
+            obj1 = lltype.malloc(OBJ, zero=True)
+            obj2 = lltype.malloc(OBJ, zero=True)
+            d[n].foo = obj1
+            d[n].bar = obj2
+            return obj1, obj2
+        def g(d):
+            key1, value1 = set(d, 1)
+            key2, value2 = set(d, 2)
+            key3, value3 = set(d, 3)
+            return key1, value1, key3, value3       # key2, value2 dropped
+        def f():
+            d = lltype.malloc(A, 4)
+            i = 0
+            while i < 4:
+                d[i].foo = prebuilt_obj
+                d[i].bar = lltype.nullptr(OBJ)
+                i += 1
+            key1, value1, key3, value3 = g(d)
+            llop.gc__collect(lltype.Void)
+            llop.gc__collect(lltype.Void)
+            return (((d[0].foo == prebuilt_obj) << 0) +
+                    ((not d[0].bar)             << 1) +
+                    ((d[1].foo == key1)         << 2) +
+                    ((d[1].bar == value1)       << 3) +
+                    ((not d[2].foo)             << 4) +   #  \  removed by
+                    ((not d[2].bar)             << 5) +   #  /  gc.collect
+                    ((d[3].foo == key3)         << 6) +
+                    ((d[3].bar == value3)       << 7))
+        res = self.interpret(f, [])
+        assert res == 255
+
     def test_weakvaluedict(self):
         py.test.skip("in-progress")
         from pypy.rlib.rweakref import RWeakValueDictionary

Modified: pypy/branch/weakdict/pypy/rpython/rweakref.py
==============================================================================
--- pypy/branch/weakdict/pypy/rpython/rweakref.py	(original)
+++ pypy/branch/weakdict/pypy/rpython/rweakref.py	Fri Sep  4 14:28:03 2009
@@ -24,7 +24,7 @@
 
     def __init__(self, rtyper):
         self.rtyper = rtyper
-        if not rtyper.getconfig().translation.rweakref:
+        if rtyper.getconfig().translation.norweakref:
             raise TyperError("RPython-level weakrefs are not supported by "
                              "this backend or GC policy")
 

Modified: pypy/branch/weakdict/pypy/translator/goal/targetpreimportedpypy.py
==============================================================================
--- pypy/branch/weakdict/pypy/translator/goal/targetpreimportedpypy.py	(original)
+++ pypy/branch/weakdict/pypy/translator/goal/targetpreimportedpypy.py	Fri Sep  4 14:28:03 2009
@@ -181,7 +181,7 @@
                                           "to translate.py instead of "
                                           "--withmod-_stackless directly")
 
-        if not config.translation.rweakref:
+        if config.translation.norweakref:
             config.objspace.usemodules._weakref = False
 
         if self.translateconfig.goal_options.jit:

Modified: pypy/branch/weakdict/pypy/translator/goal/targetpypystandalone.py
==============================================================================
--- pypy/branch/weakdict/pypy/translator/goal/targetpypystandalone.py	(original)
+++ pypy/branch/weakdict/pypy/translator/goal/targetpypystandalone.py	Fri Sep  4 14:28:03 2009
@@ -172,7 +172,7 @@
                                           "to translate.py instead of "
                                           "--withmod-_stackless directly")
 
-        if not config.translation.rweakref:
+        if config.translation.norweakref:
             config.objspace.usemodules._weakref = False
 
         if config.translation.jit:



More information about the Pypy-commit mailing list