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