[pypy-commit] pypy ppc-updated-backend: PPC Backend #7: PyPy Translation

arigo noreply at buildbot.pypy.org
Fri Oct 9 15:06:45 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: ppc-updated-backend
Changeset: r80083:69f522aef55b
Date: 2015-10-09 15:01 +0200
http://bitbucket.org/pypy/pypy/changeset/69f522aef55b/

Log:	PPC Backend #7: PyPy Translation

	All tests pass, and a full PyPy translation works. Some hard gdb-
	ing but not too bad.

diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -913,7 +913,7 @@
             descr.adr_jump_offset = failure_recovery_pos
             relative_offset = tok.pos_recovery_stub - tok.offset
             guard_pos = block_start + tok.offset
-            if not tok.is_guard_not_invalidated:
+            if not tok.guard_not_invalidated():
                 # patch the guard jump to the stub
                 # overwrite the generate NOP with a B_offs to the pos of the
                 # stub
diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -36,11 +36,9 @@
 
 class ArmGuardToken(GuardToken):
     def __init__(self, cpu, gcmap, faildescr, failargs, fail_locs,
-                 offset, exc, frame_depth, is_guard_not_invalidated=False,
-                 is_guard_not_forced=False, fcond=c.AL):
+                 offset, guard_opnum, frame_depth, fcond=c.AL):
         GuardToken.__init__(self, cpu, gcmap, faildescr, failargs, fail_locs,
-                            exc, frame_depth, is_guard_not_invalidated,
-                            is_guard_not_forced)
+                            guard_opnum, frame_depth)
         self.fcond = fcond
         self.offset = offset
 
@@ -175,10 +173,7 @@
         self.mc.RSB_ri(resloc.value, l0.value, imm=0)
         return fcond
 
-    def build_guard_token(self, op, frame_depth, arglocs, offset, fcond, save_exc,
-                                    is_guard_not_invalidated=False,
-                                    is_guard_not_forced=False):
-        assert isinstance(save_exc, bool)
+    def build_guard_token(self, op, frame_depth, arglocs, offset, fcond):
         assert isinstance(fcond, int)
         descr = op.getdescr()
         assert isinstance(descr, AbstractFailDescr)
@@ -189,16 +184,12 @@
                                     failargs=op.getfailargs(),
                                     fail_locs=arglocs,
                                     offset=offset,
-                                    exc=save_exc,
+                                    guard_opnum=op.getopnum(),
                                     frame_depth=frame_depth,
-                                    is_guard_not_invalidated=is_guard_not_invalidated,
-                                    is_guard_not_forced=is_guard_not_forced,
                                     fcond=fcond)
         return token
 
-    def _emit_guard(self, op, arglocs, save_exc,
-                                    is_guard_not_invalidated=False,
-                                    is_guard_not_forced=False):
+    def _emit_guard(self, op, arglocs, is_guard_not_invalidated=False):
         if is_guard_not_invalidated:
             fcond = c.cond_none
         else:
@@ -206,10 +197,9 @@
             self.guard_success_cc = c.cond_none
             assert fcond != c.cond_none
         pos = self.mc.currpos()
-        token = self.build_guard_token(op, arglocs[0].value, arglocs[1:], pos, fcond, save_exc,
-                                        is_guard_not_invalidated,
-                                        is_guard_not_forced)
+        token = self.build_guard_token(op, arglocs[0].value, arglocs[1:], pos, fcond)
         self.pending_guards.append(token)
+        assert token.guard_not_invalidated() == is_guard_not_invalidated
         # For all guards that are not GUARD_NOT_INVALIDATED we emit a
         # breakpoint to ensure the location is patched correctly. In the case
         # of GUARD_NOT_INVALIDATED we use just a NOP, because it is only
@@ -221,12 +211,12 @@
         return c.AL
 
     def emit_op_guard_true(self, op, arglocs, regalloc, fcond):
