[pypy-commit] pypy s390x-backend: saving f8 through f15 before entering the jit and restoring it before exiting it. (ABI demands this)
plan_rich
pypy.commits at gmail.com
Wed Feb 10 06:44:43 EST 2016
Author: Richard Plangger <planrichi at gmail.com>
Branch: s390x-backend
Changeset: r82140:6cf6a1b5353a
Date: 2016-02-10 12:43 +0100
http://bitbucket.org/pypy/pypy/changeset/6cf6a1b5353a/
Log: saving f8 through f15 before entering the jit and restoring it
before exiting it. (ABI demands this)
diff --git a/rpython/jit/backend/zarch/arch.py b/rpython/jit/backend/zarch/arch.py
--- a/rpython/jit/backend/zarch/arch.py
+++ b/rpython/jit/backend/zarch/arch.py
@@ -83,3 +83,9 @@
JUMPABS_TARGET_ADDR__POOL_OFFSET = 0
JUMPABS_POOL_ADDR_POOL_OFFSET = 8
+
+# r8 through r15 are saved registers (= non volatile)
+# thus when entering the jit, we do not know if those
+# are overwritten in the jit. save them using some extra
+# stack space!
+JIT_ENTER_EXTRA_STACK_SPACE = 8*8
diff --git a/rpython/jit/backend/zarch/assembler.py b/rpython/jit/backend/zarch/assembler.py
--- a/rpython/jit/backend/zarch/assembler.py
+++ b/rpython/jit/backend/zarch/assembler.py
@@ -17,7 +17,7 @@
STD_FRAME_SIZE_IN_BYTES, THREADLOCAL_ADDR_OFFSET,
RECOVERY_GCMAP_POOL_OFFSET, RECOVERY_TARGET_POOL_OFFSET,
JUMPABS_TARGET_ADDR__POOL_OFFSET, JUMPABS_POOL_ADDR_POOL_OFFSET,
- THREADLOCAL_ON_ENTER_JIT)
+ THREADLOCAL_ON_ENTER_JIT, JIT_ENTER_EXTRA_STACK_SPACE)
from rpython.jit.backend.zarch.opassembler import OpAssembler
from rpython.jit.backend.zarch.regalloc import Regalloc
from rpython.jit.codewriter.effectinfo import EffectInfo
@@ -50,6 +50,7 @@
self.gcrootmap_retaddr_forced = 0
self.failure_recovery_code = [0, 0, 0, 0]
self.wb_slowpath = [0,0,0,0,0]
+ self.pool = None
def setup(self, looptoken):
BaseAssembler.setup(self, looptoken)
@@ -57,7 +58,8 @@
if we_are_translated():
self.debug = False
self.current_clt = looptoken.compiled_loop_token
- self.mc = InstrBuilder()
+ self.pool = LiteralPool()
+ self.mc = InstrBuilder(self.pool)
self.pending_guard_tokens = []
self.pending_guard_tokens_recovered = 0
#assert self.datablockwrapper is None --- but obscure case
@@ -68,7 +70,6 @@
self.mc.datablockwrapper = self.datablockwrapper
self.target_tokens_currently_compiling = {}
self.frame_depth_to_patch = []
- self.pool = LiteralPool()
def teardown(self):
self.pending_guard_tokens = None
@@ -91,7 +92,7 @@
self.mc.BCR_rr(0xf, register.value)
def _build_failure_recovery(self, exc, withfloats=False):
- mc = InstrBuilder()
+ mc = InstrBuilder(self.pool)
self.mc = mc
# fill in the jf_descr and jf_gcmap fields of the frame according
# to which failure we are resuming from. These are set before
@@ -202,6 +203,7 @@
mc.LAY(r.SP, l.addr(-extra_stack_size, r.SP))
mc.STMG(r.r10, r.r12, l.addr(off, r.SP))
mc.STG(r.r2, l.addr(off+3*WORD, r.SP))
+ # OK to use STD, because offset is not negative
mc.STD(r.f0, l.addr(off+4*WORD, r.SP))
saved_regs = None
saved_fp_regs = None
@@ -1008,14 +1010,22 @@
def _call_header(self):
# Build a new stackframe of size STD_FRAME_SIZE_IN_BYTES
- self.mc.STMG(r.r6, r.r15, l.addr(6*WORD, r.SP))
+ fpoff = JIT_ENTER_EXTRA_STACK_SPACE
+ self.mc.STMG(r.r6, r.r15, l.addr(-fpoff+6*WORD, r.SP))
self.mc.LARL(r.POOL, l.halfword(self.pool.pool_start - self.mc.get_relative_pos()))
+ # f8 through f15 are saved registers (= non volatile)
+ # TODO it would be good to detect if any float is used in the loop
+ # and to skip this push/pop whenever no float operation occurs
+ for i,reg in enumerate(range(8,16)):
+ off = -fpoff + STD_FRAME_SIZE_IN_BYTES
+ assert off > 0
+ self.mc.STD_rx(reg, l.addr(off + i*8, r.SP))
# save r3, the second argument, to the thread local position
self.mc.STG(r.r3, l.addr(THREADLOCAL_ON_ENTER_JIT, r.SP))
- # push a standard frame for any call
- self.mc.push_std_frame()
+ # push a standard frame for any within the jit trace
+ self.mc.push_std_frame(fpoff)
# move the first argument to SPP: the jitframe object
self.mc.LGR(r.SPP, r.r2)
@@ -1060,8 +1070,13 @@
if gcrootmap and gcrootmap.is_shadow_stack:
self._call_footer_shadowstack(gcrootmap)
+ size = STD_FRAME_SIZE_IN_BYTES
+ # f8 through f15 are saved registers (= non volatile)
+ # TODO it would be good to detect if any float is used in the loop
+ # and to skip this push/pop whenever no float operation occurs
+ for i,reg in enumerate(range(8,16)):
+ self.mc.LD_rx(reg, l.addr(size + size + i*8, r.SP))
# restore registers r6-r15
- size = STD_FRAME_SIZE_IN_BYTES
self.mc.LMG(r.r6, r.r15, l.addr(size+6*WORD, r.SP))
self.jmpto(r.r14)
diff --git a/rpython/jit/backend/zarch/codebuilder.py b/rpython/jit/backend/zarch/codebuilder.py
--- a/rpython/jit/backend/zarch/codebuilder.py
+++ b/rpython/jit/backend/zarch/codebuilder.py
@@ -69,9 +69,10 @@
RAW_CALL_REG = r.r14
- def __init__(self):
+ def __init__(self, pool=None):
AbstractZARCHBuilder.__init__(self)
self.init_block_builder()
+ self.pool = pool
#
# ResOperation --> offset in the assembly.
# ops_offset[None] represents the beginning of the code after the last op
@@ -173,6 +174,9 @@
elif -2**31 <= word <= 2**31-1:
self.LGFI(dest_reg, l.imm(word))
else:
+ if self.pool and self.pool.contains_constant(word):
+ self.LG(dest_reg, l.pool(self.pool.get_direct_offset(word)))
+ return
# this is not put into the constant pool, because it
# is an immediate value that cannot easily be forseen
self.IILF(dest_reg, l.imm(word & 0xFFFFffff))
diff --git a/rpython/jit/backend/zarch/pool.py b/rpython/jit/backend/zarch/pool.py
--- a/rpython/jit/backend/zarch/pool.py
+++ b/rpython/jit/backend/zarch/pool.py
@@ -95,6 +95,9 @@
if arg.is_constant():
self.reserve_literal(8, arg)
+ def contains_constant(self, unique_val):
+ return unique_val in self.offset_map
+
def get_descr_offset(self, descr):
return self.offset_descr[descr]
@@ -105,6 +108,11 @@
assert self.offset_map[uvalue] >= 0
return self.offset_map[uvalue]
+ def get_direct_offset(self, unique_val):
+ """ Get the offset directly using a unique value,
+ use get_offset if you have a Const box """
+ return self.offset_map[unique_val]
+
def unique_value(self, val):
if val.type == FLOAT:
if val.getfloat() == 0.0:
@@ -170,6 +178,8 @@
self.pool_start = asm.mc.get_relative_pos()
for op in operations:
self.ensure_can_hold_constants(asm, op)
+ self.ensure_value(asm.cpu.pos_exc_value())
+ # TODO add more values that are loaded with load_imm
if self.size == 0:
# no pool needed!
return
diff --git a/rpython/jit/backend/zarch/test/test_calling_convention.py b/rpython/jit/backend/zarch/test/test_calling_convention.py
--- a/rpython/jit/backend/zarch/test/test_calling_convention.py
+++ b/rpython/jit/backend/zarch/test/test_calling_convention.py
@@ -5,7 +5,7 @@
import rpython.jit.backend.zarch.conditions as c
-class TestPPCCallingConvention(CallingConvTests):
+class TestZARCHCallingConvention(CallingConvTests):
# ../../test/calling_convention_test.py
def make_function_returning_stack_pointer(self):
More information about the pypy-commit
mailing list