[pypy-commit] pypy miniscan: In-progress.
arigo
noreply at buildbot.pypy.org
Sat Jan 28 11:20:10 CET 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: miniscan
Changeset: r51904:31b709ec2998
Date: 2012-01-28 11:19 +0100
http://bitbucket.org/pypy/pypy/changeset/31b709ec2998/
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
@@ -90,13 +90,14 @@
default=IS_64_BITS, cmdline="--gcremovetypeptr"),
ChoiceOption("gcrootfinder",
"Strategy for finding GC Roots (framework GCs only)",
- ["n/a", "shadowstack", "asmgcc"],
+ ["n/a", "shadowstack", "asmgcc", "scan"],
"shadowstack",
cmdline="--gcrootfinder",
requires={
"shadowstack": [("translation.gctransformer", "framework")],
"asmgcc": [("translation.gctransformer", "framework"),
("translation.backend", "c")],
+ "scan": [("translation.gctransformer", "framework")],
}),
# other noticeable options
diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -403,6 +403,17 @@
class GcStruct(RttiStruct):
_gckind = 'gc'
+ def __init__(self, *args, **kwds):
+ RttiStruct.__init__(self, *args, **kwds)
+ # for --gcrootfinder=scan: we need a way to ensure that most gcrefs
+ # in a program cannot point to varsized stuff. The easiest is to
+ # make sure that GcStructs with no _arrayfld cannot be extended into
+ # GcStructs with an _arrayfld. If this property is needed later,
+ # think harder about pypy.rpython.memory.gctransform.scan.
+ if self._arrayfld is not None and self._first_struct() != (None, None):
+ raise TypeError("GcStruct has both an inlined first struct and "
+ "an Array at the end")
+
STRUCT_BY_FLAVOR = {'raw': Struct,
'gc': GcStruct}
diff --git a/pypy/rpython/memory/gctransform/scan.py b/pypy/rpython/memory/gctransform/scan.py
new file mode 100644
--- /dev/null
+++ b/pypy/rpython/memory/gctransform/scan.py
@@ -0,0 +1,89 @@
+from pypy.rpython.memory.gctransform.framework import FrameworkGCTransformer
+from pypy.rpython.memory.gctransform.framework import BaseRootWalker
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rpython.annlowlevel import llhelper
+
+
+class ScanFrameworkGCTransformer(FrameworkGCTransformer):
+
+ def push_roots(self, hop, keep_current_args=False):
+ livevars = self.get_livevars_for_roots(hop, keep_current_args)
+ self.num_pushs += len(livevars)
+ return livevars
+
+ def pop_roots(self, hop, livevars):
+ if not livevars:
+ return
+ # mark the values as keepalives if they can point to var-sized objs
+ for var in livevars:
+ if self.can_point_to_varsized(var.concretetype):
+ hop.genop("keepalive", [var])
+
+ def can_point_to_varsized(self, TYPE):
+ if not isinstance(TYPE, lltype.Ptr) or TYPE.TO._gckind != "gc":
+ return False # not a ptr-to-gc type at all
+ # this is where we use the fact that a GcStruct cannot inherit another
+ # GcStruct *and* add an _arrayfld:
+ if isinstance(TYPE.TO, lltype.GcStruct) and TYPE.TO._arrayfld is None:
+ return False # can point only to a GcStruct with no _arrayfld
+ else:
+ return True # other, including GCREF
+
+ def build_root_walker(self):
+ return ScanStackRootWalker(self)
+
+
+class ScanStackRootWalker(BaseRootWalker):
+
+ def __init__(self, gctransformer):
+ BaseRootWalker.__init__(self, gctransformer)
+
+ def _asm_callback():
+ self.walk_stack_from()
+ self._asm_callback = _asm_callback
+
+ #def need_stacklet_support(self, gctransformer, getfn):
+ # anything needed?
+
+ #def need_thread_support(self, gctransformer, getfn):
+ # xxx
+
+ def walk_stack_roots(self, collect_stack_root):
+ gcdata = self.gcdata
+ gcdata._gc_collect_stack_root = collect_stack_root
+ pypy_asm_close_for_scanning(
+ llhelper(ASM_CALLBACK_PTR, self._asm_callback))
+
+ def walk_stack_from(self):
+ raise NotImplementedError
+
+
+eci = ExternalCompilationInfo(
+ post_include_bits = ["extern void pypy_asm_close_for_scanning(void*);\n"],
+ separate_module_sources = ['''
+
+void pypy_asm_close_for_scanning(void *fn)
+{
+ /* We have to do the call by clobbering all registers. This is
+ needed to ensure that all GC pointers are forced on the stack. */
+#if defined(__amd64__)
+ asm volatile("call *%%rsi" : : "rsi"(fn) :
+ "memory", "rax", "rbx", "rcx", "rdx", "rbp", "rdi",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15");
+#else
+ asm volatile("call *%%eax" : : "eax"(fn) :
+ "memory", "ebx", "ecx", "edx", "ebp", "esi", "edi");
+#endif
+}
+'''],
+ )
+
+ASM_CALLBACK_PTR = lltype.Ptr(lltype.FuncType([], lltype.Void))
+
+pypy_asm_close_for_scanning = rffi.llexternal('pypy_asm_close_for_scanning',
+ [ASM_CALLBACK_PTR], lltype.Void,
+ sandboxsafe=True,
+ _nowrapper=True,
+ random_effects_on_gcobjs=True,
+ compilation_info=eci)
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
@@ -406,6 +406,15 @@
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)
+
+ def OP_GC_RELOAD_POSSIBLY_MOVED(self, funcgen, op):
+ raise Exception("should not be produced with --gcrootfinder=scan")
+
name_to_gcpolicy = {
'boehm': BoehmGcPolicy,
@@ -413,6 +422,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
@@ -191,6 +191,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()
diff --git a/pypy/translator/c/test/test_scan.py b/pypy/translator/c/test/test_scan.py
new file mode 100644
--- /dev/null
+++ b/pypy/translator/c/test/test_scan.py
@@ -0,0 +1,5 @@
+from pypy.translator.c.test import test_newgc
+
+
+class TestMiniMarkGC(test_newgc.TestMiniMarkGC):
+ gcrootfinder = "scan"
More information about the pypy-commit
mailing list