[pypy-commit] pypy s390x-backend: adding trap2 instruction, skeletal structure to assemble a bridge, allocating additional space in pool if a 64bit jump is needed (e.g. bridge jump to loop token of already compiled loop)

plan_rich noreply at buildbot.pypy.org
Mon Nov 2 06:25:47 EST 2015


Author: Richard Plangger <planrichi at gmail.com>
Branch: s390x-backend
Changeset: r80499:468121ce68fa
Date: 2015-11-02 12:25 +0100
http://bitbucket.org/pypy/pypy/changeset/468121ce68fa/

Log:	adding trap2 instruction, skeletal structure to assemble a bridge,
	allocating additional space in pool if a 64bit jump is needed (e.g.
	bridge jump to loop token of already compiled loop)

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
@@ -210,6 +210,8 @@
             del looptoken._x86_ops_offset # else it's kept alive
         if hasattr(looptoken, '_ppc_ops_offset'):
             del looptoken._ppc_ops_offset # else it's kept alive
+        if hasattr(looptoken, '_zarch_ops_offset'):
+            del looptoken._ppc_ops_offset # else it's kept alive
         del loop
         gc.collect()
         assert not wr_i1() and not wr_guard()
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
@@ -25,6 +25,7 @@
 from rpython.rlib import rgc
 from rpython.rlib.longlong2float import float2longlong
 from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
+from rpython.rlib.jit import AsmInfo
 
 class AssemblerZARCH(BaseAssembler,
         IntOpAssembler, FloatOpAssembler,
@@ -201,6 +202,25 @@
             mc.cmp_op(0, r.SCRATCH.value, r.SCRATCH2.value, signed=False)
             mc.bgtctrl()
 
+    def _check_frame_depth(self, mc, gcmap):
+        """ check if the frame is of enough depth to follow this bridge.
+        Otherwise reallocate the frame in a helper.
+        """
+        descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
+        ofs = self.cpu.unpack_fielddescr(descrs.arraydescr.lendescr)
+        mc.LG(r.r2, l.addr(ofs, r.SPP))
+        patch_pos = mc.currpos()
+        mc.TRAP2()     # placeholder for cmpdi(0, r2, ...)
+        mc.TRAP2()     # placeholder for bge
+        mc.TRAP2()     # placeholder for li(r0, ...)
+        #mc.load_imm(r.SCRATCH2, self._frame_realloc_slowpath)
+        #mc.mtctr(r.SCRATCH2.value)
+        #self.load_gcmap(mc, r.r2, gcmap)
+        #mc.bctrl()
+
+        self.frame_depth_to_patch.append((patch_pos, mc.currpos()))
+
+
     @rgc.no_release_gil
     def assemble_loop(self, jd_id, unique_id, logger, loopname, inputargs,
                       operations, looptoken, log):
@@ -228,7 +248,7 @@
         operations = regalloc.prepare_loop(inputargs, operations,
                                            looptoken, clt.allgcrefs)
         looppos = self.mc.get_relative_pos()
-        self.pool.pre_assemble(self.mc, operations)
+        self.pool.pre_assemble(self, operations)
         frame_depth_no_fixed_size = self._assemble(regalloc, inputargs,
                                                    operations)
         self.update_frame_depth(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE)
@@ -262,6 +282,64 @@
             logger.log_loop(inputargs, operations, 0, "rewritten",
                             name=loopname, ops_offset=ops_offset)
 
+        self.fixup_target_tokens(rawstart)
+        self.teardown()
+        # oprofile support
+        #if self.cpu.profile_agent is not None:
+        #    name = "Loop # %s: %s" % (looptoken.number, loopname)
+        #    self.cpu.profile_agent.native_code_written(name,
+        #                                               rawstart, full_size)
+        return AsmInfo(ops_offset, rawstart + looppos,
+                       size_excluding_failure_stuff - looppos)
+
+    @rgc.no_release_gil
+    def assemble_bridge(self, faildescr, inputargs, operations,
+                        original_loop_token, log, logger):
+        if not we_are_translated():
+            # Arguments should be unique
+            assert len(set(inputargs)) == len(inputargs)
+
+        self.setup(original_loop_token)
+        descr_number = compute_unique_id(faildescr)
+        if log:
+            operations = self._inject_debugging_code(faildescr, operations,
+                                                     'b', descr_number)
+
+        arglocs = self.rebuild_faillocs_from_descr(faildescr, inputargs)
+        regalloc = Regalloc(assembler=self)
+        startpos = self.mc.get_relative_pos()
+        operations = regalloc.prepare_bridge(inputargs, arglocs,
+                                             operations,
+                                             self.current_clt.allgcrefs,
+                                             self.current_clt.frame_info)
+        self._check_frame_depth(self.mc, regalloc.get_gcmap())
+        frame_depth_no_fixed_size = self._assemble(regalloc, inputargs, operations)
+        codeendpos = self.mc.get_relative_pos()
+        self.write_pending_failure_recoveries()
+        fullsize = self.mc.get_relative_pos()
+        #
+        self.patch_stack_checks(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE)
+        rawstart = self.materialize_loop(original_loop_token)
+        debug_bridge(descr_number, rawstart, codeendpos)
+        self.patch_pending_failure_recoveries(rawstart)
+        # patch the jump from original guard
+        self.patch_jump_for_descr(faildescr, rawstart)
+        ops_offset = self.mc.ops_offset
+        frame_depth = max(self.current_clt.frame_info.jfi_frame_depth,
+                          frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE)
+        if logger:
+            logger.log_bridge(inputargs, operations, "rewritten",
+                              ops_offset=ops_offset)
+        self.fixup_target_tokens(rawstart)
+        self.update_frame_depth(frame_depth)
+        self.teardown()
+        return AsmInfo(ops_offset, startpos + rawstart, codeendpos - startpos)
+
+    def fixup_target_tokens(self, rawstart):
+        for targettoken in self.target_tokens_currently_compiling:
+            targettoken._ll_loop_code += rawstart
+        self.target_tokens_currently_compiling = None
+
     def _assemble(self, regalloc, inputargs, operations):
         self._regalloc = regalloc
         self.guard_success_cc = c.cond_none
diff --git a/rpython/jit/backend/zarch/instruction_builder.py b/rpython/jit/backend/zarch/instruction_builder.py
--- a/rpython/jit/backend/zarch/instruction_builder.py
+++ b/rpython/jit/backend/zarch/instruction_builder.py
@@ -45,6 +45,8 @@
                 self.counter += 4
         def impl(func):
             func._arguments_ = args_str.split(',')
+            if args_str == '':
+                func._arguments_ = []
             args = [dummy_argument(a) for a in func._arguments_]
             c = Counter()
             # invoke it once and get the amount of bytes
@@ -103,6 +105,13 @@
     mc.writechar(chr(byte))
     mc.writechar(chr(displace & 0xff))
 
+def build_e(mnemonic, (opcode1,opcode2)):
+    @builder.arguments('')
+    def encode_e(self):
+        self.writechar(opcode1)
+        self.writechar(opcode2)
+    return encode_e
+
 def build_i(mnemonic, (opcode,)):
     @builder.arguments('u8')
     def encode_i(self, imm):
diff --git a/rpython/jit/backend/zarch/instructions.py b/rpython/jit/backend/zarch/instructions.py
--- a/rpython/jit/backend/zarch/instructions.py
+++ b/rpython/jit/backend/zarch/instructions.py
@@ -168,6 +168,7 @@
     'CDB':     ('rxe',   ['\xED','\x19'], 'r,bidl,-'),
 }
 
