Author: Armin Rigo <ar...@tunes.org> Branch: miniscan Changeset: r52978:8ab8c0ea5f42 Date: 2012-02-28 14:51 +0100 http://bitbucket.org/pypy/pypy/changeset/8ab8c0ea5f42/
Log: In-progress: import existing tests for using them with 'gcrootfinder=scan'. diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py --- a/pypy/rpython/memory/gc/minimark.py +++ b/pypy/rpython/memory/gc/minimark.py @@ -251,9 +251,12 @@ 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 @@ -396,7 +399,8 @@ # 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) @@ -559,10 +563,10 @@ # # 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) @@ -581,8 +585,17 @@ 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. @@ -607,7 +620,6 @@ 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): @@ -753,6 +765,7 @@ 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): @@ -822,7 +835,9 @@ # 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 @@ -876,8 +891,13 @@ 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): @@ -1294,6 +1314,7 @@ # 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:", diff --git a/pypy/rpython/memory/gcwrapper.py b/pypy/rpython/memory/gcwrapper.py --- a/pypy/rpython/memory/gcwrapper.py +++ b/pypy/rpython/memory/gcwrapper.py @@ -177,6 +177,8 @@ 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) diff --git a/pypy/rpython/memory/test/test_gc.py b/pypy/rpython/memory/test/test_gc.py --- a/pypy/rpython/memory/test/test_gc.py +++ b/pypy/rpython/memory/test/test_gc.py @@ -24,6 +24,7 @@ class GCTest(object): GC_PARAMS = {} + CONFIG_OPTS = {} GC_CAN_MOVE = False GC_CAN_MALLOC_NONMOVABLE = True GC_CAN_SHRINK_ARRAY = False @@ -40,6 +41,7 @@ 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) @@ -921,3 +923,6 @@ class TestMiniMarkGCCardMarking(TestMiniMarkGC): GC_PARAMS = {'card_page_indices': 4} + +class TestMiniMarkGCScan(TestMiniMarkGC): + CONFIG_OPTS = {'gcrootfinder': 'scan'} diff --git a/pypy/translator/c/gc.py b/pypy/translator/c/gc.py --- a/pypy/translator/c/gc.py +++ b/pypy/translator/c/gc.py @@ -6,7 +6,7 @@ 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 @@ -403,6 +403,12 @@ 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, @@ -410,6 +416,5 @@ 'none': NoneGcPolicy, 'framework': FrameworkGcPolicy, 'framework+asmgcroot': AsmGcRootFrameworkGcPolicy, + 'framework+scan': ScanFrameworkGcPolicy, } - - diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py --- a/pypy/translator/c/genc.py +++ b/pypy/translator/c/genc.py @@ -193,6 +193,8 @@ 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 diff --git a/pypy/translator/c/test/test_newgc.py b/pypy/translator/c/test/test_newgc.py --- a/pypy/translator/c/test/test_newgc.py +++ b/pypy/translator/c/test/test_newgc.py @@ -15,6 +15,7 @@ class TestUsingFramework(object): gcpolicy = "marksweep" + gcrootfinder = "shadowstack" should_be_moving = False removetypeptr = False taggedpointers = False @@ -41,7 +42,8 @@ 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() @@ -1600,3 +1602,6 @@ class TestMiniMarkGCMostCompact(TaggedPointersTest, TestMiniMarkGC): removetypeptr = True + +class TestMiniMarkGCScan(TestMiniMarkGC): + gcrootfinder = "scan" _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit