Author: Armin Rigo <[email protected]>
Branch: stacklet
Changeset: r46557:6634ec220528
Date: 2011-08-17 09:59 +0200
http://bitbucket.org/pypy/pypy/changeset/6634ec220528/

Log:    Work in progress...

diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -69,7 +69,8 @@
                      "statistics": [("translation.gctransformer", 
"framework")],
                      "generation": [("translation.gctransformer", 
"framework")],
                      "hybrid": [("translation.gctransformer", "framework")],
-                     "boehm": [("translation.gctransformer", "boehm")],
+                     "boehm": [("translation.gctransformer", "boehm"),
+                               ("translation.continuation", False)],  # breaks
                      "markcompact": [("translation.gctransformer", 
"framework")],
                      "minimark": [("translation.gctransformer", "framework")],
                      },
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -367,44 +367,91 @@
 
     def add_jit2gc_hooks(self, jit2gc):
         #
-        def collect_jit_stack_root(callback, gc, addr):
-            # Note: first check with 'points_to_valid_gc_object' if the
-            # addr.address[0] appears to be a valid pointer.  It returns
-            # False if it's NULL, and may also check for tagged integers.
-            # The important part here is that it will return True for a
-            # pointer to a MARKER (which is word-aligned), even though it's
-            # not pointing to a valid GC object.
-            if gc.points_to_valid_gc_object(addr):
-                if addr.address[0].signed[0] != GcRootMap_shadowstack.MARKER:
-                    # common case
-                    callback(gc, addr)
+        # ---------------
+        # This is used to enumerate the shadowstack in the presence
+        # of the JIT.  It is also used by the stacklet support in
+        # rlib/_stacklet_shadowstack.  That's why it is written as
+        # an iterator that can also be used with a custom_trace.
+        #
+        def iterator_setup():
+            self._iter_frame_addr = llmemory.NULL
+            self._iter_callshape = llmemory.NULL
+            self._iter_saved_prev = llmemory.NULL
+        #
+        def iterator_next(gc, prev, range_lowest):
+            # Return the "next" valid GC object' address.  "prev" is the
+            # previous result (or the highest end of the shadowstack to start
+            # with), and "range_lowest" is the lowest end of the shadowstack.
+            # We enumerating backwards, starting from the higher addresses.
+            #
+            while True:
+                #
+                # If we are not iterating right now in a JIT frame
+                if self._iter_frame_addr == llmemory.NULL:
+                    #
+                    # Look for the previous shadowstack address that contains
+                    # a valid pointer
+                    while prev != range_lowest:
+                        prev -= llmemory.sizeof(llmemory.Address)
+                        if gc.points_to_valid_gc_object(prev):
+                            break
+                    else:
+                        return llmemory.NULL
+                    #
+                    # Now a "valid" pointer can be either really valid, or it
+                    # can be a pointer to a JIT frame in the stack.  The
+                    # important part here is that 'points_to_valid_gc_object'
+                    # above returns True even for a pointer to a MARKER
+                    # (which is word-aligned).
+                    if prev.address[0].signed[0] != self.MARKER:
+                        return prev
+                    #
+                    # It's a JIT frame.  Save away 'prev' for later, and
+                    # go into JIT-frame-exploring mode.
+                    self._iter_saved_prev = prev
+                    frame_addr = prev.signed[0] - self.marker_ofs
+                    self._iter_frame_addr = frame_addr
+                    addr = llmemory.cast_int_to_adr(frame_addr +
+                                                    self.force_index_ofs)
+                    force_index = addr.signed[0]
+                    if force_index < 0:
+                        force_index = ~force_index
+                    # NB: the next line reads a still-alive _callshapes,
+                    # because we ensure that just before we called this piece
+                    # of assembler, we put on the (same) stack a pointer to a
+                    # loop_token that keeps the force_index alive.
+                    callshape = self._callshapes[force_index]
                 else:
-                    # points to a MARKER
-                    follow_stack_frame_of_assembler(callback, gc, addr)
-        #
-        def follow_stack_frame_of_assembler(callback, gc, addr):
-            frame_addr = addr.signed[0] - self.marker_ofs
-            addr = llmemory.cast_int_to_adr(frame_addr + self.force_index_ofs)
-            force_index = addr.signed[0]
-            if force_index < 0:
-                force_index = ~force_index
-            callshape = self._callshapes[force_index]
-            # NB: the previous line reads a still-alive _callshapes,
-            # because we ensure that just before we called this piece of
-            # assembler, we put on the (same) stack a pointer to a
-            # loop_token that keeps the force_index alive.
-            n = 0
-            while True:
-                offset = rffi.cast(lltype.Signed, callshape[n])
-                if offset == 0:
-                    break
-                addr = llmemory.cast_int_to_adr(frame_addr + offset)
-                if gc.points_to_valid_gc_object(addr):
-                    callback(gc, addr)
-                n += 1
+                    # Continuing to explore this JIT frame
+                    callshape = self._iter_callshape
+                #
+                # 'callshape' points to the next INT of the callshape.
+                # If it's zero we are done with the JIT frame.
+                while callshape[0] != 0:
+                    #
+                    # Non-zero: it's an offset inside the JIT frame.
+                    # Read it and increment 'callshape'.
+                    offset = callshape[0]
+                    callshape = lltype.direct_ptradd(callshape, 1)
+                    addr = llmemory.cast_int_to_adr(self._iter_frame_addr +
+                                                    offset)
+                    if gc.points_to_valid_gc_object(addr):
+                        #
+                        # The JIT frame contains a valid GC pointer at
+                        # this address (and not e.g. NULL).  Save 'callshape'
+                        # for the next call, and return it.
+                        self._iter_callshape = callshape
+                        return addr
+                #
+                # Restore 'prev' and loop back to the start.
+                prev = self._iter_saved_prev
+                self._iter_frame_addr = llmemory.NULL
+
+        # ---------------
         #
         jit2gc.update({
-            'rootstackhook': collect_jit_stack_root,
+            'root_iterator_setup': iterator_setup,
+            'root_iterator_next': iterator_next,
             })
 
     def initialize(self):
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
@@ -149,13 +149,8 @@
             # for regular translation: pick the GC from the config
             GCClass, GC_PARAMS = choose_gc_from_config(translator.config)
 
-        self.root_stack_jit_hook = None
         if hasattr(translator, '_jit2gc'):
             self.layoutbuilder = translator._jit2gc['layoutbuilder']
-            try:
-                self.root_stack_jit_hook = translator._jit2gc['rootstackhook']
-            except KeyError:
-                pass
         else:
             self.layoutbuilder = TransformerLayoutBuilder(translator, GCClass)
         self.layoutbuilder.transformer = self
diff --git a/pypy/rpython/memory/gctransform/shadowstack.py 
b/pypy/rpython/memory/gctransform/shadowstack.py
--- a/pypy/rpython/memory/gctransform/shadowstack.py
+++ b/pypy/rpython/memory/gctransform/shadowstack.py
@@ -27,12 +27,27 @@
             return top
         self.decr_stack = decr_stack
 
-        self.rootstackhook = gctransformer.root_stack_jit_hook
-        if self.rootstackhook is None:
-            def collect_stack_root(callback, gc, addr):
-                if gc.points_to_valid_gc_object(addr):
-                    callback(gc, addr)
-            self.rootstackhook = collect_stack_root
+        translator = gctransformer.translator
+        if hasattr(translator, '_jit2gc'):
+            iterator_setup = translator._jit2gc['root_iterator_setup']
+            iterator_next  = translator._jit2gc['root_iterator_next']
+            def jit_walk_stack_root(callback, addr, end):
+                gc = self.gc
+                iterator_setup()
+                while True:
+                    end = iterator_next(end, addr)
+                    if end == llmemory.NULL:
+                        return
+                    callback(gc, end)
+            self.rootstackhook = jit_walk_stack_root
+        else:
+            def default_walk_stack_root(callback, addr, end):
+                gc = self.gc
+                while addr != end:
+                    if gc.points_to_valid_gc_object(addr):
+                        callback(gc, addr)
+                    addr += sizeofaddr
+            self.rootstackhook = default_walk_stack_root
 
     def push_stack(self, addr):
         top = self.incr_stack(1)
@@ -54,20 +69,18 @@
 
     def walk_stack_roots(self, collect_stack_root):
         gcdata = self.gcdata
-        gc = self.gc
-        rootstackhook = self.rootstackhook
-        addr = gcdata.root_stack_base
-        end = gcdata.root_stack_top
-        while addr != end:
-            rootstackhook(collect_stack_root, gc, addr)
-            addr += sizeofaddr
+        self.rootstackhook(collect_stack_root,
+                           gcdata.root_stack_base, gcdata.root_stack_top)
         if self.collect_stacks_from_other_threads is not None:
             self.collect_stacks_from_other_threads(collect_stack_root)
 
     def need_stacklet_support(self):
-        pass     # no special code needed here
+        # stacklet support: BIG HACK for rlib.rstacklet
+        from pypy.rlib import _stacklet_shadowstack
+        _stacklet_shadowstack._shadowstackrootwalker = self # as a global! argh
 
     def need_thread_support(self, gctransformer, getfn):
+        XXXXXX   # FIXME
         from pypy.module.thread import ll_thread    # xxx fish
         from pypy.rpython.memory.support import AddressDict
         from pypy.rpython.memory.support import copy_without_null_values
diff --git a/pypy/translator/goal/targetpypystandalone.py 
b/pypy/translator/goal/targetpypystandalone.py
--- a/pypy/translator/goal/targetpypystandalone.py
+++ b/pypy/translator/goal/targetpypystandalone.py
@@ -174,9 +174,14 @@
                 config.objspace.usemodules.thread = False
 
         if config.translation.continuation:
-            config.objspace.usemodules._stacklet = True
-        elif config.objspace.usemodules._stacklet:
-            config.translation.continuation = True
+            config.objspace.usemodules._continuation = True
+        elif config.objspace.usemodules._continuation:
+            try:
+                config.translation.continuation = True
+            except ConflictConfigError:
+                # Same as above: try to auto-disable the _continuation
+                # module if translation.continuation cannot be enabled
+                config.objspace.usemodules._continuation = False
 
         if not config.translation.rweakref:
             config.objspace.usemodules._weakref = False
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to