[pypy-commit] pypy default: (fijal, arigo)

arigo noreply at buildbot.pypy.org
Sat Jan 28 19:30:21 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r51929:f0d095a1d379
Date: 2012-01-28 19:18 +0100
http://bitbucket.org/pypy/pypy/changeset/f0d095a1d379/

Log:	(fijal, arigo)

	Change the order of the shadowstack processing. We now process it
	right-to-left instead of left-to-right (it's an array, so "left" is
	0 and "right" is the end).

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
@@ -394,13 +394,13 @@
     This is the class supporting --gcrootfinder=shadowstack.
     """
     is_shadow_stack = True
-    MARKER = 8
+    MARKER_FRAME = 8       # this marker now *follows* the frame addr
 
     # The "shadowstack" is a portable way in which the GC finds the
     # roots that live in the stack.  Normally it is just a list of
     # pointers to GC objects.  The pointers may be moved around by a GC
-    # collection.  But with the JIT, an entry can also be MARKER, in
-    # which case the next entry points to an assembler stack frame.
+    # collection.  But with the JIT, an entry can also be MARKER_FRAME,
+    # in which case the previous entry points to an assembler stack frame.
     # During a residual CALL from the assembler (which may indirectly
     # call the GC), we use the force_index stored in the assembler
     # stack frame to identify the call: we can go from the force_index
@@ -436,11 +436,13 @@
             def setcontext(iself, context):
                 iself.context = context
 
-            def next(iself, gc, next, range_highest):
-                # Return the "next" valid GC object' address.  This usually
-                # means just returning "next", until we reach "range_highest",
-                # except that we are skipping NULLs.  If "next" contains a
-                # MARKER instead, then we go into JIT-frame-lookup mode.
+            def nextleft(iself, gc, range_lowest, prev):
+                # Return the next valid GC object's address, in right-to-left
+                # order from the shadowstack array.  This usually means just
+                # returning "prev - sizeofaddr", until we reach "range_lowest",
+                # except that we are skipping NULLs.  If "prev - sizeofaddr"
+                # contains a MARKER_FRAME instead, then we go into
+                # JIT-frame-lookup mode.
                 #
                 while True:
                     #
@@ -449,20 +451,20 @@
                         #
                         # Look for the next shadowstack address that
                         # contains a valid pointer
-                        while next != range_highest:
-                            if next.signed[0] == self.MARKER:
+                        while prev != range_lowest:
+                            prev -= llmemory.sizeof(llmemory.Address)
+                            if prev.signed[0] == self.MARKER_FRAME:
                                 break
-                            if gc.points_to_valid_gc_object(next):
-                                return next
-                            next += llmemory.sizeof(llmemory.Address)
+                            if gc.points_to_valid_gc_object(prev):
+                                return prev
                         else:
                             return llmemory.NULL     # done
                         #
-                        # It's a JIT frame.  Save away 'next' for later, and
+                        # It's a JIT frame.  Save away 'prev' for later, and
                         # go into JIT-frame-exploring mode.
-                        next += llmemory.sizeof(llmemory.Address)
-                        frame_addr = next.signed[0]
-                        iself.saved_next = next
+                        prev -= llmemory.sizeof(llmemory.Address)
+                        frame_addr = prev.signed[0]
+                        iself.saved_prev = prev
                         iself.frame_addr = frame_addr
                         addr = llmemory.cast_int_to_adr(frame_addr +
                                                         self.force_index_ofs)
@@ -502,8 +504,7 @@
                     #
                     # Restore 'prev' and loop back to the start.
                     iself.frame_addr = 0
-                    next = iself.saved_next
-                    next += llmemory.sizeof(llmemory.Address)
+                    prev = iself.saved_prev
 
         # ---------------
         #
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -774,7 +774,7 @@
         self.mc.RET()
 
     def _call_header_shadowstack(self, gcrootmap):
-        # we need to put two words into the shadowstack: the MARKER
+        # we need to put two words into the shadowstack: the MARKER_FRAME
         # and the address of the frame (ebp, actually)
         rst = gcrootmap.get_root_stack_top_addr()
         if rx86.fits_in_32bits(rst):
@@ -783,9 +783,10 @@
             self.mc.MOV_ri(r13.value, rst)            # MOV r13, rootstacktop
             self.mc.MOV_rm(eax.value, (r13.value, 0)) # MOV eax, [r13]
         #
-        self.mc.LEA_rm(ebx.value, (eax.value, 2*WORD))  # LEA ebx, [eax+2*WORD]
-        self.mc.MOV_mi((eax.value, 0), gcrootmap.MARKER)    # MOV [eax], MARKER
-        self.mc.MOV_mr((eax.value, WORD), ebp.value)      # MOV [eax+WORD], ebp
+        MARKER = gcrootmap.MARKER_FRAME
+        self.mc.LEA_rm(ebx.value, (eax.value, 2*WORD)) # LEA ebx, [eax+2*WORD]
+        self.mc.MOV_mi((eax.value, WORD), MARKER)      # MOV [eax+WORD], MARKER
+        self.mc.MOV_mr((eax.value, 0), ebp.value)      # MOV [eax], ebp
         #
         if rx86.fits_in_32bits(rst):
             self.mc.MOV_jr(rst, ebx.value)            # MOV [rootstacktop], ebx
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
@@ -28,15 +28,15 @@
         self.decr_stack = decr_stack
 
         root_iterator = get_root_iterator(gctransformer)
-        def walk_stack_root(callback, addr, end):
+        def walk_stack_root(callback, start, end):
             root_iterator.setcontext(NonConstant(llmemory.NULL))
             gc = self.gc
+            addr = end
             while True:
-                addr = root_iterator.next(gc, addr, end)
+                addr = root_iterator.nextleft(gc, start, addr)
                 if addr == llmemory.NULL:
                     return
                 callback(gc, addr)
-                addr += sizeofaddr
         self.rootstackhook = walk_stack_root
 
         self.shadow_stack_pool = ShadowStackPool(gcdata)
@@ -333,11 +333,11 @@
                 return True
             def setcontext(self, context):
                 pass
-            def next(self, gc, addr, end):
-                while addr != end:
+            def nextleft(self, gc, start, addr):
+                while addr != start:
+                    addr -= sizeofaddr
                     if gc.points_to_valid_gc_object(addr):
                         return addr
-                    addr += sizeofaddr
                 return llmemory.NULL
         result = RootIterator()
     gctransformer._root_iterator = result
@@ -364,10 +364,8 @@
         obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR)
         if not prev:
             root_iterator.setcontext(obj.context)
-            next = obj.base
-        else:
-            next = prev + sizeofaddr
-        return root_iterator.next(gc, next, obj.top)
+            prev = obj.top
+        return root_iterator.nextleft(gc, obj.base, prev)
 
     CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
                                       llmemory.Address)


More information about the pypy-commit mailing list