[pypy-commit] pypy stm-gc: In-progress.

arigo noreply at buildbot.pypy.org
Tue Feb 7 16:53:10 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r52186:99247048a1de
Date: 2012-02-07 16:11 +0100
http://bitbucket.org/pypy/pypy/changeset/99247048a1de/

Log:	In-progress.

diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -75,7 +75,7 @@
                      "markcompact": [("translation.gctransformer", "framework")],
                      "minimark": [("translation.gctransformer", "framework")],
                      "stmgc": [("translation.gctransformer", "framework"),
-                               ("translation.gcrootfinder", "none")],   # XXX
+                               ("translation.gcrootfinder", "stm")],
                      },
                   cmdline="--gc"),
     ChoiceOption("gctransformer", "GC transformer that is used - internal",
@@ -93,7 +93,7 @@
                default=IS_64_BITS, cmdline="--gcremovetypeptr"),
     ChoiceOption("gcrootfinder",
                  "Strategy for finding GC Roots (framework GCs only)",
-                 ["n/a", "shadowstack", "asmgcc", "none"],
+                 ["n/a", "shadowstack", "asmgcc", "stm"],
                  "shadowstack",
                  cmdline="--gcrootfinder",
                  requires={
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,4 @@
-from pypy.rpython.lltypesystem import lltype, llmemory, llarena, rffi
+from pypy.rpython.lltypesystem import lltype, llmemory, llarena, llgroup, rffi
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
 from pypy.rpython.memory.gc.base import GCBase
@@ -34,6 +34,7 @@
     _alloc_flavor_ = "raw"
     inline_simple_malloc = True
     inline_simple_malloc_varsize = True
+    needs_custom_readers = "stm"
     needs_write_barrier = "stm"
     prebuilt_gc_objects_are_static_roots = False
     malloc_zero_filled = True    # xxx?
@@ -80,12 +81,13 @@
             self.declare_reader(size, TYPE)
         self.declare_write_barrier()
 
+    GETSIZE = lltype.Ptr(lltype.FuncType([llmemory.Address],lltype.Signed))
+
     def setup(self):
         """Called at run-time to initialize the GC."""
         GCBase.setup(self)
-        GETSIZE = lltype.Ptr(lltype.FuncType([llmemory.Address],lltype.Signed))
         self.stm_operations.setup_size_getter(
-                llhelper(GETSIZE, self._getsize_fn))
+                llhelper(self.GETSIZE, self._getsize_fn))
         self.main_thread_tls = self.setup_thread(True)
         self.mutex_lock = ll_thread.allocate_ll_lock()
 
@@ -201,6 +203,11 @@
 
 
     @always_inline
+    def get_type_id(self, obj):
+        tid = self.header(obj).tid
+        return llop.extract_ushort(llgroup.HALFWORD, tid)
+
+    @always_inline
     def combine(self, typeid16, flags):
         return llop.combine_ushort(lltype.Signed, typeid16, flags)
 
@@ -314,6 +321,11 @@
 
     # ----------
 
+    def identityhash(self, gcref):
+        raise NotImplementedError("XXX")
+
+    # ----------
+
     def acquire(self, lock):
         ll_thread.c_thread_acquirelock(lock, 1)
 
diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py
--- a/pypy/rpython/memory/gctransform/framework.py
+++ b/pypy/rpython/memory/gctransform/framework.py
@@ -313,14 +313,6 @@
                 [s_gc, annmodel.SomeInteger(knowntype=llgroup.r_halfword)],
                 annmodel.SomeInteger())
 
-        if hasattr(GCClass, 'writebarrier_before_copy'):
-            self.wb_before_copy_ptr = \
-                    getfn(GCClass.writebarrier_before_copy.im_func,
-                    [s_gc] + [annmodel.SomeAddress()] * 2 +
-                    [annmodel.SomeInteger()] * 3, annmodel.SomeBool())
-        elif GCClass.needs_write_barrier:
-            raise NotImplementedError("GC needs write barrier, but does not provide writebarrier_before_copy functionality")
-
         # in some GCs we can inline the common case of
         # malloc_fixedsize(typeid, size, False, False, False)
         if getattr(GCClass, 'inline_simple_malloc', False):
