Armin Rigo avatar Armin Rigo committed 8ab8c0e

In-progress: import existing tests for using them with 'gcrootfinder=scan'.

Comments (0)

Files changed (6)

pypy/rpython/memory/gc/minimark.py

         self.nursery          = NULL
         self.nursery_next     = NULL
         self.nursery_frag_end = NULL
+        self.nursery_top      = NULL
         self.debug_tiny_nursery = -1
         self.debug_rotating_nurseries = None
         #
+        self.gcrootfinder_scan = (config.gcrootfinder == "scan")
+        #
         # The ArenaCollection() handles the nonmovable objects allocation.
         if ArenaCollectionClass is None:
             ArenaCollectionClass = minimarkpage.ArenaCollection
         # the current position in the nursery:
         self.nursery_next = self.nursery
         # the end of the nursery:
-        self.nursery_frag_end = self.nursery + self.nursery_size
+        self.nursery_top = self.nursery + self.nursery_size
+        self.nursery_frag_end = self.nursery_top
         # initialize the threshold
         self.min_heap_size = max(self.min_heap_size, self.nursery_size *
                                               self.major_collection_threshold)
             #
             # Get the memory from the nursery.  If there is not enough space
             # there, do a collect first.
-            result = self.nursery_free
-            self.nursery_free = result + totalsize
-            if self.nursery_free > self.nursery_top:
-                result = self.collect_and_reserve(totalsize)
+            result = self.nursery_next
+            self.nursery_next = result + totalsize
+            if self.nursery_next > self.nursery_frag_end:
+                result = self.pick_next_fragment(totalsize)
             #
             # Build the object.
             llarena.arena_reserve(result, totalsize)
         if gen > 0:
             self.major_collection()
 
+    def pick_next_fragment(self, totalsize):
+        """To call when nursery_next overflows nursery_frag_end.
+        Pick the next fragment of the nursery, or if there are none
+        big enough for 'totalsize', do a collection.
+        """
+        # XXX
+        return self.collect_and_reserve(totalsize)
+    pick_next_fragment._dont_inline_ = True
+
     def collect_and_reserve(self, totalsize):
-        """To call when nursery_free overflows nursery_top.
+        """To call when we have run out of nursery fragments.
         Do a minor collection, and possibly also a major collection,
         and finally reserve 'totalsize' bytes at the start of the
         now-empty nursery.
                 self.nursery_free = self.nursery_top - self.debug_tiny_nursery
         #
         return result
-    collect_and_reserve._dont_inline_ = True
 
 
     def external_malloc(self, typeid, length, can_make_young=True):
         if self.next_major_collection_threshold < 0:
             # cannot trigger a full collection now, but we can ensure
             # that one will occur very soon
+            xxx
             self.nursery_free = self.nursery_top
 
     def can_malloc_nonmovable(self):
         # have been chosen to allow 'flags' to be zero in the common
         # case (hence the 'NO' in their name).
         hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR))
-        hdr.tid = self.combine(typeid16, flags | GCFLAG_HIGH)
+        if self.gcrootfinder_scan:   # don't bother setting these high
+            flags |= GCFLAG_HIGH     # bits if not "scan"
+        hdr.tid = self.combine(typeid16, flags)
 
     def init_gc_object_immortal(self, addr, typeid16, flags=0):
         # For prebuilt GC objects, the flags must contain
         if result:
             ll_assert(tid == -42, "bogus header for young obj")
         else:
-            ll_assert(bool(tid), "bogus header (1)")
-            ll_assert(tid & ~TID_MASK == 0, "bogus header (2)")
+            htid = llop.extract_ushort(llgroup.HALFWORD, tid)
+            ll_assert(bool(htid), "bogus header (1)")
+            if self.gcrootfinder_scan:
+                expected = GCFLAG_HIGH
+            else:
+                expected = 0
+            ll_assert(tid & GCFLAG_HIGH_MASK == expected, "bogus header (2)")
         return result
 
     def get_forwarding_address(self, obj):
         # the whole nursery with zero and reset the current nursery pointer.
         llarena.arena_reset(self.nursery, self.nursery_size, 2)
         self.debug_rotate_nursery()
