Commits

Armin Rigo committed 8c87151

Fix fix fix, with a hack for now

Comments (0)

Files changed (4)

pypy/jit/backend/llsupport/llmodel.py

         deadframe = lltype.cast_opaque_ptr(jitframe.DEADFRAMEPTR, deadframe)
         return deadframe.jf_guard_exc
 
+    def set_savedata_ref(self, deadframe, data):
+        deadframe = lltype.cast_opaque_ptr(jitframe.DEADFRAMEPTR, deadframe)
+        deadframe.jf_savedata = data
+
+    def get_savedata_ref(self, deadframe):
+        deadframe = lltype.cast_opaque_ptr(jitframe.DEADFRAMEPTR, deadframe)
+        return deadframe.jf_savedata
+
     def free_loop_and_bridges(self, compiled_loop_token):
         AbstractCPU.free_loop_and_bridges(self, compiled_loop_token)
         blocks = compiled_loop_token.asmmemmgr_blocks

pypy/jit/backend/test/runner_test.py

     else:
         return BoxFloat(ll)
 
-class RandomGcRef(object):
-    _TYPE = llmemory.GCREF
-random_gcref = RandomGcRef()
+STUFF = lltype.GcStruct('STUFF')
+random_gcref = lltype.cast_opaque_ptr(llmemory.GCREF,
+                                      lltype.malloc(STUFF, immortal=True))
 
 
 class Runner(object):
         assert self.cpu.get_latest_value_int(deadframe, 0) == 1
         assert self.cpu.get_latest_value_int(deadframe, 1) == 10
         assert values == [faildescr, 1, 10]
+        assert self.cpu.get_savedata_ref(deadframe)   # not NULL
         assert self.cpu.get_savedata_ref(deadframe) == random_gcref
 
     def test_force_operations_returning_int(self):

pypy/jit/backend/x86/assembler.py

 
 class GuardToken(object):
     def __init__(self, faildescr, failargs, fail_locs, exc,
-                 is_guard_not_invalidated):
+                 is_guard_not_invalidated, is_guard_not_forced):
         self.faildescr = faildescr
         self.failargs = failargs
         self.fail_locs = fail_locs
         self.exc = exc
         self.is_guard_not_invalidated = is_guard_not_invalidated
+        self.is_guard_not_forced = is_guard_not_forced
 
 DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', ('i', lltype.Signed),
                               ('type', lltype.Char), # 'b'ridge, 'l'abel or
         self.propagate_exception_path = 0
         self.gcrootmap_retaddr_forced = 0
         self.teardown()
+        self.force_token_to_dead_frame = {}    # XXX temporary hack
 
     def set_debug(self, v):
         r = self._debug
                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
         return GuardToken(faildescr, failargs, fail_locs, exc,
-                          is_guard_not_invalidated)
+                          is_guard_not_invalidated, is_guard_not_forced)
 
     def generate_propagate_error_64(self):
         assert WORD == 8
             mc.CALL_r(X86_64_SCRATCH_REG.value)
             assert mc.get_relative_pos() == start + 13
         # write tight data that describes the failure recovery
+        if guardtok.is_guard_not_forced:
+            mc.writechar(chr(self.CODE_FORCED))
         self.write_failure_recovery_description(mc, guardtok.failargs,
                                                 guardtok.fail_locs)
         # write the fail_index too
     CODE_STOP       = 0 | DESCR_SPECIAL
     CODE_HOLE       = 4 | DESCR_SPECIAL
     CODE_INPUTARG   = 8 | DESCR_SPECIAL
+    CODE_FORCED     = 12 | DESCR_SPECIAL
 
     def write_failure_recovery_description(self, mc, failargs, locs):
         for i in range(len(failargs)):
         assert cpu.gc_ll_descr.kind == "boehm", "XXX Boehm only"
         #self.fail_ebp = allregisters[16 + ebp.value]
         num = 0
+        deadframe = lltype.nullptr(jitframe.DEADFRAME)
         # step 1: lots of mess just to count the final value of 'num'
         bytecode1 = bytecode
         while 1:
                         continue
                     if code == Assembler386.CODE_INPUTARG:
                         continue
+                    if code == Assembler386.CODE_FORCED:
+                        # resuming from a GUARD_NOT_FORCED
+                        token = allregisters[16 + ebp.value]
+                        deadframe = (
+                            cpu.assembler.force_token_to_dead_frame.pop(token))
+                        deadframe = lltype.cast_opaque_ptr(
+                            jitframe.DEADFRAMEPTR, deadframe)
+                        continue
                     assert code == Assembler386.CODE_STOP
                     break
             num += 1
         # allocate the deadframe
-        deadframe = lltype.malloc(jitframe.DEADFRAME, num)
+        if not deadframe:
+            deadframe = lltype.malloc(jitframe.DEADFRAME, num)
         # fill it
         code_inputarg = False
         num = 0
                     if code == Assembler386.CODE_INPUTARG:
                         code_inputarg = True
                         continue
+                    if code == Assembler386.CODE_FORCED:
+                        continue
                     assert code == Assembler386.CODE_STOP
                     break
                 # 'code' identifies a register: load its value

pypy/jit/backend/x86/runner.py

         rffi.cast(TP, addr_of_force_index)[0] = ~fail_index
         frb = self.assembler._find_failure_recovery_bytecode(faildescr)
         bytecode = rffi.cast(rffi.UCHARP, frb)
-        # start of "no gc operation!" block
+        assert (rffi.cast(lltype.Signed, bytecode[0]) ==
+                self.assembler.CODE_FORCED)
+        bytecode = rffi.ptradd(bytecode, 1)
         deadframe = self.assembler.grab_frame_values(
             self,
             bytecode,
             addr_of_force_token,
             self.all_null_registers)
-        # end of "no gc operation!" block
         assert self.get_latest_descr(deadframe) is faildescr
+        self.assembler.force_token_to_dead_frame[addr_of_force_token] = (
+            deadframe)
         return deadframe
 
     def redirect_call_assembler(self, oldlooptoken, newlooptoken):