@@ -447,43 +439,8 @@
                                             annmodel.SomeInteger(nonneg=True)],
                                            annmodel.s_None)
 
-        self.write_barrier_ptr = None
-        self.write_barrier_from_array_ptr = None
-        if GCClass.needs_write_barrier:
-            self.write_barrier_ptr = getfn(GCClass.write_barrier.im_func,
-                                           [s_gc,
-                                            annmodel.SomeAddress(),
-                                            annmodel.SomeAddress()],
-                                           annmodel.s_None,
-                                           inline=True)
-            func = getattr(gcdata.gc, 'remember_young_pointer', None)
-            if func is not None:
-                # func should not be a bound method, but a real function
-                assert isinstance(func, types.FunctionType)
-                self.write_barrier_failing_case_ptr = getfn(func,
-                                               [annmodel.SomeAddress(),
-                                                annmodel.SomeAddress()],
-                                               annmodel.s_None)
-            func = getattr(GCClass, 'write_barrier_from_array', None)
-            if func is not None:
-                self.write_barrier_from_array_ptr = getfn(func.im_func,
-                                           [s_gc,
-                                            annmodel.SomeAddress(),
-                                            annmodel.SomeAddress(),
-                                            annmodel.SomeInteger()],
-                                           annmodel.s_None,
-                                           inline=True)
-                func = getattr(gcdata.gc, 'remember_young_pointer_from_array3',
-                               None)
-                if func is not None:
-                    # func should not be a bound method, but a real function
-                    assert isinstance(func, types.FunctionType)
-                    self.write_barrier_from_array_failing_case_ptr = \
-                                             getfn(func,
-                                                   [annmodel.SomeAddress(),
-                                                    annmodel.SomeInteger(),
-                                                    annmodel.SomeAddress()],
-                                                   annmodel.s_None)
+        self.setup_write_barriers(GCClass, s_gc)
+
         self.statistics_ptr = getfn(GCClass.statistics.im_func,
                                     [s_gc, annmodel.SomeInteger()],
                                     annmodel.SomeInteger())
@@ -525,6 +482,53 @@
         from pypy.rpython.memory.gctransform import shadowstack
         return shadowstack.ShadowStackRootWalker(self)
 
+    def setup_write_barriers(self, GCClass, s_gc):
+        self.write_barrier_ptr = None
+        self.write_barrier_from_array_ptr = None
+        if GCClass.needs_write_barrier:
+            self.write_barrier_ptr = getfn(GCClass.write_barrier.im_func,
+                                           [s_gc,
+                                            annmodel.SomeAddress(),
+                                            annmodel.SomeAddress()],
+                                           annmodel.s_None,
+                                           inline=True)
+            func = getattr(gcdata.gc, 'remember_young_pointer', None)
+            if func is not None:
+                # func should not be a bound method, but a real function
+                assert isinstance(func, types.FunctionType)
+                self.write_barrier_failing_case_ptr = getfn(func,
+                                               [annmodel.SomeAddress(),
+                                                annmodel.SomeAddress()],
+                                               annmodel.s_None)
+            func = getattr(GCClass, 'write_barrier_from_array', None)
+            if func is not None:
+                self.write_barrier_from_array_ptr = getfn(func.im_func,
+                                           [s_gc,
+                                            annmodel.SomeAddress(),
+                                            annmodel.SomeAddress(),
+                                            annmodel.SomeInteger()],
+                                           annmodel.s_None,
+                                           inline=True)
+                func = getattr(gcdata.gc, 'remember_young_pointer_from_array3',
+                               None)
+                if func is not None:
+                    # func should not be a bound method, but a real function
+                    assert isinstance(func, types.FunctionType)
+                    self.write_barrier_from_array_failing_case_ptr = \
+                                             getfn(func,
+                                                   [annmodel.SomeAddress(),
+                                                    annmodel.SomeInteger(),
+                                                    annmodel.SomeAddress()],
+                                                   annmodel.s_None)
+        if hasattr(GCClass, 'writebarrier_before_copy'):
+            self.wb_before_copy_ptr = \
+                    getfn(GCClass.writebarrier_before_copy.im_func,
+                    [s_gc] + [annmodel.SomeAddress()] * 2 +
+                    [annmodel.SomeInteger()] * 3, annmodel.SomeBool())
+        elif GCClass.needs_write_barrier:
+            raise NotImplementedError("GC needs write barrier, but does not provide writebarrier_before_copy functionality")
+
+
     def consider_constant(self, TYPE, value):
         self.layoutbuilder.consider_constant(TYPE, value, self.gcdata.gc)
 
diff --git a/pypy/rpython/memory/gctransform/stmframework.py b/pypy/rpython/memory/gctransform/stmframework.py
new file mode 100644
--- /dev/null
+++ b/pypy/rpython/memory/gctransform/stmframework.py
@@ -0,0 +1,22 @@
+from pypy.rpython.memory.gctransform.framework import FrameworkGCTransformer
+from pypy.translator.backendopt.support import var_needsgc
+
+
+class StmFrameworkGCTransformer(FrameworkGCTransformer):
+
+    def setup_write_barriers(self, GCClass, s_gc):
+        self.write_barrier_ptr = None
+        self.write_barrier_from_array_ptr = None
+        pass  # xxx
+
+    def gct_getfield(self, hop):
+        if self.var_needs_set_transform(hop.spaceop.args[0]):
+            hop.rename('stm_' + hop.spaceop.opname)
+        else:
+            self.default(hop)
+    gct_getarrayitem = gct_getfield
+    gct_getinteriorfield = gct_getfield
+
+
+    def gct_gc_writebarrier_before_copy(self, hop):
+        xxx
diff --git a/pypy/rpython/memory/gctransform/test/test_framework.py b/pypy/rpython/memory/gctransform/test/test_framework.py
--- a/pypy/rpython/memory/gctransform/test/test_framework.py
+++ b/pypy/rpython/memory/gctransform/test/test_framework.py
@@ -18,9 +18,13 @@
 
 import py
 
+class ForTestGCTransformer(FrameworkGCTransformer):
+    root_stack_depth = 100
+
 class FrameworkGcPolicy2(FrameworkGcPolicy):
-    class transformerclass(FrameworkGCTransformer):
-        root_stack_depth = 100
+    @staticmethod
+    def get_transformer_class():
+        return ForTestGCTransformer
 
 def test_framework_simple():
     def g(x):
diff --git a/pypy/rpython/memory/gctransform/test/test_stmframework.py b/pypy/rpython/memory/gctransform/test/test_stmframework.py
new file mode 100644
--- /dev/null
+++ b/pypy/rpython/memory/gctransform/test/test_stmframework.py
@@ -0,0 +1,27 @@
+from pypy.translator.translator import graphof
+from pypy.objspace.flow.model import summary
+from pypy.rpython.memory.gctransform.test.test_transform import rtype
+from pypy.rpython.memory.gctransform.stmframework import (
+    StmFrameworkGCTransformer)
+
+
+def prepare(entrypoint, types, func=None):
+    t = rtype(entrypoint, types)
+    t.config.translation.gc = 'stmgc'
+    transformer = StmFrameworkGCTransformer(t)
+    graph = graphof(t, func or entrypoint)
+    transformer.transform_graph(graph)
+    return t, graph
+
+
+def test_reader():
+    class A(object):
+        def __init__(self, x):
+            self.x = x
+    def f(a1, a2):
+        return a1.x
+    def entry(n, m):
+        return f(A(n), A(m))
+
+    t, graph = prepare(entry, [int, int], f)
+    assert summary(graph) == {'stm_getfield': 1}
diff --git a/pypy/rpython/memory/test/test_transformed_gc.py b/pypy/rpython/memory/test/test_transformed_gc.py
--- a/pypy/rpython/memory/test/test_transformed_gc.py
+++ b/pypy/rpython/memory/test/test_transformed_gc.py
@@ -933,6 +933,7 @@
 class TestMarkSweepGC(GenericGCTests):
     gcname = "marksweep"
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             GC_PARAMS = {'start_heap_size': 1024*WORD,
                          'translated_to_c': False}
