Author: Armin Rigo <[email protected]>
Branch: branch-prediction
Changeset: r90991:74361356084a
Date: 2017-04-06 16:45 +0200
http://bitbucket.org/pypy/pypy/changeset/74361356084a/

Log:    Move off-line the code to do COND_CALL. Move the following
        GUARD_NO_EXCEPTION, if any, together with that off-line code too

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
@@ -788,7 +788,9 @@
         self.teardown_gcrefs_list()
 
     def write_pending_failure_recoveries(self, regalloc):
-        # for each pending slowpath, generate it now
+        # for each pending slowpath, generate it now.  Note that this
+        # may occasionally add an extra guard_token in
+        # pending_guard_tokens, so it must be done before the next loop.
         for sp in self.pending_slowpaths:
             sp.generate(self)
         # for each pending guard, generate the code of the recovery stub
@@ -1191,9 +1193,9 @@
                                                     faillocs, frame_depth)
         genop_guard_list[guard_opnum](self, guard_op, guard_token,
                                       arglocs, resloc)
-        if not we_are_translated():
-            # must be added by the genop_guard_list[]()
-            assert guard_token is self.pending_guard_tokens[-1]
+        # this must usually have added guard_token as last element
+        # of self.pending_guard_tokens, but not always (see
+        # genop_guard_guard_no_exception)
 
     def load_effective_addr(self, sizereg, baseofs, scale, result, frm=imm0):
         self.mc.LEA(result, addr_add(frm, sizereg, baseofs, scale))
@@ -1733,22 +1735,21 @@
     genop_guard_guard_isnull = genop_guard_guard_false
 
     def genop_guard_guard_no_exception(self, guard_op, guard_token, locs, ign):
+        # If the previous operation was a COND_CALL, don't emit
+        # anything now.  Instead, we'll emit the GUARD_NO_EXCEPTION at
+        # the end of the slowpath in CondCallSlowPath.
+        if self._find_nearby_operation(-1).getopnum() in (
+                rop.COND_CALL, rop.COND_CALL_VALUE_I, rop.COND_CALL_VALUE_R):
+            sp = self.pending_slowpaths[-1]
+            assert isinstance(sp, self.CondCallSlowPath)
+            sp.guard_token_no_exception = guard_token
+        else:
+            self.generate_guard_no_exception(guard_token)
+
+    def generate_guard_no_exception(self, guard_token):
         self.mc.CMP(heap(self.cpu.pos_exception()), imm0)
         self.guard_success_cc = rx86.Conditions['Z']
         self.implement_guard(guard_token)
-        # If the previous operation was a COND_CALL, overwrite its conditional
-        # jump to jump over this GUARD_NO_EXCEPTION as well, if we can
-        if self._find_nearby_operation(-1).getopnum() in (
-                rop.COND_CALL, rop.COND_CALL_VALUE_I, rop.COND_CALL_VALUE_R):
-            j_location = self.previous_cond_call_jcond
-            try:
-                self.mc.patch_forward_jump(j_location)
-            except codebuf.ShortJumpTooFar:
-                pass    # ignore this case
-            else:
-                # succeeded: forget the saved value of the scratch
-                # register here
-                self.mc.forget_scratch_register()
 
     def genop_guard_guard_not_invalidated(self, guard_op, guard_token,
                                           locs, ign):
@@ -2422,64 +2423,75 @@
     def label(self):
         self._check_frame_depth_debug(self.mc)
 
+    class CondCallSlowPath(SlowPath):
+        guard_token_no_exception = None
+
+        def generate_body(self, assembler, mc):
+            assembler.push_gcmap(mc, self.gcmap, store=True)
+            #
+            # first save away the 4 registers from
+            # 'cond_call_register_arguments' plus the register 'eax'
+            base_ofs = assembler.cpu.get_baseofs_of_frame_field()
+            should_be_saved = assembler._regalloc.rm.reg_bindings.values()
+            restore_eax = False
+            for gpr in cond_call_register_arguments + [eax]:
+                if gpr not in should_be_saved or gpr is self.resloc:
+                    continue
+                v = gpr_reg_mgr_cls.all_reg_indexes[gpr.value]
+                mc.MOV_br(v * WORD + base_ofs, gpr.value)
+                if gpr is eax:
+                    restore_eax = True
+            #
+            # load the 0-to-4 arguments into these registers
+            from rpython.jit.backend.x86.jump import remap_frame_layout
+            arglocs = self.arglocs
+            remap_frame_layout(assembler, arglocs,
+                               cond_call_register_arguments[:len(arglocs)],
+                               X86_64_SCRATCH_REG if IS_X86_64 else None)
+            #
+            # load the constant address of the function to call into eax
+            mc.MOV(eax, self.imm_func)
+            #
+            # figure out which variant of cond_call_slowpath to call,
+            # and call it
+            callee_only = False
+            floats = False
+            if assembler._regalloc is not None:
+                for reg in assembler._regalloc.rm.reg_bindings.values():
+                    if reg not in assembler._regalloc.rm.save_around_call_regs:
+                        break
+                else:
+                    callee_only = True
+                if assembler._regalloc.xrm.reg_bindings:
+                    floats = True
+            cond_call_adr = assembler.cond_call_slowpath[floats*2 + 
callee_only]
+            mc.CALL(imm(follow_jump(cond_call_adr)))
+            # if this is a COND_CALL_VALUE, we need to move the result in place
+            resloc = self.resloc
+            if resloc is not None and resloc is not eax:
+                mc.MOV(resloc, eax)
+            # restoring the registers saved above, and doing pop_gcmap(), is
+            # left to the cond_call_slowpath helper.  We must only restore eax,
+            # if needed.
+            if restore_eax:
+                v = gpr_reg_mgr_cls.all_reg_indexes[eax.value]
+                mc.MOV_rb(eax.value, v * WORD + base_ofs)
+            #
+            # if needed, emit now the guard_no_exception
+            if self.guard_token_no_exception is not None:
+                assembler.generate_guard_no_exception(
+                             self.guard_token_no_exception)
+
     def cond_call(self, gcmap, imm_func, arglocs, resloc=None):
         assert self.guard_success_cc >= 0
-        # PPP FIX ME
-        j_location = self.mc.emit_forward_jump_cond(
-            rx86.invert_condition(self.guard_success_cc))
+        sp = self.CondCallSlowPath(self.mc, self.guard_success_cc)
+        sp.set_continue_addr(self.mc)
         self.guard_success_cc = rx86.cond_none
-        #
-        self.push_gcmap(self.mc, gcmap, store=True)
-        #
-        # first save away the 4 registers from 'cond_call_register_arguments'
-        # plus the register 'eax'
-        base_ofs = self.cpu.get_baseofs_of_frame_field()
-        should_be_saved = self._regalloc.rm.reg_bindings.values()
-        restore_eax = False
-        for gpr in cond_call_register_arguments + [eax]:
-            if gpr not in should_be_saved or gpr is resloc:
-                continue
-            v = gpr_reg_mgr_cls.all_reg_indexes[gpr.value]
-            self.mc.MOV_br(v * WORD + base_ofs, gpr.value)
-            if gpr is eax:
-                restore_eax = True
-        #
-        # load the 0-to-4 arguments into these registers
-        from rpython.jit.backend.x86.jump import remap_frame_layout
-        remap_frame_layout(self, arglocs,
-                           cond_call_register_arguments[:len(arglocs)],
-                           X86_64_SCRATCH_REG if IS_X86_64 else None)
-        #
-        # load the constant address of the function to call into eax
-        self.mc.MOV(eax, imm_func)
-        #
-        # figure out which variant of cond_call_slowpath to call, and call it
-        callee_only = False
-        floats = False
-        if self._regalloc is not None:
-            for reg in self._regalloc.rm.reg_bindings.values():
-                if reg not in self._regalloc.rm.save_around_call_regs:
-                    break
-            else:
-                callee_only = True
-            if self._regalloc.xrm.reg_bindings:
-                floats = True
-        cond_call_adr = self.cond_call_slowpath[floats * 2 + callee_only]
-        self.mc.CALL(imm(follow_jump(cond_call_adr)))
-        # if this is a COND_CALL_VALUE, we need to move the result in place
-        if resloc is not None and resloc is not eax:
-            self.mc.MOV(resloc, eax)
-        # restoring the registers saved above, and doing pop_gcmap(), is left
-        # to the cond_call_slowpath helper.  We must only restore eax, if
-        # needed.
-        if restore_eax:
-            v = gpr_reg_mgr_cls.all_reg_indexes[eax.value]
-            self.mc.MOV_rb(eax.value, v * WORD + base_ofs)
-        #
-        self.mc.patch_forward_jump(j_location)
-        # might be overridden again to skip over the following
-        # guard_no_exception too
-        self.previous_cond_call_jcond = j_location
+        sp.gcmap = gcmap
+        sp.imm_func = imm_func
+        sp.arglocs = arglocs
+        sp.resloc = resloc
+        self.pending_slowpaths.append(sp)
 
     class MallocCondSlowPath(SlowPath):
         def generate_body(self, assembler, mc):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to