Author: Armin Rigo <[email protected]>
Branch: guard-compatible
Changeset: r83029:f30a30829848
Date: 2016-03-14 10:20 +0100
http://bitbucket.org/pypy/pypy/changeset/f30a30829848/

Log:    In-progress

diff --git a/rpython/jit/backend/test/runner_test.py 
b/rpython/jit/backend/test/runner_test.py
--- a/rpython/jit/backend/test/runner_test.py
+++ b/rpython/jit/backend/test/runner_test.py
@@ -215,10 +215,11 @@
         assert fail.identifier == 1
 
         self.cpu.grow_guard_compatible_switch(faildescr1, t2_box._resref)
-        deadframe = self.cpu.execute_token(looptoken,
-                                           t2_box._resref)
-        fail = self.cpu.get_latest_descr(deadframe)
-        assert fail.identifier == 2
+        for retry in range(2):
+            deadframe = self.cpu.execute_token(looptoken,
+                                               t2_box._resref)
+            fail = self.cpu.get_latest_descr(deadframe)
+            assert fail.identifier == 2
 
     def test_compile_with_holes_in_fail_args(self):
         targettoken = TargetToken()
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
@@ -33,7 +33,7 @@
 from rpython.jit.backend.x86.vector_ext import VectorAssemblerMixin
 from rpython.jit.backend.x86.callbuilder import follow_jump
 from rpython.jit.metainterp.resoperation import rop
-from rpython.jit.backend.x86 import support
+from rpython.jit.backend.x86 import support, guard_compat
 from rpython.rlib.debug import debug_print, debug_start, debug_stop
 from rpython.rlib import rgc
 from rpython.jit.codewriter.effectinfo import EffectInfo
@@ -69,6 +69,7 @@
 
     def setup_once(self):
         BaseAssembler.setup_once(self)
+        guard_compat.setup_once(self)
         if self.cpu.supports_floats:
             support.ensure_sse2_floats()
             self._build_float_constants()
@@ -1726,10 +1727,15 @@
         self.implement_guard(guard_token)
 
     def genop_guard_guard_compatible(self, guard_op, guard_token, locs, ign):
-        assert guard_op.getarg(0).type == REF # XXX for now?
-        self.mc.CMP(locs[0], locs[1])
-        self.guard_success_cc = rx86.Conditions['E']
-        self.implement_guard(guard_token)
+        assert guard_op.getarg(0).type == REF    # only supported case for now
+        assert guard_op.getarg(1).type == REF
+        loc_reg, loc_imm = locs
+        assert isinstance(loc_reg, RegLoc)
+        assert isinstance(loc_imm, ImmedLoc)
+        if IS_X86_32:
+            XXX
+        guard_compat.generate_guard_compatible(self, guard_token,
+                                               loc_reg, loc_imm.value)
 
     def _cmp_guard_class(self, locs):
         loc_ptr = locs[0]
diff --git a/rpython/jit/backend/x86/guard_compat.py 
b/rpython/jit/backend/x86/guard_compat.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/x86/guard_compat.py
@@ -0,0 +1,96 @@
+from rpython.rtyper.lltypesystem import rffi
+from rpython.jit.backend.x86.arch import WORD
+from rpython.jit.backend.x86 import rx86, codebuf
+from rpython.jit.backend.x86.regloc import X86_64_SCRATCH_REG, imm
+
+# uses the raw structure COMPATINFO, which is informally defined like this:
+# it is an array containing all the expected values that should pass the
+# guard, terminated with a small_ofs value ( < 128, see in code).
+
+
+def generate_guard_compatible(assembler, guard_token, loc_reg, initial_value):
+    # fast-path check
+    mc = assembler.mc
+    mc.MOV_ri64(X86_64_SCRATCH_REG.value, initial_value)
+    rel_pos_compatible_imm = mc.get_relative_pos()
+    mc.CMP_rr(loc_reg.value, X86_64_SCRATCH_REG.value)
+    mc.J_il8(rx86.Conditions['E'], 0)
+    je_location = mc.get_relative_pos()
+
+    # fast-path failed, call the slow-path checker
+    checker = get_or_build_checker(assembler, loc_reg.value)
+
+    # initialize 'compatinfo' with only 'initial_value' in it
+    compatinfoaddr = assembler.datablockwrapper.malloc_aligned(
+        2 * WORD, alignment=WORD)
+    compatinfo = rffi.cast(rffi.SIGNEDP, compatinfoaddr)
+    compatinfo[0] = initial_value
+
+    mc.MOV_ri64(X86_64_SCRATCH_REG.value, compatinfoaddr)  # patchable
+    mc.PUSH_r(X86_64_SCRATCH_REG.value)
+    mc.CALL(imm(checker))
+    mc.stack_frame_size_delta(-WORD)
+
+    small_ofs = mc.get_relative_pos() - rel_pos_compatible_imm
+    assert 0 <= small_ofs <= 127
+    compatinfo[1] = small_ofs
+
+    assembler.guard_success_cc = rx86.Conditions['NZ']
+    assembler.implement_guard(guard_token)
+    #
+    # patch the JE above
+    offset = mc.get_relative_pos() - je_location
+    assert 0 < offset <= 127
+    mc.overwrite(je_location-1, chr(offset))
+
+
+def setup_once(assembler):
+    nb_registers = WORD * 2
+    assembler._guard_compat_checkers = [0] * nb_registers
+
+
+def get_or_build_checker(assembler, regnum):
+    """Returns a piece of assembler that checks if the value is in
+    some array (there is one such piece per input register 'regnum')
+    """
+    addr = assembler._guard_compat_checkers[regnum]
+    if addr != 0:
+        return addr
+
+    mc = codebuf.MachineCodeBlockWrapper()
+
+    mc.MOV_rs(X86_64_SCRATCH_REG.value, WORD)
+
+    pos = mc.get_relative_pos()
+    mc.CMP_mr((X86_64_SCRATCH_REG.value, 0), regnum)
+    mc.J_il8(rx86.Conditions['E'], 0)    # patched below
+    je_location = mc.get_relative_pos()
+    mc.ADD_ri(X86_64_SCRATCH_REG.value, WORD)
+    mc.CMP_mi((X86_64_SCRATCH_REG.value, 0), 127)
+    mc.J_il8(rx86.Conditions['NBE'], pos - (mc.get_relative_pos() + 2))
+
+    # not found!  Return the condition code 'Zero' to mean 'not found'.
+    mc.CMP_rr(regnum, regnum)
+    mc.RET16_i(WORD)
+
+    mc.force_frame_size(WORD)
+
+    # patch the JE above
+    offset = mc.get_relative_pos() - je_location
+    assert 0 < offset <= 127
+    mc.overwrite(je_location-1, chr(offset))
+
+    # found!  update the assembler by writing the value at 'small_ofs'
+    # bytes before our return address.  This should overwrite the const in
+    # 'MOV_ri64(r11, const)', first instruction of the guard_compatible.
+    mc.NEG_r(X86_64_SCRATCH_REG.value)
+    mc.ADD_rs(X86_64_SCRATCH_REG.value, 0)
+    mc.MOV_mr((X86_64_SCRATCH_REG.value, -WORD), regnum)
+
+    # the condition codes say 'Not Zero', as a result of the ADD above.
+    # Return this condition code to mean 'found'.
+    mc.RET16_i(WORD)
+
+    addr = mc.materialize(assembler.cpu, [])
+    assembler._guard_compat_checkers[regnum] = addr
+    return addr
diff --git a/rpython/jit/backend/x86/regalloc.py 
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -483,12 +483,7 @@
         y = self.loc(op.getarg(1))
         self.perform_guard(op, [x, y], None)
 
-    def consider_guard_compatible(self, op):
-        x = self.make_sure_var_in_reg(op.getarg(0))
-        loc = self.assembler.cpu.all_reg_indexes[x.value]
-        op.getdescr().make_a_counter_per_value(op, loc)
-        y = self.loc(op.getarg(1))
-        self.perform_guard(op, [x, y], None)
+    consider_guard_compatible = consider_guard_value
 
     def consider_guard_class(self, op):
         assert not isinstance(op.getarg(0), Const)