-        fcond = self._emit_guard(op, arglocs, save_exc=False)
+        fcond = self._emit_guard(op, arglocs)
         return fcond
 
     def emit_op_guard_false(self, op, arglocs, regalloc, fcond):
         self.guard_success_cc = c.get_opposite_of(self.guard_success_cc)
-        fcond = self._emit_guard(op, arglocs, save_exc=False)
+        fcond = self._emit_guard(op, arglocs)
         return fcond
 
     def emit_op_guard_value(self, op, arglocs, regalloc, fcond):
@@ -244,7 +234,7 @@
             self.mc.VCMP(l0.value, l1.value)
             self.mc.VMRS(cond=fcond)
         self.guard_success_cc = c.EQ
-        fcond = self._emit_guard(op, failargs, save_exc=False)
+        fcond = self._emit_guard(op, failargs)
         return fcond
 
     emit_op_guard_nonnull = emit_op_guard_true
@@ -256,14 +246,14 @@
     def emit_op_guard_class(self, op, arglocs, regalloc, fcond):
         self._cmp_guard_class(op, arglocs, regalloc, fcond)
         self.guard_success_cc = c.EQ
-        self._emit_guard(op, arglocs[2:], save_exc=False)
+        self._emit_guard(op, arglocs[2:])
         return fcond
 
     def emit_op_guard_nonnull_class(self, op, arglocs, regalloc, fcond):
         self.mc.CMP_ri(arglocs[0].value, 1)
         self._cmp_guard_class(op, arglocs, regalloc, c.HS)
         self.guard_success_cc = c.EQ
-        self._emit_guard(op, arglocs[2:], save_exc=False)
+        self._emit_guard(op, arglocs[2:])
         return fcond
 
     def _cmp_guard_class(self, op, locs, regalloc, fcond):
@@ -288,7 +278,7 @@
     def emit_op_guard_gc_type(self, op, arglocs, regalloc, fcond):
         self._cmp_guard_gc_type(arglocs[0], arglocs[1].value, fcond)
         self.guard_success_cc = c.EQ
-        self._emit_guard(op, arglocs[2:], save_exc=False)
+        self._emit_guard(op, arglocs[2:])
         return fcond
 
     def emit_op_guard_is_object(self, op, arglocs, regalloc, fcond):
@@ -309,7 +299,7 @@
         self.mc.LDRB_rr(r.ip.value, r.ip.value, r.lr.value)
         self.mc.TST_ri(r.ip.value, imm=(IS_OBJECT_FLAG & 0xff))
         self.guard_success_cc = c.NE
-        self._emit_guard(op, arglocs[1:], save_exc=False)
+        self._emit_guard(op, arglocs[1:])
         return fcond
 
     def emit_op_guard_subclass(self, op, arglocs, regalloc, fcond):
@@ -353,12 +343,11 @@
             self.mc.CMP_rr(r.ip.value, r.lr.value)
         # the guard passes if we get a result of "below or equal"
         self.guard_success_cc = c.LS
-        self._emit_guard(op, arglocs[2:], save_exc=False)
+        self._emit_guard(op, arglocs[2:])
         return fcond
 
     def emit_op_guard_not_invalidated(self, op, locs, regalloc, fcond):
-        return self._emit_guard(op, locs, save_exc=False,
-                                            is_guard_not_invalidated=True)
+        return self._emit_guard(op, locs, is_guard_not_invalidated=True)
 
     def emit_op_label(self, op, arglocs, regalloc, fcond):
         self._check_frame_depth_debug(self.mc)
@@ -498,7 +487,7 @@
         self.mc.LDR_ri(loc.value, loc.value)
         self.mc.CMP_ri(loc.value, 0)
         self.guard_success_cc = c.EQ
-        fcond = self._emit_guard(op, failargs, save_exc=True)
+        fcond = self._emit_guard(op, failargs)
         # 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() == rop.COND_CALL:
@@ -515,7 +504,7 @@
 
         self.mc.CMP_rr(r.ip.value, loc.value)
         self.guard_success_cc = c.EQ
-        self._emit_guard(op, failargs, save_exc=True)
+        self._emit_guard(op, failargs)
         self._store_and_reset_exception(self.mc, resloc)
         return fcond
 
@@ -1047,7 +1036,7 @@
 
     def store_force_descr(self, op, fail_locs, frame_depth):
         pos = self.mc.currpos()
-        guard_token = self.build_guard_token(op, frame_depth, fail_locs, pos, c.AL, True, False, True)
+        guard_token = self.build_guard_token(op, frame_depth, fail_locs, pos, c.AL)
         #self.pending_guards.append(guard_token)
         self._finish_gcmap = guard_token.gcmap
         self._store_force_index(op)
@@ -1152,7 +1141,7 @@
         self.mc.LDR_ri(r.ip.value, r.fp.value, imm=ofs)
         self.mc.CMP_ri(r.ip.value, 0)
         self.guard_success_cc = c.EQ
-        self._emit_guard(op, arglocs, save_exc=True, is_guard_not_forced=True)
+        self._emit_guard(op, arglocs)
         return fcond
 
     def _genop_call_may_force(self, op, arglocs, regalloc, fcond):
diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py
--- a/rpython/jit/backend/llsupport/assembler.py
+++ b/rpython/jit/backend/llsupport/assembler.py
@@ -23,8 +23,8 @@
 
 
 class GuardToken(object):
-    def __init__(self, cpu, gcmap, faildescr, failargs, fail_locs, exc,
-                 frame_depth, is_guard_not_invalidated, is_guard_not_forced):
+    def __init__(self, cpu, gcmap, faildescr, failargs, fail_locs,
+                 guard_opnum, frame_depth):
         assert isinstance(faildescr, AbstractFailDescr)
         self.cpu = cpu
         self.faildescr = faildescr
@@ -32,9 +32,16 @@
         self.fail_locs = fail_locs
         self.gcmap = self.compute_gcmap(gcmap, failargs,
                                         fail_locs, frame_depth)
-        self.exc = exc
-        self.is_guard_not_invalidated = is_guard_not_invalidated
-        self.is_guard_not_forced = is_guard_not_forced
+        self.guard_opnum = guard_opnum
+
+    def guard_not_invalidated(self):
+        return self.guard_opnum == rop.GUARD_NOT_INVALIDATED
+
+    def must_save_exception(self):
+        guard_opnum = self.guard_opnum
+        return (guard_opnum == rop.GUARD_EXCEPTION or
+                guard_opnum == rop.GUARD_NO_EXCEPTION or
+                guard_opnum == rop.GUARD_NOT_FORCED)
 
     def compute_gcmap(self, gcmap, failargs, fail_locs, frame_depth):
         # note that regalloc has a very similar compute, but
@@ -172,7 +179,7 @@
             if box is not None and box.type == FLOAT:
                 withfloats = True
                 break
-        exc = guardtok.exc
+        exc = guardtok.must_save_exception()
         target = self.failure_recovery_code[exc + 2 * withfloats]
         fail_descr = cast_instance_to_gcref(guardtok.faildescr)
         fail_descr = rffi.cast(lltype.Signed, fail_descr)
diff --git a/rpython/jit/backend/ppc/arch.py b/rpython/jit/backend/ppc/arch.py
--- a/rpython/jit/backend/ppc/arch.py
+++ b/rpython/jit/backend/ppc/arch.py
@@ -70,7 +70,8 @@
 LR_BC_OFFSET            = 16
 _GAP                    = 0 if IS_BIG_ENDIAN else 16
 PARAM_SAVE_AREA_OFFSET  = 48 - _GAP
-THREADLOCAL_ADDR_OFFSET = 112 - _GAP
+LOCAL_VARS_OFFSET       = 112 - _GAP
+THREADLOCAL_ADDR_OFFSET = LOCAL_VARS_OFFSET
 GPR_SAVE_AREA_OFFSET    = 120 - _GAP
 
 REGISTERS_SAVED         = [r.r25, r.r26, r.r27, r.r28, r.r29, r.r30, r.r31]
diff --git a/rpython/jit/backend/ppc/callbuilder.py b/rpython/jit/backend/ppc/callbuilder.py
--- a/rpython/jit/backend/ppc/callbuilder.py
+++ b/rpython/jit/backend/ppc/callbuilder.py
@@ -124,9 +124,9 @@
         gcrootmap = self.asm.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:
             if gcrootmap.is_shadow_stack and self.is_call_release_gil:
-                # in this mode, 'ebx' happens to contain the shadowstack
+                # in this mode, RSHADOWOLD happens to contain the shadowstack
                 # top at this point, so reuse it instead of loading it again
-                ssreg = self.RSHADOWPTR
+                ssreg = self.RSHADOWOLD
         self.asm._reload_frame_if_necessary(self.mc, shadowstack_reg=ssreg)
 
     def emit_raw_call(self):
diff --git a/rpython/jit/backend/ppc/codebuilder.py b/rpython/jit/backend/ppc/codebuilder.py
--- a/rpython/jit/backend/ppc/codebuilder.py
+++ b/rpython/jit/backend/ppc/codebuilder.py
@@ -936,11 +936,9 @@
 
 class PPCGuardToken(GuardToken):
     def __init__(self, cpu, gcmap, descr, failargs, faillocs,
-                 exc, frame_depth, is_guard_not_invalidated=False,
-                 is_guard_not_forced=False, fcond=c.cond_none):
-        GuardToken.__init__(self, cpu, gcmap, descr, failargs, faillocs, exc,
-                            frame_depth, is_guard_not_invalidated,
-                            is_guard_not_forced)
+                 guard_opnum, frame_depth, fcond=c.cond_none):
+        GuardToken.__init__(self, cpu, gcmap, descr, failargs, faillocs,
+                            guard_opnum, frame_depth)
         self.fcond = fcond
 
 
diff --git a/rpython/jit/backend/ppc/opassembler.py b/rpython/jit/backend/ppc/opassembler.py
--- a/rpython/jit/backend/ppc/opassembler.py
+++ b/rpython/jit/backend/ppc/opassembler.py
@@ -254,9 +254,7 @@
 
     _mixin_ = True
 
-    def _emit_guard(self, op, arglocs, save_exc=False,
-                    is_guard_not_invalidated=False,
-                    is_guard_not_forced=False):
+    def _emit_guard(self, op, arglocs, is_guard_not_invalidated=False):
         if is_guard_not_invalidated:
             fcond = c.cond_none
         else:
@@ -264,22 +262,18 @@
             self.guard_success_cc = c.cond_none
             assert fcond != c.cond_none
             fcond = c.negate(fcond)
-        token = self.build_guard_token(op, arglocs[0].value, arglocs[1:],
-                                       fcond, save_exc, is_guard_not_invalidated,
-                                       is_guard_not_forced)
+        token = self.build_guard_token(op, arglocs[0].value, arglocs[1:], fcond)
         token.pos_jump_offset = self.mc.currpos()
+        assert token.guard_not_invalidated() == is_guard_not_invalidated
         if not is_guard_not_invalidated:
             self.mc.trap()     # has to be patched later on
         self.pending_guard_tokens.append(token)
 
-    def build_guard_token(self, op, frame_depth, arglocs, fcond, save_exc,
-                          is_guard_not_invalidated=False,
-                          is_guard_not_forced=False):
+    def build_guard_token(self, op, frame_depth, arglocs, fcond):
         descr = op.getdescr()
         gcmap = allocate_gcmap(self, frame_depth, r.JITFRAME_FIXED_SIZE)
         token = PPCGuardToken(self.cpu, gcmap, descr, op.getfailargs(),
-                              arglocs, save_exc, frame_depth,
-                              is_guard_not_invalidated, is_guard_not_forced,
+                              arglocs, op.getopnum(), frame_depth,
                               fcond)
         return token
 
