[pypy-commit] pypy guard-compatible: Move 3/4th of guard_compat to llsupport

arigo pypy.commits at gmail.com
Tue May 24 02:51:32 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: guard-compatible
Changeset: r84654:389d769796e8
Date: 2016-05-24 08:52 +0200
http://bitbucket.org/pypy/pypy/changeset/389d769796e8/

Log:	Move 3/4th of guard_compat to llsupport

diff --git a/rpython/jit/backend/llsupport/guard_compat.py b/rpython/jit/backend/llsupport/guard_compat.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/guard_compat.py
@@ -0,0 +1,228 @@
+from rpython.rlib import rgc
+from rpython.rlib.objectmodel import specialize, we_are_translated
+from rpython.rlib.rarithmetic import r_uint
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
+from rpython.rtyper.lltypesystem.lloperation import llop
+from rpython.rtyper.annlowlevel import cast_instance_to_gcref
+from rpython.rtyper.annlowlevel import cast_gcref_to_instance
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.jit.metainterp.compile import GuardCompatibleDescr
+from rpython.jit.backend.llsupport import jitframe
+
+
+# See ../x86/guard_compat.py for an explanation of the idea, based on
+# x86-64 code.  Here, we have the generic data structures and algos.
+
+
+PAIR = lltype.Struct('PAIR', ('gcref', lltype.Unsigned),   # a GC ref or -1
+                             ('asmaddr', lltype.Signed))
+BACKEND_CHOICES = lltype.GcStruct('BACKEND_CHOICES',
+                        ('bc_faildescr', llmemory.GCREF),
+                        ('bc_gc_table_tracer', llmemory.GCREF),
+                        ('bc_most_recent', PAIR),
+                        ('bc_list', lltype.Array(PAIR)))
+
+def _getofs(name):
+    return llmemory.offsetof(BACKEND_CHOICES, name)
+BCFAILDESCR = _getofs('bc_faildescr')
+BCMOSTRECENT = _getofs('bc_most_recent')
+BCLIST = _getofs('bc_list')
+del _getofs
+BCLISTLENGTHOFS = llmemory.arraylengthoffset(BACKEND_CHOICES.bc_list)
+BCLISTITEMSOFS = llmemory.itemoffsetof(BACKEND_CHOICES.bc_list, 0)
+PAIRSIZE = llmemory.sizeof(PAIR)
+
+def _real_number(ofs):    # hack
+    return rffi.cast(lltype.Signed, rffi.cast(lltype.Unsigned, ofs))
+
+ at specialize.arg(2)
+def bchoices_pair(gc, pair_addr, callback, arg):
+    gcref_addr = pair_addr + llmemory.offsetof(PAIR, 'gcref')
+    old = gcref_addr.unsigned[0]
+    if old != r_uint(-1):
+        gc._trace_callback(callback, arg, gcref_addr)
+    new = gcref_addr.unsigned[0]
+    return old != new
+
+def bchoices_trace(gc, obj_addr, callback, arg):
+    gc._trace_callback(callback, arg, obj_addr + BCFAILDESCR)
+    bchoices_pair(gc, obj_addr + BCMOSTRECENT, callback, arg)
+    length = (obj_addr + BCLIST + BCLISTLENGTHOFS).signed[0]
+    array_addr = obj_addr + BCLIST + BCLISTITEMSOFS
+    item_addr = array_addr
+    i = 0
+    changes = False
+    while i < length:
+        changes |= bchoices_pair(gc, item_addr, callback, arg)
+        item_addr += PAIRSIZE
+        i += 1
+    if changes:
+        pairs_quicksort(array_addr, length)
+lambda_bchoices_trace = lambda: bchoices_trace
+
+eci = ExternalCompilationInfo(post_include_bits=["""
+RPY_EXTERN void pypy_pairs_quicksort(void *base_addr, Signed length);
+"""], separate_module_sources=["""
+#include <stdlib.h>
+
+static int _pairs_compare(const void *p1, const void *p2)
+{
+    if (*(Unsigned *const *)p1 < *(Unsigned *const *)p2)
+        return -1;
+    else if (*(Unsigned *const *)p1 == *(Unsigned *const *)p2)
+        return 0;
+    else
+        return 1;
+}
+RPY_EXTERN
+void pypy_pairs_quicksort(void *base_addr, Signed length)
+{
+    qsort(base_addr, length, 2 * sizeof(void *), _pairs_compare);
+}
+"""])
+pairs_quicksort = rffi.llexternal('pypy_pairs_quicksort',
+                                  [llmemory.Address, lltype.Signed],
+                                  lltype.Void,
+                                  sandboxsafe=True,
+                                  _nowrapper=True,
+                                  compilation_info=eci)
+
+def gcref_to_unsigned(gcref):
+    return rffi.cast(lltype.Unsigned, gcref)
+
+
+INVOKE_FIND_COMPATIBLE_FUNC = lltype.Ptr(lltype.FuncType(
+                [lltype.Ptr(BACKEND_CHOICES), llmemory.GCREF,
+                 lltype.Ptr(jitframe.JITFRAME)],
+                lltype.Signed))
+
+ at specialize.memo()
+def make_invoke_find_compatible(cpu):
+    def invoke_find_compatible(bchoices, new_gcref, jitframe):
+        descr = bchoices.bc_faildescr
+        descr = cast_gcref_to_instance(GuardCompatibleDescr, descr)
+        try:
+            jitframe.jf_gcmap = descr._backend_gcmap
+            result = descr.find_compatible(cpu, new_gcref)
+            if result == 0:
+                result = descr._backend_failure_recovery
+            else:
+                if result == -1:
+                    result = descr._backend_sequel_label
+                bchoices = add_in_tree(bchoices, new_gcref, result)
+                # ---no GC operation---
+                choices_addr = descr._backend_choices_addr  # GC table
+                bchoices_int = rffi.cast(lltype.Signed, bchoices)
+                llop.raw_store(lltype.Void, choices_addr, 0, bchoices_int)
+                llop.gc_writebarrier(lltype.Void, bchoices.bc_gc_table_tracer)
+                # ---no GC operation end---
+            bchoices.bc_most_recent.gcref = gcref_to_unsigned(new_gcref)
+            bchoices.bc_most_recent.asmaddr = result
+            llop.gc_writebarrier(lltype.Void, bchoices)
+        except:             # oops!
+            if not we_are_translated():
+                import sys, pdb
+                pdb.post_mortem(sys.exc_info()[2])
+            result = descr._backend_failure_recovery
+        jitframe.jf_gcmap = lltype.nullptr(lltype.typeOf(jitframe.jf_gcmap).TO)
+        return result
+    return invoke_find_compatible
+
+def add_in_tree(bchoices, new_gcref, new_asmaddr):
+    rgc.register_custom_trace_hook(BACKEND_CHOICES, lambda_bchoices_trace)
+    length = len(bchoices.bc_list)
+    #
+    gcref_base = lltype.cast_opaque_ptr(llmemory.GCREF, bchoices)
+    ofs = BCLIST + BCLISTITEMSOFS
+    ofs += (length - 1) * llmemory.sizeof(PAIR)
+    ofs = _real_number(ofs)
+    if llop.raw_load(lltype.Unsigned, gcref_base, ofs) != r_uint(-1):
+        # reallocate
+        new_bchoices = lltype.malloc(BACKEND_CHOICES, length * 2 + 1)
+        # --- no GC below: it would mess up the order of bc_list ---
+        new_bchoices.bc_faildescr = bchoices.bc_faildescr
+        new_bchoices.bc_gc_table_tracer = bchoices.bc_gc_table_tracer
+        new_bchoices.bc_most_recent.gcref = bchoices.bc_most_recent.gcref
+        new_bchoices.bc_most_recent.asmaddr = bchoices.bc_most_recent.asmaddr
+        i = 0
+        while i < length:
+            new_bchoices.bc_list[i].gcref = bchoices.bc_list[i].gcref
+            new_bchoices.bc_list[i].asmaddr = bchoices.bc_list[i].asmaddr
+            i += 1
+        # fill the new pairs with the invalid gcref value -1
+        length = len(new_bchoices.bc_list)
+        ofs = (llmemory.offsetof(BACKEND_CHOICES, 'bc_list') +
+               llmemory.itemoffsetof(BACKEND_CHOICES.bc_list) +
+               i * llmemory.sizeof(PAIR))
+        while i < length:
+            invalidate_pair(new_bchoices, ofs)
+            ofs += llmemory.sizeof(PAIR)
+            i += 1
+        bchoices = new_bchoices
+    #
+    bchoices.bc_list[length - 1].gcref = gcref_to_unsigned(new_gcref)
+    bchoices.bc_list[length - 1].asmaddr = new_asmaddr
+    llop.gc_writebarrier(lltype.Void, bchoices)
+    # --- no GC above ---
+    addr = llmemory.cast_ptr_to_adr(bchoices)
+    addr += BCLIST + BCLISTITEMSOFS
+    pairs_quicksort(addr, length)
+    return bchoices
+
+def initial_bchoices(guard_compat_descr, initial_gcref):
+    bchoices = lltype.malloc(BACKEND_CHOICES, 1)
+    bchoices.bc_faildescr = cast_instance_to_gcref(guard_compat_descr)
+    bchoices.bc_gc_table_tracer = lltype.nullptr(llmemory.GCREF.TO)   # (*)
+    bchoices.bc_most_recent.gcref = gcref_to_unsigned(initial_gcref)
+    bchoices.bc_most_recent.asmaddr = -43  # (*)
+    bchoices.bc_list[0].gcref = gcref_to_unsigned(initial_gcref)
+    bchoices.bc_list[0].asmaddr = -43  # (*)
+    llop.gc_writebarrier(lltype.Void, bchoices)
+    # entries with (*) are fixed in patch_guard_compatible()
+    return bchoices
+
+def descr_to_bchoices(descr):
+    assert isinstance(descr, GuardCompatibleDescr)
+    # ---no GC operation---
+    bchoices = llop.raw_load(lltype.Signed, descr._backend_choices_addr, 0)
+    bchoices = rffi.cast(lltype.Ptr(BACKEND_CHOICES), bchoices)
+    # ---no GC operation end---
+    return bchoices
+
+def patch_guard_compatible(guard_token, rawstart, get_addr_in_gc_table,
+                           gc_table_tracer):
+    # go to the address in the gctable, number 'bindex'
+    bindex = guard_token.guard_compat_bindex
+    choices_addr = get_addr_in_gc_table(bindex)
+    sequel_label = rawstart + guard_token.pos_jump_offset
+    failure_recovery = rawstart + guard_token.pos_recovery_stub
+    gcmap = guard_token.gcmap
+    # choices_addr:     points to bchoices in the GC table
+    # sequel_label:     "sequel:" label above
+    # failure_recovery: failure recovery address
+    guard_compat_descr = guard_token.faildescr
+    assert isinstance(guard_compat_descr, GuardCompatibleDescr)
+    guard_compat_descr._backend_choices_addr = choices_addr
+    guard_compat_descr._backend_sequel_label = sequel_label
+    guard_compat_descr._backend_failure_recovery = failure_recovery
+    guard_compat_descr._backend_gcmap = gcmap
+    #
+    bchoices = descr_to_bchoices(guard_compat_descr)
+    assert len(bchoices.bc_list) == 1
+    assert (cast_gcref_to_instance(GuardCompatibleDescr, bchoices.bc_faildescr)
+            is guard_compat_descr)
+    bchoices.bc_gc_table_tracer = lltype.cast_opaque_ptr(llmemory.GCREF,
+                                                         gc_table_tracer)
+    bchoices.bc_most_recent.asmaddr = sequel_label
+    bchoices.bc_list[0].asmaddr = sequel_label
+
+def invalidate_pair(bchoices, pair_ofs):
+    gcref_base = lltype.cast_opaque_ptr(llmemory.GCREF, bchoices)
+    llop.raw_store(lltype.Void, gcref_base, _real_number(pair_ofs), r_uint(-1))
+    ofs = pair_ofs + llmemory.sizeof(lltype.Unsigned)
+    llop.raw_store(lltype.Void, gcref_base, _real_number(ofs), -1)
+
+def invalidate_cache(faildescr):
+    """Write -1 inside bchoices.bc_most_recent.gcref."""
+    bchoices = descr_to_bchoices(faildescr)
+    invalidate_pair(bchoices, BCMOSTRECENT)
diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -990,7 +990,7 @@
         return load_op
 
     def handle_guard_compatible(self, op):
-        from rpython.jit.backend.x86 import guard_compat    # XXX
+        from rpython.jit.backend.llsupport import guard_compat
         c = op.getarg(1)
         assert isinstance(c, ConstPtr)
         descr = op.getdescr()
diff --git a/rpython/jit/backend/llsupport/test/test_guard_compat.py b/rpython/jit/backend/llsupport/test/test_guard_compat.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/test/test_guard_compat.py
@@ -0,0 +1,61 @@
+from rpython.jit.backend.llsupport.guard_compat import *
+
+
+def test_invalidate_cache():
+    b = lltype.malloc(BACKEND_CHOICES, 4)
+    invalidate_pair(b, BCMOSTRECENT)
+    x = b.bc_most_recent.gcref
+    assert x == r_uint(-1)
+
+def check_bclist(bchoices, expected):
+    assert len(bchoices.bc_list) == len(expected)
+    for i in range(len(bchoices.bc_list)):
+        pair = bchoices.bc_list[i]
+        assert pair.gcref == rffi.cast(lltype.Unsigned, expected[i][0])
+        assert pair.asmaddr == expected[i][1]
+
+def test_add_in_tree():
+    b = lltype.malloc(BACKEND_CHOICES, 3, zero=True)    # 3 * null
+    check_bclist(b, [
+        (0, 0),    # null
+        (0, 0),    # null
+        (0, 0),    # null
+        ])
+    new_gcref = rffi.cast(llmemory.GCREF, 717344)
+    new_asmaddr = 1234567
+    b2 = add_in_tree(b, new_gcref, new_asmaddr)
+    check_bclist(b2, [
+        (0, 0),    # null
+        (0, 0),    # null
+        (0, 0),    # null
+        (new_gcref, new_asmaddr),
+        (-1, -1),  # invalid
+        (-1, -1),  # invalid
+        (-1, -1),  # invalid
+        ])
+    new_gcref_2 = rffi.cast(llmemory.GCREF, 717000)   # lower than before
+    new_asmaddr_2 = 2345678
+    b3 = add_in_tree(b2, new_gcref_2, new_asmaddr_2)
+    assert b3 == b2     # was still large enough
+    check_bclist(b2, [
+        (0, 0),    # null
+        (0, 0),    # null
+        (0, 0),    # null
+        (new_gcref_2, new_asmaddr_2),
+        (new_gcref,   new_asmaddr),
+        (-1, -1),  # invalid
+        (-1, -1),  # invalid
+        ])
+    new_gcref_3 = rffi.cast(llmemory.GCREF, 717984)   # higher than before
+    new_asmaddr_3 = 3456789
+    b4 = add_in_tree(b3, new_gcref_3, new_asmaddr_3)
+    assert b4 == b2     # was still large enough
+    check_bclist(b2, [
+        (0, 0),    # null
+        (0, 0),    # null
+        (0, 0),    # null
+        (new_gcref_2, new_asmaddr_2),
+        (new_gcref,   new_asmaddr),
+        (new_gcref_3, new_asmaddr_3),
+        (-1, -1),  # invalid
+        ])
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -1414,3 +1414,22 @@
             jump()
         """)
         assert len(self.gcrefs) == 2
+
+    def test_guard_compatible(self):
+        from rpython.jit.backend.llsupport import guard_compat
+        self.check_rewrite("""
+            [p0]
+            guard_compatible(p0, ConstPtr(myR1)) []
+            guard_compatible(p0, ConstPtr(myR1)) []
+            jump()
+        """, """
+            [p0]
+            guard_compatible(p0, 0) []
+            guard_compatible(p0, 2) []    # no sharing the number
+            jump()
+        """)
+        assert len(self.gcrefs) == 4
+        for i in [0, 2]:
+            # type-checking
+            x = self.gcrefs[i]
+            lltype.cast_opaque_ptr(lltype.Ptr(guard_compat.BACKEND_CHOICES), x)
diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -736,6 +736,10 @@
         if WORD == 8 and len(self.pending_memoryerror_trampoline_from) > 0:
             self.error_trampoline_64 = self.generate_propagate_error_64()
 
+    def _get_addr_in_gc_table(self, index):
+        # return the address of the slot in the gctable, number 'index'
+        return self.gc_table_addr + index * WORD
+
     def patch_pending_failure_recoveries(self, rawstart):
         # after we wrote the assembler to raw memory, set up
         # tok.faildescr.adr_jump_offset to contain the raw address of
@@ -747,7 +751,7 @@
             tok.faildescr.adr_jump_offset = addr
             if tok.guard_compatible():
                 guard_compat.patch_guard_compatible(tok, rawstart,
-                                                    self.gc_table_addr,
+                                                    self._get_addr_in_gc_table,
                                                     self.gc_table_tracer)
                 continue
             descr = tok.faildescr
diff --git a/rpython/jit/backend/x86/guard_compat.py b/rpython/jit/backend/x86/guard_compat.py
--- a/rpython/jit/backend/x86/guard_compat.py
+++ b/rpython/jit/backend/x86/guard_compat.py
@@ -1,18 +1,12 @@
-from rpython.rlib import rgc
-from rpython.rlib.objectmodel import specialize, we_are_translated
-from rpython.rlib.rarithmetic import r_uint
-from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
-from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.rtyper.annlowlevel import cast_instance_to_gcref, llhelper
-from rpython.rtyper.annlowlevel import cast_gcref_to_instance
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.jit.metainterp.compile import GuardCompatibleDescr
-from rpython.jit.backend.llsupport import jitframe
+from rpython.rtyper.annlowlevel import llhelper
 from rpython.jit.backend.x86 import rx86, codebuf, regloc
 from rpython.jit.backend.x86.regalloc import gpr_reg_mgr_cls
 from rpython.jit.backend.x86.arch import WORD, IS_X86_64, IS_X86_32
 from rpython.jit.backend.x86.arch import DEFAULT_FRAME_BYTES
 
+from rpython.jit.backend.llsupport.guard_compat import *
+from rpython.jit.backend.llsupport.guard_compat import _real_number
+
 
 #
 # GUARD_COMPATIBLE(reg, const-ptr) produces the following assembler.
@@ -171,218 +165,8 @@
 # ____________________________________________________________
 
 
-PAIR = lltype.Struct('PAIR', ('gcref', lltype.Unsigned),   # a GC ref or -1
-                             ('asmaddr', lltype.Signed))
-BACKEND_CHOICES = lltype.GcStruct('BACKEND_CHOICES',
-                        ('bc_faildescr', llmemory.GCREF),
-                        ('bc_gc_table_tracer', llmemory.GCREF),
-                        ('bc_most_recent', PAIR),
-                        ('bc_list', lltype.Array(PAIR)))
-
-def _getofs(name):
-    return llmemory.offsetof(BACKEND_CHOICES, name)
-BCFAILDESCR = _getofs('bc_faildescr')
-BCMOSTRECENT = _getofs('bc_most_recent')
-BCLIST = _getofs('bc_list')
-del _getofs
-BCLISTLENGTHOFS = llmemory.arraylengthoffset(BACKEND_CHOICES.bc_list)
-BCLISTITEMSOFS = llmemory.itemoffsetof(BACKEND_CHOICES.bc_list, 0)
-PAIRSIZE = llmemory.sizeof(PAIR)
-
-def _real_number(ofs):    # hack
-    return rffi.cast(lltype.Signed, rffi.cast(lltype.Unsigned, ofs))
-
- at specialize.arg(2)
-def bchoices_pair(gc, pair_addr, callback, arg):
-    gcref_addr = pair_addr + llmemory.offsetof(PAIR, 'gcref')
-    old = gcref_addr.unsigned[0]
-    if old != r_uint(-1):
-        gc._trace_callback(callback, arg, gcref_addr)
-    new = gcref_addr.unsigned[0]
-    return old != new
-
-def bchoices_trace(gc, obj_addr, callback, arg):
-    gc._trace_callback(callback, arg, obj_addr + BCFAILDESCR)
-    bchoices_pair(gc, obj_addr + BCMOSTRECENT, callback, arg)
-    length = (obj_addr + BCLIST + BCLISTLENGTHOFS).signed[0]
-    array_addr = obj_addr + BCLIST + BCLISTITEMSOFS
-    item_addr = array_addr
-    i = 0
-    changes = False
-    while i < length:
-        changes |= bchoices_pair(gc, item_addr, callback, arg)
-        item_addr += PAIRSIZE
-        i += 1
-    if changes:
-        pairs_quicksort(array_addr, length)
-lambda_bchoices_trace = lambda: bchoices_trace
-
-eci = ExternalCompilationInfo(post_include_bits=["""
-RPY_EXTERN void pypy_pairs_quicksort(void *base_addr, Signed length);
-"""], separate_module_sources=["""
-#include <stdlib.h>
-
-static int _pairs_compare(const void *p1, const void *p2)
-{
-    if (*(Unsigned *const *)p1 < *(Unsigned *const *)p2)
-        return -1;
-    else if (*(Unsigned *const *)p1 == *(Unsigned *const *)p2)
-        return 0;
-    else
-        return 1;
-}
-RPY_EXTERN
-void pypy_pairs_quicksort(void *base_addr, Signed length)
-{
-    qsort(base_addr, length, 2 * sizeof(void *), _pairs_compare);
-}
-"""])
-pairs_quicksort = rffi.llexternal('pypy_pairs_quicksort',
-                                  [llmemory.Address, lltype.Signed],
-                                  lltype.Void,
-                                  sandboxsafe=True,
-                                  _nowrapper=True,
-                                  compilation_info=eci)
-
-def gcref_to_unsigned(gcref):
-    return rffi.cast(lltype.Unsigned, gcref)
-
-
-INVOKE_FIND_COMPATIBLE_FUNC = lltype.Ptr(lltype.FuncType(
-                [lltype.Ptr(BACKEND_CHOICES), llmemory.GCREF,
-                 lltype.Ptr(jitframe.JITFRAME)],
-                lltype.Signed))
-
- at specialize.memo()
-def make_invoke_find_compatible(cpu):
-    def invoke_find_compatible(bchoices, new_gcref, jitframe):
-        descr = bchoices.bc_faildescr
-        descr = cast_gcref_to_instance(GuardCompatibleDescr, descr)
-        try:
-            jitframe.jf_gcmap = descr._backend_gcmap
-            result = descr.find_compatible(cpu, new_gcref)
-            if result == 0:
-                result = descr._backend_failure_recovery
-            else:
-                if result == -1:
-                    result = descr._backend_sequel_label
-                bchoices = add_in_tree(bchoices, new_gcref, result)
-                # ---no GC operation---
-                choices_addr = descr._backend_choices_addr  # GC table
-                bchoices_int = rffi.cast(lltype.Signed, bchoices)
-                llop.raw_store(lltype.Void, choices_addr, 0, bchoices_int)
-                llop.gc_writebarrier(lltype.Void, bchoices.bc_gc_table_tracer)
-                # ---no GC operation end---
-            bchoices.bc_most_recent.gcref = gcref_to_unsigned(new_gcref)
-            bchoices.bc_most_recent.asmaddr = result
-            llop.gc_writebarrier(lltype.Void, bchoices)
-        except:             # oops!
-            if not we_are_translated():
-                import sys, pdb
-                pdb.post_mortem(sys.exc_info()[2])
-            result = descr._backend_failure_recovery
-        jitframe.jf_gcmap = lltype.nullptr(lltype.typeOf(jitframe.jf_gcmap).TO)
-        return result
-    return invoke_find_compatible
-
-def add_in_tree(bchoices, new_gcref, new_asmaddr):
-    rgc.register_custom_trace_hook(BACKEND_CHOICES, lambda_bchoices_trace)
-    length = len(bchoices.bc_list)
-    #
-    gcref_base = lltype.cast_opaque_ptr(llmemory.GCREF, bchoices)
-    ofs = BCLIST + BCLISTITEMSOFS
-    ofs += (length - 1) * llmemory.sizeof(PAIR)
-    ofs = _real_number(ofs)
-    if llop.raw_load(lltype.Unsigned, gcref_base, ofs) != r_uint(-1):
-        # reallocate
-        new_bchoices = lltype.malloc(BACKEND_CHOICES, length * 2 + 1)
-        # --- no GC below: it would mess up the order of bc_list ---
-        new_bchoices.bc_faildescr = bchoices.bc_faildescr
-        new_bchoices.bc_gc_table_tracer = bchoices.bc_gc_table_tracer
-        new_bchoices.bc_most_recent.gcref = bchoices.bc_most_recent.gcref
-        new_bchoices.bc_most_recent.asmaddr = bchoices.bc_most_recent.asmaddr
-        i = 0
-        while i < length:
-            new_bchoices.bc_list[i].gcref = bchoices.bc_list[i].gcref
-            new_bchoices.bc_list[i].asmaddr = bchoices.bc_list[i].asmaddr
-            i += 1
-        # fill the new pairs with the invalid gcref value -1
-        length = len(new_bchoices.bc_list)
-        ofs = (llmemory.offsetof(BACKEND_CHOICES, 'bc_list') +
-               llmemory.itemoffsetof(BACKEND_CHOICES.bc_list) +
-               i * llmemory.sizeof(PAIR))
-        while i < length:
-            invalidate_pair(new_bchoices, ofs)
-            ofs += llmemory.sizeof(PAIR)
-            i += 1
-        bchoices = new_bchoices
-    #
-    bchoices.bc_list[length - 1].gcref = gcref_to_unsigned(new_gcref)
-    bchoices.bc_list[length - 1].asmaddr = new_asmaddr
-    llop.gc_writebarrier(lltype.Void, bchoices)
-    # --- no GC above ---
-    addr = llmemory.cast_ptr_to_adr(bchoices)
-    addr += BCLIST + BCLISTITEMSOFS
-    pairs_quicksort(addr, length)
-    return bchoices
-
-def initial_bchoices(guard_compat_descr, initial_gcref):
-    bchoices = lltype.malloc(BACKEND_CHOICES, 1)
-    bchoices.bc_faildescr = cast_instance_to_gcref(guard_compat_descr)
-    bchoices.bc_gc_table_tracer = lltype.nullptr(llmemory.GCREF.TO)   # (*)
-    bchoices.bc_most_recent.gcref = gcref_to_unsigned(initial_gcref)
-    bchoices.bc_most_recent.asmaddr = -43  # (*)
-    bchoices.bc_list[0].gcref = gcref_to_unsigned(initial_gcref)
-    bchoices.bc_list[0].asmaddr = -43  # (*)
-    llop.gc_writebarrier(lltype.Void, bchoices)
-    # entries with (*) are fixed in patch_guard_compatible()
-    return bchoices
-
-def descr_to_bchoices(descr):
-    assert isinstance(descr, GuardCompatibleDescr)
-    # ---no GC operation---
-    bchoices = llop.raw_load(lltype.Signed, descr._backend_choices_addr, 0)
-    bchoices = rffi.cast(lltype.Ptr(BACKEND_CHOICES), bchoices)
-    # ---no GC operation end---
-    return bchoices
-
-def patch_guard_compatible(guard_token, rawstart, gc_table_addr,
-                           gc_table_tracer):
-    # go to the address in the gctable, number 'bindex'
-    bindex = guard_token.guard_compat_bindex
-    choices_addr = gc_table_addr + WORD * bindex
-    sequel_label = rawstart + guard_token.pos_jump_offset
-    failure_recovery = rawstart + guard_token.pos_recovery_stub
-    gcmap = guard_token.gcmap
-    # choices_addr:     points to bchoices in the GC table
-    # sequel_label:     "sequel:" label above
-    # failure_recovery: failure recovery address
-    guard_compat_descr = guard_token.faildescr
-    assert isinstance(guard_compat_descr, GuardCompatibleDescr)
-    guard_compat_descr._backend_choices_addr = choices_addr
-    guard_compat_descr._backend_sequel_label = sequel_label
-    guard_compat_descr._backend_failure_recovery = failure_recovery
-    guard_compat_descr._backend_gcmap = gcmap
-    #
-    bchoices = descr_to_bchoices(guard_compat_descr)
-    assert len(bchoices.bc_list) == 1
-    assert (cast_gcref_to_instance(GuardCompatibleDescr, bchoices.bc_faildescr)
-            is guard_compat_descr)
-    bchoices.bc_gc_table_tracer = lltype.cast_opaque_ptr(llmemory.GCREF,
-                                                         gc_table_tracer)
-    bchoices.bc_most_recent.asmaddr = sequel_label
-    bchoices.bc_list[0].asmaddr = sequel_label
-
-def invalidate_pair(bchoices, pair_ofs):
-    gcref_base = lltype.cast_opaque_ptr(llmemory.GCREF, bchoices)
-    llop.raw_store(lltype.Void, gcref_base, _real_number(pair_ofs), r_uint(-1))
-    ofs = pair_ofs + llmemory.sizeof(lltype.Unsigned)
-    llop.raw_store(lltype.Void, gcref_base, _real_number(ofs), -1)
-
-def invalidate_cache(faildescr):
-    """Write -1 inside bchoices.bc_most_recent.gcref."""
-    bchoices = descr_to_bchoices(faildescr)
-    invalidate_pair(bchoices, BCMOSTRECENT)
+# A lot of the logic is not specific to the x86 backend and is
+# written in ../llsupport/guard_compat.py.
 
 
 def _fix_forward_label(mc, jmp_location):
diff --git a/rpython/jit/backend/x86/test/test_compatible.py b/rpython/jit/backend/x86/test/test_compatible.py
--- a/rpython/jit/backend/x86/test/test_compatible.py
+++ b/rpython/jit/backend/x86/test/test_compatible.py
@@ -10,65 +10,6 @@
     pass
 
 
-def test_invalidate_cache():
-    b = lltype.malloc(BACKEND_CHOICES, 4)
-    invalidate_pair(b, BCMOSTRECENT)
-    x = b.bc_most_recent.gcref
-    assert x == r_uint(-1)
-
-def check_bclist(bchoices, expected):
-    assert len(bchoices.bc_list) == len(expected)
-    for i in range(len(bchoices.bc_list)):
-        pair = bchoices.bc_list[i]
-        assert pair.gcref == rffi.cast(lltype.Unsigned, expected[i][0])
-        assert pair.asmaddr == expected[i][1]
-
-def test_add_in_tree():
-    b = lltype.malloc(BACKEND_CHOICES, 3, zero=True)    # 3 * null
-    check_bclist(b, [
-        (0, 0),    # null
-        (0, 0),    # null
-        (0, 0),    # null
-        ])
-    new_gcref = rffi.cast(llmemory.GCREF, 717344)
-    new_asmaddr = 1234567
-    b2 = add_in_tree(b, new_gcref, new_asmaddr)
-    check_bclist(b2, [
-        (0, 0),    # null
-        (0, 0),    # null
-        (0, 0),    # null
-        (new_gcref, new_asmaddr),
-        (-1, -1),  # invalid
-        (-1, -1),  # invalid
-        (-1, -1),  # invalid
-        ])
-    new_gcref_2 = rffi.cast(llmemory.GCREF, 717000)   # lower than before
-    new_asmaddr_2 = 2345678
-    b3 = add_in_tree(b2, new_gcref_2, new_asmaddr_2)
-    assert b3 == b2     # was still large enough
-    check_bclist(b2, [
-        (0, 0),    # null
-        (0, 0),    # null
-        (0, 0),    # null
-        (new_gcref_2, new_asmaddr_2),
-        (new_gcref,   new_asmaddr),
-        (-1, -1),  # invalid
-        (-1, -1),  # invalid
-        ])
-    new_gcref_3 = rffi.cast(llmemory.GCREF, 717984)   # higher than before
-    new_asmaddr_3 = 3456789
-    b4 = add_in_tree(b3, new_gcref_3, new_asmaddr_3)
-    assert b4 == b2     # was still large enough
-    check_bclist(b2, [
-        (0, 0),    # null
-        (0, 0),    # null
-        (0, 0),    # null
-        (new_gcref_2, new_asmaddr_2),
-        (new_gcref,   new_asmaddr),
-        (new_gcref_3, new_asmaddr_3),
-        (-1, -1),  # invalid
-        ])
-
 def test_guard_compat():
     cpu = CPU(rtyper=None, stats=FakeStats())
     cpu.setup_once()
@@ -129,7 +70,8 @@
         faildescr = guard_compat_descr
     guard_token = FakeGuardToken()
 
-    patch_guard_compatible(guard_token, rawstart, rawstart,
+    patch_guard_compatible(guard_token, rawstart,
+                           lambda index: rawstart + index * WORD,
                            lltype.nullptr(llmemory.GCREF.TO))
 
     # ---- ready ----


More information about the pypy-commit mailing list