+        xxx
         self.nursery_free = self.nursery
         #
         debug_print("minor collect, total memory used:",

pypy/rpython/memory/gcwrapper.py

                 if self.gcheap.gc.points_to_valid_gc_object(addrofaddr):
                     collect_static_in_prebuilt_nongc(gc, addrofaddr)
         if collect_stack_root:
+            translator = gcheap.llinterp.typer.annotator.translator
+            assert translator.config.translation.gcrootfinder != 'scan'
             for addrofaddr in gcheap.llinterp.find_roots():
                 if self.gcheap.gc.points_to_valid_gc_object(addrofaddr):
                     collect_stack_root(gc, addrofaddr)

pypy/rpython/memory/test/test_gc.py

 
 class GCTest(object):
     GC_PARAMS = {}
+    CONFIG_OPTS = {}
     GC_CAN_MOVE = False
     GC_CAN_MALLOC_NONMOVABLE = True
     GC_CAN_SHRINK_ARRAY = False
         py.log._setstate(cls._saved_logstate)
 
     def interpret(self, func, values, **kwds):
+        kwds.update(self.CONFIG_OPTS)
         interp, graph = get_interpreter(func, values, **kwds)
         gcwrapper.prepare_graphs_and_create_gc(interp, self.GCClass,
                                                self.GC_PARAMS)
 
 class TestMiniMarkGCCardMarking(TestMiniMarkGC):
     GC_PARAMS = {'card_page_indices': 4}
+
+class TestMiniMarkGCScan(TestMiniMarkGC):
+    CONFIG_OPTS = {'gcrootfinder': 'scan'}

pypy/translator/c/gc.py

      typeOf, Ptr, ContainerType, RttiStruct, \
      RuntimeTypeInfo, getRuntimeTypeInfo, top_container
 from pypy.rpython.memory.gctransform import \
-     refcounting, boehm, framework, asmgcroot
+     refcounting, boehm, framework, asmgcroot, scan
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
     def OP_GC_STACK_BOTTOM(self, funcgen, op):
         return 'pypy_asm_stack_bottom();'
 
+class ScanFrameworkGcPolicy(FrameworkGcPolicy):
+    transformerclass = scan.ScanFrameworkGCTransformer
+
+    def GC_KEEPALIVE(self, funcgen, v):
+        return 'pypy_asm_keepalive(%s);' % funcgen.expr(v)
+
 
 name_to_gcpolicy = {
     'boehm': BoehmGcPolicy,
     'none': NoneGcPolicy,
     'framework': FrameworkGcPolicy,
     'framework+asmgcroot': AsmGcRootFrameworkGcPolicy,
+    'framework+scan': ScanFrameworkGcPolicy,
 }
-
-

pypy/translator/c/genc.py

             name = self.config.translation.gctransformer
             if self.config.translation.gcrootfinder == "asmgcc":
                 name = "%s+asmgcroot" % (name,)
+            if self.config.translation.gcrootfinder == "scan":
+                name = "%s+scan" % (name,)
             return gc.name_to_gcpolicy[name]
         return self.gcpolicy
 

pypy/translator/c/test/test_newgc.py

 
 class TestUsingFramework(object):
     gcpolicy = "marksweep"
+    gcrootfinder = "shadowstack"
     should_be_moving = False
     removetypeptr = False
     taggedpointers = False
         t = Translation(main, standalone=True, gc=cls.gcpolicy,
                         policy=annpolicy.StrictAnnotatorPolicy(),
                         taggedpointers=cls.taggedpointers,
-                        gcremovetypeptr=cls.removetypeptr)
+                        gcremovetypeptr=cls.removetypeptr,
+                        gcrootfinder=cls.gcrootfinder)
         t.disable(['backendopt'])
         t.set_backend_extra_options(c_debug_defines=True)
         t.rtype()
 
 class TestMiniMarkGCMostCompact(TaggedPointersTest, TestMiniMarkGC):
     removetypeptr = True
+
+class TestMiniMarkGCScan(TestMiniMarkGC):
+    gcrootfinder = "scan"
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.