@@ -440,7 +434,7 @@
 
     def emit_guard_not_forced_2(self, op, arglocs, regalloc):
         guard_token = self.build_guard_token(op, arglocs[0].value, arglocs[1:],
-                                             c.cond_none, save_exc=False)
+                                             c.cond_none)
         self._finish_gcmap = guard_token.gcmap
         self._store_force_index(op)
         self.store_info_on_descr(0, guard_token)
@@ -531,7 +525,7 @@
         self.mc.load_from_addr(r.SCRATCH2, self.cpu.pos_exception())
         self.mc.cmp_op(0, r.SCRATCH2.value, 0, imm=True)
         self.guard_success_cc = c.EQ
-        self._emit_guard(op, arglocs, save_exc=True)
+        self._emit_guard(op, arglocs)
         # 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(regalloc,-1).getopnum() == rop.COND_CALL:
@@ -553,7 +547,7 @@
         mc.load(r.SCRATCH.value, r.SCRATCH2.value, diff)
         mc.cmp_op(0, r.SCRATCH.value, loc.value)
         self.guard_success_cc = c.EQ
-        self._emit_guard(op, failargs, save_exc=True)
+        self._emit_guard(op, failargs)
 
         if resloc:
             mc.load(resloc.value, r.SCRATCH2.value, 0)
@@ -1281,12 +1275,12 @@
             self.mc.load_imm(r.r4, value)
             self.mc.cmp_op(0, r.r5.value, r.r4.value, imm=False)
         jump_if_eq = self.mc.currpos()
-        self.mc.nop()      # patched later
+        self.mc.trap()      # patched later
         return jump_if_eq
 
     def _call_assembler_patch_je(self, result_loc, je_location):
         jump_to_done = self.mc.currpos()
-        self.mc.nop()      # patched later
+        self.mc.trap()      # patched later
         #
         currpos = self.mc.currpos()
         pmc = OverwritingBuilder(self.mc, je_location, 1)
@@ -1325,23 +1319,26 @@
         baseofs = self.cpu.get_baseofs_of_frame_field()
         newlooptoken.compiled_loop_token.update_frame_info(
             oldlooptoken.compiled_loop_token, baseofs)
-        if IS_PPC_32 or not IS_BIG_ENDIAN:
-            # we overwrite the instructions at the old _ll_function_addr
-            # to start with a JMP to the new _ll_function_addr.
-            # Ideally we should rather patch all existing CALLs, but well.
-            mc = PPCBuilder()
-            mc.b_abs(target)
-            mc.copy_to_raw_memory(oldadr)
-        else:
+        if IS_PPC_64 and IS_BIG_ENDIAN:
             # PPC64 big-endian trampolines are data so overwrite the code
             # address in the function descriptor at the old address.
             # Copy the whole 3-word trampoline, even though the other
-            # words are always zero so far.
+            # words are always zero so far.  That's not enough in all
+            # cases: if the "target" trampoline is itself redirected
+            # later, then the "old" trampoline won't be updated; so
+            # we still need the jump below to be safe.
             odata = rffi.cast(rffi.CArrayPtr(lltype.Signed), oldadr)
             tdata = rffi.cast(rffi.CArrayPtr(lltype.Signed), target)
             odata[0] = tdata[0]
             odata[1] = tdata[1]
             odata[2] = tdata[2]
