Author: Armin Rigo <[email protected]>
Branch: branch-prediction
Changeset: r90986:9702232cd5b9
Date: 2017-04-06 15:54 +0200
http://bitbucket.org/pypy/pypy/changeset/9702232cd5b9/
Log: Start moving the first slowpath offline
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
@@ -41,6 +41,34 @@
from rpython.rlib.objectmodel import compute_unique_id
+class SlowPath(object):
+ def __init__(self, mc, condition):
+ mc.J_il(condition, 0xfffff) # patched later
+ self.cond_jump_addr = mc.get_relative_pos(break_basic_block=False)
+ self.saved_scratch_value_1 = mc.get_scratch_register_known_value()
+
+ def set_continue_addr(self, mc):
+ self.continue_addr = mc.get_relative_pos(break_basic_block=False)
+ self.saved_scratch_value_2 = mc.get_scratch_register_known_value()
+
+ def generate(self, assembler):
+ # no alignment here, prefer compactness for these slow-paths
+ mc = assembler.mc
+ # patch the original jump to go here
+ offset = mc.get_relative_pos() - self.cond_jump_addr
+ mc.overwrite32(self.cond_jump_addr-4, offset)
+ # restore the knowledge of the scratch register value
+ # (this does not emit any code)
+ mc.restore_scratch_register_known_value(self.saved_scratch_value_1)
+ # generate the body of the slow-path
+ self.generate_body(assembler, mc)
+ # reload (if needed) the (possibly different) scratch register value
+ mc.load_scratch_if_known(self.saved_scratch_value_2)
+ # jump back
+ curpos = mc.get_relative_pos() + 5
+ mc.JMP_l(self.continue_addr - curpos)
+
+
class Assembler386(BaseAssembler, VectorAssemblerMixin):
_regalloc = None
_output_loop_log = None
@@ -76,6 +104,7 @@
BaseAssembler.setup(self, looptoken)
assert self.memcpy_addr != 0, "setup_once() not called?"
self.current_clt = looptoken.compiled_loop_token
+ self.pending_slowpaths = []
self.pending_guard_tokens = []
if WORD == 8:
self.pending_memoryerror_trampoline_from = []
@@ -90,6 +119,7 @@
self.frame_depth_to_patch = []
def teardown(self):
+ self.pending_slowpaths = None
self.pending_guard_tokens = None
if WORD == 8:
self.pending_memoryerror_trampoline_from = None
@@ -758,6 +788,9 @@
self.teardown_gcrefs_list()
def write_pending_failure_recoveries(self, regalloc):
+ # for each pending slowpath, generate it now
+ for sp in self.pending_slowpaths:
+ sp.generate(self)
# for each pending guard, generate the code of the recovery stub
# at the end of self.mc.
for tok in self.pending_guard_tokens:
@@ -2444,18 +2477,21 @@
# guard_no_exception too
self.previous_cond_call_jcond = j_location
+ class MallocCondSlowPath(SlowPath):
+ def generate_body(self, assembler, mc):
+ assembler.push_gcmap(mc, self.gcmap, store=True)
+ mc.CALL(imm(follow_jump(assembler.malloc_slowpath)))
+
def malloc_cond(self, nursery_free_adr, nursery_top_adr, size, gcmap):
assert size & (WORD-1) == 0 # must be correctly aligned
self.mc.MOV(ecx, heap(nursery_free_adr))
self.mc.LEA_rm(edx.value, (ecx.value, size))
self.mc.CMP(edx, heap(nursery_top_adr))
- # PPP FIX ME
- jna_location = self.mc.emit_forward_jump('NA') # patched later
- # save the gcmap
- self.push_gcmap(self.mc, gcmap, store=True)
- self.mc.CALL(imm(follow_jump(self.malloc_slowpath)))
- self.mc.patch_forward_jump(jna_location)
+ sp = self.MallocCondSlowPath(self.mc, rx86.Conditions['A'])
+ sp.gcmap = gcmap
self.mc.MOV(heap(nursery_free_adr), edx)
+ sp.set_continue_addr(self.mc)
+ self.pending_slowpaths.append(sp)
def malloc_cond_varsize_frame(self, nursery_free_adr, nursery_top_adr,
sizeloc, gcmap):
diff --git a/rpython/jit/backend/x86/regloc.py
b/rpython/jit/backend/x86/regloc.py
--- a/rpython/jit/backend/x86/regloc.py
+++ b/rpython/jit/backend/x86/regloc.py
@@ -373,7 +373,7 @@
class LocationCodeBuilder(object):
_mixin_ = True
- _scratch_register_value = 0 # 0 means 'unknown'
+ _scratch_register_value = -1 # -1 means 'unknown'
def _binaryop(name):
@@ -552,7 +552,7 @@
# If we are within a "reuse_scratch_register" block, we remember the
# last value we loaded to the scratch register and encode the address
# as an offset from that if we can
- if self._scratch_register_value != 0:
+ if self._scratch_register_value != -1:
offset = r_uint(addr) - r_uint(self._scratch_register_value)
offset = intmask(offset)
if rx86.fits_in_32bits(offset):
@@ -593,7 +593,7 @@
return (reg, scalereg, scale, ofs)
def _load_scratch(self, value):
- if self._scratch_register_value != 0:
+ if self._scratch_register_value != -1:
if self._scratch_register_value == value:
#print '_load_scratch(%x) [REUSED]' % (value,)
return
@@ -619,7 +619,7 @@
self.MOV_ri(X86_64_SCRATCH_REG.value, value)
def forget_scratch_register(self):
- self._scratch_register_value = 0
+ self._scratch_register_value = -1
def get_scratch_register_known_value(self):
return self._scratch_register_value
@@ -627,6 +627,11 @@
def restore_scratch_register_known_value(self, saved_value):
self._scratch_register_value = saved_value
+ def load_scratch_if_known(self, saved_value):
+ if saved_value != -1:
+ assert IS_X86_64
+ self._load_scratch(saved_value)
+
def trap(self):
self.INT3()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit