[pypy-commit] pypy arm-backend-2: implement call_release_gil

bivab noreply at buildbot.pypy.org
Wed Jul 13 14:53:16 CEST 2011


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r45549:37b0e249c32f
Date: 2011-07-13 14:53 +0200
http://bitbucket.org/pypy/pypy/changeset/37b0e249c32f/

Log:	implement call_release_gil

diff --git a/pypy/jit/backend/arm/assembler.py b/pypy/jit/backend/arm/assembler.py
--- a/pypy/jit/backend/arm/assembler.py
+++ b/pypy/jit/backend/arm/assembler.py
@@ -121,11 +121,34 @@
                                                       ll_new_unicode)
         if gc_ll_descr.get_malloc_slowpath_addr is not None:
             self._build_malloc_slowpath()
+        if gc_ll_descr.gcrootmap:
+            self._build_release_gil(gc_ll_descr.gcrootmap)
         self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn)
         self._exit_code_addr = self._gen_exit_path()
         self._leave_jitted_hook_save_exc = self._gen_leave_jitted_hook_code(True)
         self._leave_jitted_hook = self._gen_leave_jitted_hook_code(False)
 
+    @staticmethod
+    def _release_gil_shadowstack():
+        before = rffi.aroundstate.before
+        if before:
+            before()
+
+    @staticmethod
+    def _reacquire_gil_shadowstack():
+        after = rffi.aroundstate.after
+        if after:
+            after()
+    _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void))
+    def _build_release_gil(self, gcrootmap):
+        assert gcrootmap.is_shadow_stack
+        releasegil_func = llhelper(self._NOARG_FUNC,
+                                   self._release_gil_shadowstack)
+        reacqgil_func = llhelper(self._NOARG_FUNC,
+                                 self._reacquire_gil_shadowstack)
+        self.releasegil_addr  = self.cpu.cast_ptr_to_int(releasegil_func)
+        self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func)
+
     def setup_failure_recovery(self):
 
         @rgc.no_collect
@@ -758,6 +781,8 @@
             opnum = operations[i + 1].getopnum()
             assert opnum  == rop.GUARD_OVERFLOW or opnum == rop.GUARD_NO_OVERFLOW
             return True
+        if num == rop.CALL_RELEASE_GIL:
+            return True
         return False
 
 
diff --git a/pypy/jit/backend/arm/opassembler.py b/pypy/jit/backend/arm/opassembler.py
--- a/pypy/jit/backend/arm/opassembler.py
+++ b/pypy/jit/backend/arm/opassembler.py
@@ -474,7 +474,7 @@
 
         # the following is supposed to be the slow path, so whenever possible
         # we choose the most compact encoding over the most efficient one.
-        with saved_registers(self.mc, r.caller_resp, regalloc=regalloc):
+        with saved_registers(self.mc, r.caller_resp):
             if N == 2:
                 callargs = [r.r0, r.r1]
             else:
@@ -950,6 +950,35 @@
         self._emit_guard(guard_op, arglocs, c.GE)
         return fcond
 
+    emit_guard_call_release_gil = emit_guard_call_may_force
+
+    def call_release_gil(self, gcrootmap, save_registers):
+        # First, we need to save away the registers listed in
+        # 'save_registers' that are not callee-save.  XXX We assume that
+        # the floating point registers won't be modified.
+        import pdb; pdb.set_trace()
+        regs_to_save = []
+        for reg in self._regalloc.rm.save_around_call_regs:
+            if reg in save_registers:
+                regs_to_save.append(reg)
+        assert gcrootmap.is_shadow_stack
+        with saved_registers(self.mc, regs_to_save):
+            self._emit_call(-1, self.releasegil_addr, [], regalloc, fcond)
+
+    def call_reacquire_gil(self, gcrootmap, save_loc):
+        # save the previous result into the stack temporarily.
+        # XXX like with call_release_gil(), we assume that we don't need
+        # to save vfp regs in this case.
+        regs_to_save = []
+        if isinstance(save_loc, RegLoc) and not save_loc.is_vfp_reg():
+            regs_to_save.append(save_loc)
+        # call the reopenstack() function (also reacquiring the GIL)
+        if len(regs_to_save) == 1:
+            regs_to_save.append(r.ip) # for alingment
+        assert gcrootmap.is_shadow_stack
+        with saved_registers(self.mc, regs_to_save):
+            self._emit_call(-1, self.reacqgil_addr, [], regalloc, fcond)
+
     def write_new_force_index(self):
         # for shadowstack only: get a new, unused force_index number and
         # write it to FORCE_INDEX_OFS.  Used to record the call shape
diff --git a/pypy/jit/backend/arm/regalloc.py b/pypy/jit/backend/arm/regalloc.py
--- a/pypy/jit/backend/arm/regalloc.py
+++ b/pypy/jit/backend/arm/regalloc.py
@@ -998,6 +998,23 @@
         self.possibly_free_vars(guard_op.getfailargs())
         return locs
 
+    def prepare_guard_call_release_gil(self, op, guard_op, fcond):
+        # first, close the stack in the sense of the asmgcc GC root tracker
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap:
+            self.assembler.call_release_gil(gcrootmap, arglocs)
+        # do the call
+        faildescr = guard_op.getdescr()
+        fail_index = self.cpu.get_fail_descr_number(faildescr)
+        args = [imm(rffi.cast(lltype.Signed, op.getarg(0).getint()))]
+        self.assembler.emit_op_call(op, args, self, fcond, fail_index)
+        # then reopen the stack
+        if gcrootmap:
+            self.call_reacquire_gil(gcrootmap, r.r0)
+        locs = self._prepare_guard(guard_op)
+        self.possibly_free_vars(guard_op.getfailargs())
+        return locs
+
     def prepare_guard_call_assembler(self, op, guard_op, fcond):
         descr = op.getdescr()
         assert isinstance(descr, LoopToken)


More information about the pypy-commit mailing list