+            oldadr += 3 * WORD
+            target += 3 * WORD
+        # we overwrite the instructions at the old _ll_function_addr
+        # to start with a JMP to the new _ll_function_addr.
+        mc = PPCBuilder()
+        mc.b_abs(target)
+        mc.copy_to_raw_memory(oldadr)
 
 
 class OpAssembler(IntOpAssembler, GuardOpAssembler,
diff --git a/rpython/jit/backend/ppc/ppc_assembler.py b/rpython/jit/backend/ppc/ppc_assembler.py
--- a/rpython/jit/backend/ppc/ppc_assembler.py
+++ b/rpython/jit/backend/ppc/ppc_assembler.py
@@ -8,7 +8,8 @@
                                           GPR_SAVE_AREA_OFFSET,
                                           THREADLOCAL_ADDR_OFFSET,
                                           STD_FRAME_SIZE_IN_BYTES,
-                                          IS_BIG_ENDIAN)
+                                          IS_BIG_ENDIAN,
+                                          LOCAL_VARS_OFFSET)
 from rpython.jit.backend.ppc.helper.assembler import Saved_Volatiles
 from rpython.jit.backend.ppc.helper.regalloc import _check_imm_arg
 import rpython.jit.backend.ppc.register as r
@@ -233,6 +234,7 @@
         # Second argument is the new size, which is still in r0 here
         mc.mr(r.r4.value, r.r0.value)
 
+        # This trashes r0 and r2
         self._store_and_reset_exception(mc, r.RCS2, r.RCS3)
 
         # Do the call
@@ -283,6 +285,7 @@
         mc.store(exctploc.value, r.r2.value, diff)
 
     def _reload_frame_if_necessary(self, mc, shadowstack_reg=None):
+        # might trash the VOLATILE registers different from r3 and f1
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:
             if gcrootmap.is_shadow_stack:
@@ -492,6 +495,8 @@
         old_mc = self.mc
         self.mc = mc
 
+        extra_stack_size = LOCAL_VARS_OFFSET + 4 * WORD + 8
+        extra_stack_size = (extra_stack_size + 15) & ~15
         if for_frame:
             # NOTE: don't save registers on the jitframe here!  It might
             # override already-saved values that will be restored
@@ -508,12 +513,12 @@
             # We need to increase our stack frame size a bit to store them.
             #
             self.mc.load(r.SCRATCH.value, r.SP.value, 0)    # SP back chain
-            self.mc.store_update(r.SCRATCH.value, r.SP.value, -6 * WORD)
-            self.mc.std(r.RCS1.value, r.SP.value, 1 * WORD)
-            self.mc.std(r.RCS2.value, r.SP.value, 2 * WORD)
-            self.mc.std(r.RCS3.value, r.SP.value, 3 * WORD)
-            self.mc.std(r.r3.value, r.SP.value, 4 * WORD)
-            self.mc.stfd(r.f1.value, r.SP.value, 5 * WORD)
+            self.mc.store_update(r.SCRATCH.value, r.SP.value, -extra_stack_size)
+            self.mc.std(r.RCS1.value, r.SP.value, LOCAL_VARS_OFFSET + 0 * WORD)
+            self.mc.std(r.RCS2.value, r.SP.value, LOCAL_VARS_OFFSET + 1 * WORD)
+            self.mc.std(r.RCS3.value, r.SP.value, LOCAL_VARS_OFFSET + 2 * WORD)
+            self.mc.std(r.r3.value,   r.SP.value, LOCAL_VARS_OFFSET + 3 * WORD)
+            self.mc.stfd(r.f1.value,  r.SP.value, LOCAL_VARS_OFFSET + 4 * WORD)
             saved_regs = None
             saved_fp_regs = None
 
@@ -536,6 +541,8 @@
             # since the call to write barrier can't collect
             # (and this is assumed a bit left and right here, like lack
             # of _reload_frame_if_necessary)
+            # This trashes r0 and r2, which is fine in this case
+            assert argument_loc is not r.r0
             self._store_and_reset_exception(mc, r.RCS2, r.RCS3)
 
         if withcards:
