[pypy-commit] pypy stm-gc: malloc_fixedsize_clear(). Use a simple scheme to use the same

arigo noreply at buildbot.pypy.org
Thu Feb 2 16:46:38 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r52032:5e10a34f2e55
Date: 2012-02-01 18:02 +0100
http://bitbucket.org/pypy/pypy/changeset/5e10a34f2e55/

Log:	malloc_fixedsize_clear(). Use a simple scheme to use the same code
	for both transactional and non-transactional modes.

diff --git a/pypy/rpython/memory/gc/stmgc.py b/pypy/rpython/memory/gc/stmgc.py
--- a/pypy/rpython/memory/gc/stmgc.py
+++ b/pypy/rpython/memory/gc/stmgc.py
@@ -1,4 +1,6 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena
+from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
 from pypy.rpython.memory.gc.base import GCBase
 from pypy.rlib.rarithmetic import LONG_BIT
 
@@ -41,7 +43,8 @@
     GCTLS = lltype.Struct('GCTLS', ('nursery_free', llmemory.Address),
                                    ('nursery_top', llmemory.Address),
                                    ('nursery_start', llmemory.Address),
-                                   ('nursery_size', lltype.Signed))
+                                   ('nursery_size', lltype.Signed),
+                                   ('malloc_flags', lltype.Signed))
 
 
     def __init__(self, config, stm_operations,
@@ -55,7 +58,7 @@
     def setup(self):
         """Called at run-time to initialize the GC."""
         GCBase.setup(self)
-        self.setup_thread()
+        self.main_thread_tls = self.setup_thread(True)
 
     def _alloc_nursery(self):
         nursery = llarena.arena_malloc(self.max_nursery_size, 1)
@@ -63,22 +66,43 @@
             raise MemoryError("cannot allocate nursery")
         return nursery
 
-    def setup_thread(self):
+    def _free_nursery(self, nursery):
+        llarena.arena_free(nursery)
+
+    def setup_thread(self, in_main_thread):
         tls = lltype.malloc(self.GCTLS, flavor='raw')
         self.stm_operations.set_tls(llmemory.cast_ptr_to_adr(tls))
         tls.nursery_start = self._alloc_nursery()
         tls.nursery_size  = self.max_nursery_size
         tls.nursery_free  = tls.nursery_start
         tls.nursery_top   = tls.nursery_start + tls.nursery_size
+        #
+        # XXX for now, we use as the "global area" the nursery of the
+        # main thread.  So allocation in the main thread is the same as
+        # allocation in another thread, except that the new objects
+        # should be immediately marked as GCFLAG_GLOBAL.
+        if in_main_thread:
+            tls.malloc_flags = GCFLAG_GLOBAL
+        else:
+            tls.malloc_flags = 0
+        return tls
+
+    def teardown_thread(self):
+        tls = self.get_tls()
+        self.stm_operations.set_tls(NULL)
+        self._free_nursery(tls.nursery_start)
+        lltype.free(tls, flavor='raw')
 
     @always_inline
     def get_tls(self):
         tls = self.stm_operations.get_tls()
         return llmemory.cast_adr_to_ptr(tls, lltype.Ptr(self.GCTLS))
 
+    def allocate_bump_pointer(self, size):
+        return self._allocate_bump_pointer(self.get_tls(), size)
+
     @always_inline
-    def allocate_bump_pointer(self, size):
-        tls = self.get_tls()
+    def _allocate_bump_pointer(self, tls, size):
         free = tls.nursery_free
         top  = tls.nursery_top
         new  = free + size
@@ -90,3 +114,39 @@
     @dont_inline
     def local_collection(self, oldfree):
         raise MemoryError("nursery exhausted")   # XXX for now
+
+
+    def malloc_fixedsize_clear(self, typeid, size,
+                               needs_finalizer=False,
+                               is_finalizer_light=False,
+                               contains_weakptr=False):
+        assert not needs_finalizer, "XXX"
+        assert not contains_weakptr, "XXX"
+        #
+        # Check the mode: either in a transactional thread, or in
+        # the main thread.  For now we do the same thing in both
+        # modes, but set different flags.
+        tls = self.get_tls()
+        flags = tls.malloc_flags
+        #
+        # Get the memory from the nursery.
+        size_gc_header = self.gcheaderbuilder.size_gc_header
+        totalsize = size_gc_header + size
+        result = self._allocate_bump_pointer(tls, totalsize)
+        #
+        # Build the object.
+        llarena.arena_reserve(result, totalsize)
+        obj = result + size_gc_header
+        self.init_gc_object(result, typeid, flags=flags)
+        #
+        return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
+
+
+    @always_inline
+    def combine(self, typeid16, flags):
+        return llop.combine_ushort(lltype.Signed, typeid16, flags)
+
+    @always_inline
+    def init_gc_object(self, addr, typeid16, flags=0):
+        hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR))
+        hdr.tid = self.combine(typeid16, flags)
diff --git a/pypy/rpython/memory/gc/test/test_stmgc.py b/pypy/rpython/memory/gc/test/test_stmgc.py
--- a/pypy/rpython/memory/gc/test/test_stmgc.py
+++ b/pypy/rpython/memory/gc/test/test_stmgc.py
@@ -1,5 +1,6 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.memory.gc.stmgc import StmGC
+from pypy.rpython.memory.gc.stmgc import GCFLAG_GLOBAL
 
 
 class FakeStmOperations:
@@ -33,3 +34,24 @@
         assert a4 - a3 == 3
         assert a5 - a4 == 4
         assert a6 - a5 == 5
+
+    def test_malloc_fixedsize_clear(self):
+        S = lltype.GcStruct('S', ('a', lltype.Signed), ('b', lltype.Signed))
+        gcref = self.gc.malloc_fixedsize_clear(123, llmemory.sizeof(S))
+        s = lltype.cast_opaque_ptr(lltype.Ptr(S), gcref)
+        assert s.a == 0
+        assert s.b == 0
+        gcref2 = self.gc.malloc_fixedsize_clear(123, llmemory.sizeof(S))
+        assert gcref2 != gcref
+
+    def test_malloc_main_vs_thread(self):
+        S = lltype.GcStruct('S', ('a', lltype.Signed), ('b', lltype.Signed))
+        gcref = self.gc.malloc_fixedsize_clear(123, llmemory.sizeof(S))
+        obj = llmemory.cast_ptr_to_adr(gcref)
+        assert (self.gc.header(obj).tid & GCFLAG_GLOBAL) != 0
+        #
+        self.gc.setup_thread(False)
+        gcref = self.gc.malloc_fixedsize_clear(123, llmemory.sizeof(S))
+        obj = llmemory.cast_ptr_to_adr(gcref)
+        assert (self.gc.header(obj).tid & GCFLAG_GLOBAL) == 0
+        self.gc.teardown_thread()


More information about the pypy-commit mailing list