[pypy-svn] pypy jit-shadowstack: Split to its own file the part that can be reused with jit+shadowstack.

arigo commits-noreply at bitbucket.org
Thu Mar 31 11:43:17 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: jit-shadowstack
Changeset: r43033:a55b47edd32f
Date: 2011-03-30 20:08 +0200
http://bitbucket.org/pypy/pypy/changeset/a55b47edd32f/

Log:	Split to its own file the part that can be reused with
	jit+shadowstack.

diff --git a/pypy/rpython/memory/gctransform/asmgcroot.py b/pypy/rpython/memory/gctransform/asmgcroot.py
--- a/pypy/rpython/memory/gctransform/asmgcroot.py
+++ b/pypy/rpython/memory/gctransform/asmgcroot.py
@@ -1,5 +1,7 @@
 from pypy.rpython.memory.gctransform.framework import FrameworkGCTransformer
 from pypy.rpython.memory.gctransform.framework import BaseRootWalker
+from pypy.rpython.memory.gctransform import gcjit
+from pypy.rpython.memory.gctransform.gcjit import sizeofaddr, arrayitemsize
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.rbuiltin import gen_cast
@@ -137,15 +139,7 @@
             self.walk_stack_from()
         self._asm_callback = _asm_callback
         self._shape_decompressor = ShapeDecompressor()
-        if hasattr(gctransformer.translator, '_jit2gc'):
-            jit2gc = gctransformer.translator._jit2gc
-            self._extra_gcmapstart  = jit2gc['gcmapstart']
-            self._extra_gcmapend    = jit2gc['gcmapend']
-            self._extra_mark_sorted = jit2gc['gcmarksorted']
-        else:
-            self._extra_gcmapstart  = lambda: llmemory.NULL
-            self._extra_gcmapend    = lambda: llmemory.NULL
-            self._extra_mark_sorted = lambda: True
+        self._jittablesearch = gcjit.GcJitTableSearch(gctransformer.translator)
 
     def need_thread_support(self, gctransformer, getfn):
         # Threads supported "out of the box" by the rest of the code.
@@ -391,36 +385,14 @@
         if item:
             self._shape_decompressor.setpos(item.signed[1])
             return
-        gcmapstart2 = self._extra_gcmapstart()
-        gcmapend2   = self._extra_gcmapend()
-        if gcmapstart2 != gcmapend2:
-            # we have a non-empty JIT-produced table to look in
-            item = search_in_gcmap2(gcmapstart2, gcmapend2, retaddr)
-            if item:
-                self._shape_decompressor.setaddr(item)
-                return
-            # maybe the JIT-produced table is not sorted?
-            was_already_sorted = self._extra_mark_sorted()
-            if not was_already_sorted:
-                sort_gcmap(gcmapstart2, gcmapend2)
-                item = search_in_gcmap2(gcmapstart2, gcmapend2, retaddr)
-                if item:
-                    self._shape_decompressor.setaddr(item)
-                    return
-            # there is a rare risk that the array contains *two* entries
-            # with the same key, one of which is dead (null value), and we
-            # found the dead one above.  Solve this case by replacing all
-            # dead keys with nulls, sorting again, and then trying again.
-            replace_dead_entries_with_nulls(gcmapstart2, gcmapend2)
-            sort_gcmap(gcmapstart2, gcmapend2)
-            item = search_in_gcmap2(gcmapstart2, gcmapend2, retaddr)
-            if item:
-                self._shape_decompressor.setaddr(item)
-                return
+        item = self._jittablesearch.look_in_jit_table(retaddr)
+        if item:
+            self._shape_decompressor.setaddr(item)
+            return
         # the item may have been not found because the main array was
         # not sorted.  Sort it and try again.
         win32_follow_gcmap_jmp(gcmapstart, gcmapend)
-        sort_gcmap(gcmapstart, gcmapend)
+        gcjit.sort_gcmap(gcmapstart, gcmapend)
         item = search_in_gcmap(gcmapstart, gcmapend, retaddr)
         if item:
             self._shape_decompressor.setpos(item.signed[1])
@@ -461,32 +433,8 @@
 
 # ____________________________________________________________
 