+# MISC
 all_mnemonic_codes = {
     #
     'BXH':     ('rs',    ['\x86']),
@@ -184,6 +185,7 @@
     'PKA':     ('ssf',   ['\xE9']),
 
     'SVC':     ('i',     ['\x0A']),
+    'TRAP2':   ('e',     ['\x01','\xFF']),
 }
 all_mnemonic_codes.update(arith_mnemonic_codes)
 all_mnemonic_codes.update(logic_mnemonic_codes)
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
@@ -13,12 +13,17 @@
         self.pool_start = 0
         self.offset_map = {}
 
-    def ensure_can_hold_constants(self, op):
+    def ensure_can_hold_constants(self, asm, op):
         if op.is_guard():
             # 1x gcmap pointer
             # 1x target address
             self.offset_map[op.getdescr()] = self.size
             self.reserve_literal(2 * 8)
+        if op.getopnum() == rop.JUMP:
+            descr = op.getdescr()
+            if descr not in asm.target_tokens_currently_compiling:
+                # this is a 'long' jump instead of a relative jump
+                self.reserve_literal(8)
         for arg in op.getarglist():
             if arg.is_constant():
                 self.offset_map[arg] = self.size
@@ -33,7 +38,8 @@
         self.size = 0
         self.offset = 0
 
-    def walk_operations(self, operations):
+    def pre_assemble(self, asm, operations):
+        self.reset()
         # O(len(operations)). I do not think there is a way
         # around this.
         #
@@ -49,20 +55,16 @@
         # located at register r13. This one can easily offset with 20
         # bit signed values (should be enough)
         for op in operations:
-            self.ensure_can_hold_constants(op)
-
-    def pre_assemble(self, mc, operations):
-        self.reset()
-        self.walk_operations(operations)
+            self.ensure_can_hold_constants(asm, op)
         if self.size == 0:
             # no pool needed!
             return
         if self.size % 2 == 1:
             self.size += 1
         assert self.size < 2**16-1
-        mc.BRAS(r.POOL, l.imm(self.size+mc.BRAS._byte_count))
+        asm.mc.BRAS(r.POOL, l.imm(self.size+mc.BRAS._byte_count))
         self.pool_start = mc.get_relative_pos()
-        mc.write('\x00' * self.size)
+        asm.mc.write('\x00' * self.size)
         print "pool with %d quad words" % (self.size // 8)
 
     def overwrite_64(self, mc, index, value):
diff --git a/rpython/jit/backend/zarch/runner.py b/rpython/jit/backend/zarch/runner.py
--- a/rpython/jit/backend/zarch/runner.py
+++ b/rpython/jit/backend/zarch/runner.py
@@ -38,3 +38,11 @@
     @rgc.no_release_gil
     def finish_once(self):
         self.assembler.finish_once()
+
+    def compile_bridge(self, faildescr, inputargs, operations,
+                       original_loop_token, log=True, logger=None):
+        clt = original_loop_token.compiled_loop_token
+        clt.compiling_a_bridge()
+        return self.assembler.assemble_bridge(faildescr, inputargs, operations,
+                                              original_loop_token, log, logger)
+


More information about the pypy-commit mailing list