diff --git a/rpython/jit/backend/x86/runner.py 
b/rpython/jit/backend/x86/runner.py
--- a/rpython/jit/backend/x86/runner.py
+++ b/rpython/jit/backend/x86/runner.py
@@ -122,6 +122,9 @@
             l[i].counter = ll_s.i
         return l
 
+    def grow_guard_compatible_switch(self, guarddescr, gcref):
+        pass#xxx
+
 
 class CPU386(AbstractX86CPU):
     backend_name = 'x86'
diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py
--- a/rpython/jit/backend/x86/rx86.py
+++ b/rpython/jit/backend/x86/rx86.py
@@ -380,6 +380,7 @@
     INSN_rr = insn(rex_w, chr(base+1), register(2,8), register(1,1), '\xC0')
     INSN_br = insn(rex_w, chr(base+1), register(2,8), stack_bp(1))
     INSN_rb = insn(rex_w, chr(base+3), register(1,8), stack_bp(2))
+    INSN_rs = insn(rex_w, chr(base+3), register(1,8), stack_sp(2))
     INSN_rm = insn(rex_w, chr(base+3), register(1,8), mem_reg_plus_const(2))
     INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_(2))
     INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_(1), immediate(2,'b'))
@@ -403,7 +404,7 @@
     INSN_bi._always_inline_ = True      # try to constant-fold single_byte()
 
     return (INSN_ri, INSN_rr, INSN_rb, INSN_bi, INSN_br, INSN_rm, INSN_rj,
-            INSN_ji8, INSN_mi8)
+            INSN_ji8, INSN_mi8, INSN_rs)
 
 def select_8_or_32_bit_immed(insn_8, insn_32):
     def INSN(*args):
@@ -505,13 +506,13 @@
     INC_m = insn(rex_w, '\xFF', orbyte(0), mem_reg_plus_const(1))
     INC_j = insn(rex_w, '\xFF', orbyte(0), abs_(1))
 
-    AD1_ri,ADD_rr,ADD_rb,_,_,ADD_rm,ADD_rj,_,_ = common_modes(0)
-    OR_ri, OR_rr, OR_rb, _,_,OR_rm, OR_rj, _,_ = common_modes(1)
-    AND_ri,AND_rr,AND_rb,_,_,AND_rm,AND_rj,_,_ = common_modes(4)
-    SU1_ri,SUB_rr,SUB_rb,_,_,SUB_rm,SUB_rj,SUB_ji8,SUB_mi8 = common_modes(5)
-    SBB_ri,SBB_rr,SBB_rb,_,_,SBB_rm,SBB_rj,_,_ = common_modes(3)
-    XOR_ri,XOR_rr,XOR_rb,_,_,XOR_rm,XOR_rj,_,_ = common_modes(6)
-    CMP_ri,CMP_rr,CMP_rb,CMP_bi,CMP_br,CMP_rm,CMP_rj,_,_ = common_modes(7)
+    AD1_ri,ADD_rr,ADD_rb,_,_,ADD_rm,ADD_rj,_,_,ADD_rs = common_modes(0)
+    OR_ri, OR_rr, OR_rb, _,_,OR_rm, OR_rj, _,_,_ = common_modes(1)
+    AND_ri,AND_rr,AND_rb,_,_,AND_rm,AND_rj,_,_,_ = common_modes(4)
+    SU1_ri,SUB_rr,SUB_rb,_,_,SUB_rm,SUB_rj,SUB_ji8,SUB_mi8,_ = common_modes(5)
+    SBB_ri,SBB_rr,SBB_rb,_,_,SBB_rm,SBB_rj,_,_,_ = common_modes(3)
+    XOR_ri,XOR_rr,XOR_rb,_,_,XOR_rm,XOR_rj,_,_,_ = common_modes(6)
+    CMP_ri,CMP_rr,CMP_rb,CMP_bi,CMP_br,CMP_rm,CMP_rj,_,_,_ = common_modes(7)
 
     def ADD_ri(self, reg, immed):
         self.AD1_ri(reg, immed)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to