-sizeofaddr = llmemory.sizeof(llmemory.Address)
-arrayitemsize = 2 * sizeofaddr
-
-
-def binary_search(start, end, addr1):
-    """Search for an element in a sorted array.
-
-    The interval from the start address (included) to the end address
-    (excluded) is assumed to be a sorted arrays of pairs (addr1, addr2).
-    This searches for the item with a given addr1 and returns its
-    address.  If not found exactly, it tries to return the address
-    of the item left of addr1 (i.e. such that result.address[0] < addr1).
-    """
-    count = (end - start) // arrayitemsize
-    while count > 1:
-        middleindex = count // 2
-        middle = start + middleindex * arrayitemsize
-        if addr1 < middle.address[0]:
-            count = middleindex
-        else:
-            start = middle
-            count -= middleindex
-    return start
-
 def search_in_gcmap(gcmapstart, gcmapend, retaddr):
-    item = binary_search(gcmapstart, gcmapend, retaddr)
+    item = gcjit.binary_search(gcmapstart, gcmapend, retaddr)
     if item.address[0] == retaddr:
         return item     # found
     # 'retaddr' not exactly found.  Check that 'item' is the start of a
@@ -496,31 +444,6 @@
     else:
         return llmemory.NULL    # failed
 
-def search_in_gcmap2(gcmapstart, gcmapend, retaddr):
-    # same as 'search_in_gcmap', but without range checking support
-    # (item.signed[1] is an address in this case, not a signed at all!)
-    item = binary_search(gcmapstart, gcmapend, retaddr)
-    if item.address[0] == retaddr:
-        return item.address[1]     # found
-    else:
-        return llmemory.NULL    # failed
-
-def sort_gcmap(gcmapstart, gcmapend):
-    count = (gcmapend - gcmapstart) // arrayitemsize
-    qsort(gcmapstart,
-          rffi.cast(rffi.SIZE_T, count),
-          rffi.cast(rffi.SIZE_T, arrayitemsize),
-          llhelper(QSORT_CALLBACK_PTR, _compare_gcmap_entries))
-
-def replace_dead_entries_with_nulls(start, end):
-    # replace the dead entries (null value) with a null key.
-    count = (end - start) // arrayitemsize - 1
-    while count >= 0:
-        item = start + count * arrayitemsize
-        if item.address[1] == llmemory.NULL:
-            item.address[0] = llmemory.NULL
-        count -= 1
-
 if sys.platform == 'win32':
     def win32_follow_gcmap_jmp(start, end):
         # The initial gcmap table contains addresses to a JMP
@@ -537,17 +460,6 @@
     def win32_follow_gcmap_jmp(start, end):
         pass
 
-def _compare_gcmap_entries(addr1, addr2):
-    key1 = addr1.address[0]
-    key2 = addr2.address[0]
-    if key1 < key2:
-        result = -1
-    elif key1 == key2:
-        result = 0
-    else:
-        result = 1
-    return rffi.cast(rffi.INT, result)
-
 # ____________________________________________________________
 
 class ShapeDecompressor:
@@ -645,14 +557,3 @@
                                      sandboxsafe=True,
                                      _nowrapper=True)
 c_asm_nocollect = Constant(pypy_asm_nocollect, lltype.typeOf(pypy_asm_nocollect))
-
-QSORT_CALLBACK_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address,
-                                                 llmemory.Address], rffi.INT))
-qsort = rffi.llexternal('qsort',
-                        [llmemory.Address,
-                         rffi.SIZE_T,
-                         rffi.SIZE_T,
-                         QSORT_CALLBACK_PTR],
-                        lltype.Void,
-                        sandboxsafe=True,
-                        _nowrapper=True)