@@ -545,6 +552,8 @@
         mc.mflr(r.RCS1.value)
         #
         func = rffi.cast(lltype.Signed, func)
+        # Note: if not 'for_frame', argument_loc is r0, which must carefully
+        # not be overwritten above
         mc.mr(r.r3.value, argument_loc.value)
         mc.load_imm(mc.RAW_CALL_REG, func)
         mc.raw_call()
@@ -564,12 +573,12 @@
             mc.andix(r.RCS2.value, r.RCS2.value, card_marking_mask & 0xFF)
 
         if for_frame:
-            self.mc.ld(r.RCS1.value, r.SP.value, 1 * WORD)
-            self.mc.ld(r.RCS2.value, r.SP.value, 2 * WORD)
-            self.mc.ld(r.RCS3.value, r.SP.value, 3 * WORD)
-            self.mc.ld(r.r3.value, r.SP.value, 4 * WORD)
-            self.mc.lfd(r.f1.value, r.SP.value, 5 * WORD)
-            self.mc.addi(r.SP.value, r.SP.value, 6 * WORD)
+            self.mc.ld(r.RCS1.value, r.SP.value, LOCAL_VARS_OFFSET + 0 * WORD)
+            self.mc.ld(r.RCS2.value, r.SP.value, LOCAL_VARS_OFFSET + 1 * WORD)
+            self.mc.ld(r.RCS3.value, r.SP.value, LOCAL_VARS_OFFSET + 2 * WORD)
+            self.mc.ld(r.r3.value,   r.SP.value, LOCAL_VARS_OFFSET + 3 * WORD)
+            self.mc.lfd(r.f1.value,  r.SP.value, LOCAL_VARS_OFFSET + 4 * WORD)
+            self.mc.addi(r.SP.value, r.SP.value, extra_stack_size)
 
         else:
             self._pop_core_regs_from_jitframe(mc, saved_regs)
@@ -875,13 +884,12 @@
     def target_arglocs(self, looptoken):
         return looptoken._ppc_arglocs
 
-    def materialize_loop(self, looptoken, show=False):
+    def materialize_loop(self, looptoken):
         self.datablockwrapper.done()
         self.datablockwrapper = None
         allblocks = self.get_asmmemmgr_blocks(looptoken)
         start = self.mc.materialize(self.cpu, allblocks,
                                     self.cpu.gc_ll_descr.gcrootmap)
-        #print "=== Loop start is at %s ===" % hex(r_uint(start))
         return start
 
     def load_gcmap(self, mc, reg, gcmap):
@@ -946,7 +954,7 @@
             #
             relative_target = tok.pos_recovery_stub - tok.pos_jump_offset
             #
-            if not tok.is_guard_not_invalidated:
+            if not tok.guard_not_invalidated():
                 mc = PPCBuilder()
                 mc.b_cond_offset(relative_target, tok.fcond)
                 mc.copy_to_raw_memory(addr)
@@ -1219,7 +1227,7 @@
         force_realignment = (itemsize % WORD) != 0
         if force_realignment:
             constsize += WORD - 1
-        mc.addi(r.RSZ.value, r.RSZ.value, constsize)
+        mc.addi(r.RSZ.value, varsizeloc.value, constsize)
         if force_realignment:
             # "& ~(WORD-1)"
             bit_limit = 60 if WORD == 8 else 61
@@ -1324,8 +1332,10 @@
 
 
 def notimplemented_op(self, op, arglocs, regalloc):
-    print "[PPC/asm] %s not implemented" % op.getopname()
-    raise NotImplementedError(op)
+    msg = '[PPC/asm] %s not implemented\n' % op.getopname()
+    if we_are_translated():
+        llop.debug_print(lltype.Void, msg)
+    raise NotImplementedError(msg)
 
 operations = [notimplemented_op] * (rop._LAST + 1)
 
diff --git a/rpython/jit/backend/ppc/regalloc.py b/rpython/jit/backend/ppc/regalloc.py
--- a/rpython/jit/backend/ppc/regalloc.py
+++ b/rpython/jit/backend/ppc/regalloc.py
@@ -25,6 +25,7 @@
 from rpython.jit.backend.llsupport.descr import unpack_interiorfielddescr
 from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
 from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.debug import debug_print
 from rpython.jit.codewriter.effectinfo import EffectInfo
 from rpython.rlib import rgc
 from rpython.rlib.rarithmetic import r_uint
@@ -1115,8 +1116,10 @@
         return locs
 
 def notimplemented(self, op):
-    print "[PPC/regalloc] %s not implemented" % op.getopname()
-    raise NotImplementedError(op)
+    msg = '[PPC/regalloc] %s not implemented\n' % op.getopname()
+    if we_are_translated():
+        llop.debug_print(lltype.Void, msg)
+    raise NotImplementedError(msg)
 
 def force_int(intvalue):
     # a hack before transaction: force the intvalue argument through
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
@@ -3903,6 +3903,30 @@
         x = self.cpu.get_float_value(deadframe, 0)
         assert longlong.getrealfloat(x) == 13.5
         assert called == [finish_descr2]
+        del called[:]
+
+        # compile a second replacement
+        ops = '''
+        [f0, f1]
+        f2 = float_mul(f0, f1)
+        finish(f2)'''
+        loop3 = parse(ops)
+        looptoken3 = JitCellToken()
+        looptoken3.outermost_jitdriver_sd = FakeJitDriverSD()
+        self.cpu.compile_loop(loop3.inputargs, loop3.operations, looptoken3)
+        finish_descr3 = loop3.operations[-1].getdescr()
+
+        # install it
+        self.cpu.redirect_call_assembler(looptoken2, looptoken3)
+
+        # now, our call_assembler should go to looptoken3
+        args = [longlong.getfloatstorage(0.5),
+                longlong.getfloatstorage(9.0)]         # 0.5*9.0 == 1.25+3.25
+        deadframe = self.cpu.execute_token(othertoken, *args)
+        x = self.cpu.get_float_value(deadframe, 0)
+        assert longlong.getrealfloat(x) == 13.5
+        assert called == [finish_descr3]
+        del called[:]
 
     def test_short_result_of_getfield_direct(self):
         # Test that a getfield that returns a CHAR, SHORT or INT, signed
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
@@ -602,7 +602,7 @@
             relative_target = tok.pos_recovery_stub - (tok.pos_jump_offset + 4)
             assert rx86.fits_in_32bits(relative_target)
             #
-            if not tok.is_guard_not_invalidated:
+            if not tok.guard_not_invalidated():
                 mc = codebuf.MachineCodeBlockWrapper()
                 mc.writeimm32(relative_target)
                 mc.copy_to_raw_memory(addr)
@@ -1774,15 +1774,9 @@
 
     def implement_guard_recovery(self, guard_opnum, faildescr, failargs,
                                  fail_locs, frame_depth):
-        exc = (guard_opnum == rop.GUARD_EXCEPTION or
-               guard_opnum == rop.GUARD_NO_EXCEPTION or
-               guard_opnum == rop.GUARD_NOT_FORCED)
-        is_guard_not_invalidated = guard_opnum == rop.GUARD_NOT_INVALIDATED
-        is_guard_not_forced = guard_opnum == rop.GUARD_NOT_FORCED
         gcmap = allocate_gcmap(self, frame_depth, JITFRAME_FIXED_SIZE)
-        return GuardToken(self.cpu, gcmap, faildescr, failargs,
-                          fail_locs, exc, frame_depth,
-                          is_guard_not_invalidated, is_guard_not_forced)
+        return GuardToken(self.cpu, gcmap, faildescr, failargs, fail_locs,
+                          guard_opnum, frame_depth)
 
     def generate_propagate_error_64(self):
         assert WORD == 8


More information about the pypy-commit mailing list