[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