diff --git a/pypy/rpython/memory/gctransform/gcjit.py b/pypy/rpython/memory/gctransform/gcjit.py
new file mode 100644
--- /dev/null
+++ b/pypy/rpython/memory/gctransform/gcjit.py
@@ -0,0 +1,116 @@
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.rpython.annlowlevel import llhelper
+
+
+sizeofaddr = llmemory.sizeof(llmemory.Address)
+arrayitemsize = 2 * sizeofaddr
+
+
+def binary_search(start, end, addr1):
+    """Search for an element in a sorted array.
+
+    The interval from the start address (included) to the end address
+    (excluded) is assumed to be a sorted arrays of pairs (addr1, addr2).
+    This searches for the item with a given addr1 and returns its
+    address.  If not found exactly, it tries to return the address
+    of the item left of addr1 (i.e. such that result.address[0] < addr1).
+    """
+    count = (end - start) // arrayitemsize
+    while count > 1:
+        middleindex = count // 2
+        middle = start + middleindex * arrayitemsize
+        if addr1 < middle.address[0]:
+            count = middleindex
+        else:
+            start = middle
+            count -= middleindex
+    return start
+
+def search_in_gcmap_direct(gcmapstart, gcmapend, key):
+    # same as 'search_in_gcmap' in asmgcroot.py, but without range checking
+    # support (item.address[1] is an address in this case, not a int at all!)
+    item = binary_search(gcmapstart, gcmapend, key)
+    if item.address[0] == key:
+        return item.address[1]     # found
+    else:
+        return llmemory.NULL    # failed
+
+def sort_gcmap(gcmapstart, gcmapend):
+    count = (gcmapend - gcmapstart) // arrayitemsize
+    qsort(gcmapstart,
+          rffi.cast(rffi.SIZE_T, count),
+          rffi.cast(rffi.SIZE_T, arrayitemsize),
+          llhelper(QSORT_CALLBACK_PTR, _compare_gcmap_entries))
+
+QSORT_CALLBACK_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address,
+                                                 llmemory.Address], rffi.INT))
+qsort = rffi.llexternal('qsort',
+                        [llmemory.Address,
+                         rffi.SIZE_T,
+                         rffi.SIZE_T,
+                         QSORT_CALLBACK_PTR],
+                        lltype.Void,
+                        sandboxsafe=True,
+                        _nowrapper=True)
+
+def replace_dead_entries_with_nulls(start, end):
+    # replace the dead entries (null value) with a null key.
+    count = (end - start) // arrayitemsize - 1
+    while count >= 0:
+        item = start + count * arrayitemsize
+        if item.address[1] == llmemory.NULL:
+            item.address[0] = llmemory.NULL
+        count -= 1
+
+def _compare_gcmap_entries(addr1, addr2):
+    key1 = addr1.address[0]
+    key2 = addr2.address[0]
+    if key1 < key2:
+        result = -1
+    elif key1 == key2:
+        result = 0
+    else:
+        result = 1
+    return rffi.cast(rffi.INT, result)
+
+
+class GcJitTableSearch(object):
+
+    def __init__(self, translator):
+        if hasattr(translator, '_jit2gc'):
+            jit2gc = translator._jit2gc
+            self._extra_gcmapstart  = jit2gc['gcmapstart']
+            self._extra_gcmapend    = jit2gc['gcmapend']
+            self._extra_mark_sorted = jit2gc['gcmarksorted']
+        else:
+            self._extra_gcmapstart  = lambda: llmemory.NULL
+            self._extra_gcmapend    = lambda: llmemory.NULL
+            self._extra_mark_sorted = lambda: True
+
+    def _freeze_(self):
+        return True
+
+    def look_in_jit_table(self, key):
+        gcmapstart2 = self._extra_gcmapstart()
+        gcmapend2   = self._extra_gcmapend()
+        if gcmapstart2 == gcmapend2:
+            return llmemory.NULL
+        # we have a non-empty JIT-produced table to look in
+        item = search_in_gcmap_direct(gcmapstart2, gcmapend2, key)
+        if item:
+            return item
+        # maybe the JIT-produced table is not sorted?
+        was_already_sorted = self._extra_mark_sorted()
+        if not was_already_sorted:
+            sort_gcmap(gcmapstart2, gcmapend2)
+            item = search_in_gcmap_direct(gcmapstart2, gcmapend2, key)
+            if item:
+                return item
+        # there is a rare risk that the array contains *two* entries
+        # with the same key, one of which is dead (null value), and we
+        # found the dead one above.  Solve this case by replacing all
+        # dead keys with nulls, sorting again, and then trying again.
+        replace_dead_entries_with_nulls(gcmapstart2, gcmapend2)
+        sort_gcmap(gcmapstart2, gcmapend2)
+        item = search_in_gcmap_direct(gcmapstart2, gcmapend2, key)
+        return item


More information about the Pypy-commit mailing list