@@ -943,6 +944,7 @@
     gcname = "statistics"
 
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.marksweep import PrintingMarkSweepGC as GCClass
             GC_PARAMS = {'start_heap_size': 1024*WORD,
@@ -954,6 +956,7 @@
     GC_CAN_SHRINK_ARRAY = True
 
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass
             GC_PARAMS = {'space_size': 512*WORD,
@@ -964,6 +967,7 @@
     gcname = 'markcompact'
 
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.markcompact import MarkCompactGC as GCClass
             GC_PARAMS = {'space_size': 4096*WORD,
@@ -975,6 +979,7 @@
     GC_CAN_SHRINK_ARRAY = True
 
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.generation import GenerationGC as \
                                                           GCClass
@@ -1161,6 +1166,7 @@
     gcname = "generation"
 
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.generation import GenerationGC
             class GCClass(GenerationGC):
@@ -1206,6 +1212,7 @@
     GC_CAN_MALLOC_NONMOVABLE = True
 
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass
             GC_PARAMS = {'space_size': 512*WORD,
@@ -1275,6 +1282,7 @@
     GC_CAN_TEST_ID = True
 
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.minimark import MiniMarkGC as GCClass
             GC_PARAMS = {'nursery_size': 32*WORD,
@@ -1391,6 +1399,7 @@
 class TestMarkSweepTaggedPointerGC(TaggedPointerGCTests):
     gcname = "marksweep"
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             GC_PARAMS = {'start_heap_size': 1024*WORD,
                          'translated_to_c': False}
@@ -1400,6 +1409,7 @@
     gcname = "hybrid"
 
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.generation import GenerationGC as \
                                                           GCClass
@@ -1412,6 +1422,7 @@
     gcname = 'markcompact'
 
     class gcpolicy(gc.FrameworkGcPolicy):
+        get_transformer_class = lambda self: self.transformerclass
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.markcompact import MarkCompactGC as GCClass
             GC_PARAMS = {'space_size': 4096*WORD,
diff --git a/pypy/translator/c/database.py b/pypy/translator/c/database.py
--- a/pypy/translator/c/database.py
+++ b/pypy/translator/c/database.py
@@ -60,7 +60,8 @@
         else:
             self.exctransformer = translator.getexceptiontransformer()
         if translator is not None:
-            self.gctransformer = self.gcpolicy.transformerclass(translator)
+            transformerclass = self.gcpolicy.get_transformer_class()
+            self.gctransformer = transformerclass(translator)
         self.completed = False
 
         self.instrument_ncounter = 0
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
@@ -5,8 +5,6 @@
 from pypy.rpython.lltypesystem.lltype import \
      typeOf, Ptr, ContainerType, RttiStruct, \
      RuntimeTypeInfo, getRuntimeTypeInfo, top_container
-from pypy.rpython.memory.gctransform import \
-     refcounting, boehm, framework, asmgcroot
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
@@ -112,7 +110,10 @@
 from pypy.rlib.objectmodel import CDefinedIntSymbolic
 
 class RefcountingGcPolicy(BasicGcPolicy):
-    transformerclass = refcounting.RefcountingGCTransformer
+    @staticmethod
+    def get_transformer_class():
+        from pypy.rpython.memory.gctransform import refcounting
+        return refcounting.RefcountingGCTransformer
 
     def common_gcheader_initdata(self, defnode):
         if defnode.db.gctransformer is not None:
@@ -197,7 +198,10 @@
 
 
 class BoehmGcPolicy(BasicGcPolicy):
-    transformerclass = boehm.BoehmGCTransformer
+    @staticmethod
+    def get_transformer_class():
+        from pypy.rpython.memory.gctransform import boehm
+        return boehm.BoehmGCTransformer
 
     def common_gcheader_initdata(self, defnode):
         if defnode.db.gctransformer is not None:
@@ -247,9 +251,11 @@
         yield 'boehm_gc_startup_code();'
 
     def get_real_weakref_type(self):
+        from pypy.rpython.memory.gctransform import boehm
         return boehm.WEAKLINK
 
     def convert_weakref_to(self, ptarget):
+        from pypy.rpython.memory.gctransform import boehm
         return boehm.convert_weakref_to(ptarget)
 
     def OP_GC__COLLECT(self, funcgen, op):
@@ -306,7 +312,10 @@
 
 
 class FrameworkGcPolicy(BasicGcPolicy):
-    transformerclass = framework.FrameworkGCTransformer
+    @staticmethod
+    def get_transformer_class():
+        from pypy.rpython.memory.gctransform import framework
+        return framework.FrameworkGCTransformer
 
     def struct_setup(self, structdefnode, rtti):
         if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
@@ -338,9 +347,11 @@
         yield '%s();' % (self.db.get(fnptr),)
 
     def get_real_weakref_type(self):
+        from pypy.rpython.memory.gctransform import framework
         return framework.WEAKREF
 
     def convert_weakref_to(self, ptarget):
+        from pypy.rpython.memory.gctransform import framework
         return framework.convert_weakref_to(ptarget)
 
     def OP_GC_RELOAD_POSSIBLY_MOVED(self, funcgen, op):
@@ -396,7 +407,10 @@
         raise Exception("the FramewokGCTransformer should handle this")
 
 class AsmGcRootFrameworkGcPolicy(FrameworkGcPolicy):
-    transformerclass = asmgcroot.AsmGcRootFrameworkGCTransformer
+    @staticmethod
+    def get_transformer_class():
+        from pypy.rpython.memory.gctransform import asmgcroot
+        return asmgcroot.AsmGcRootFrameworkGCTransformer
 
     def GC_KEEPALIVE(self, funcgen, v):
         return 'pypy_asm_keepalive(%s);' % funcgen.expr(v)
@@ -404,6 +418,12 @@
     def OP_GC_STACK_BOTTOM(self, funcgen, op):
         return 'pypy_asm_stack_bottom();'
 
+class StmFrameworkGcPolicy(FrameworkGcPolicy):
+    @staticmethod
+    def get_transformer_class():
+        from pypy.rpython.memory.gctransform import stmframework
+        return stmframework.StmFrameworkGCTransformer
+
 
 name_to_gcpolicy = {
     'boehm': BoehmGcPolicy,
@@ -411,6 +431,5 @@
     'none': NoneGcPolicy,
     'framework': FrameworkGcPolicy,
     'framework+asmgcroot': AsmGcRootFrameworkGcPolicy,
+    'framework+stm': StmFrameworkGcPolicy,
 }
-
-
diff --git a/pypy/translator/stm/stmgcintf.py b/pypy/translator/stm/stmgcintf.py
--- a/pypy/translator/stm/stmgcintf.py
+++ b/pypy/translator/stm/stmgcintf.py
@@ -1,4 +1,5 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.memory.gc.stmgc import PRIMITIVE_SIZES
 from pypy.translator.stm import _rffi_stm
 
 
@@ -28,9 +29,10 @@
                             lltype.Void)
     tldict_enum = smexternal('stm_tldict_enum', [CALLBACK], lltype.Void)
 
-    stm_read_word = smexternal('stm_read_word',
-                               [llmemory.Address, lltype.Signed],
-                               lltype.Signed)
+    for _size, _TYPE in PRIMITIVE_SIZES.items():
+        _name = 'stm_read_int%d' % _size
+        locals()[_name] = smexternal(_name, [llmemory.Address, lltype.Signed],
+                                     _TYPE)
 
     stm_copy_transactional_to_raw = smexternal('stm_copy_transactional_to_raw',
                                                [llmemory.Address,


More information about the pypy-commit mailing list