[pypy-commit] pypy jit-get-errno: Speed up the reads and writes of 'errno'.

arigo noreply at buildbot.pypy.org
Thu Jun 26 12:38:39 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: jit-get-errno
Changeset: r72241:c8b2c8ee757a
Date: 2014-06-26 12:35 +0200
http://bitbucket.org/pypy/pypy/changeset/c8b2c8ee757a/

Log:	Speed up the reads and writes of 'errno'.

diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py
--- a/rpython/jit/backend/llsupport/test/ztranslation_test.py
+++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py
@@ -3,7 +3,7 @@
 from rpython.rlib.jit import JitDriver, unroll_parameters, set_param
 from rpython.rlib.jit import PARAMETERS, dont_look_inside
 from rpython.rlib.jit import promote
-from rpython.rlib import jit_hooks
+from rpython.rlib import jit_hooks, rposix
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rlib.rthread import ThreadLocalReference
 from rpython.jit.backend.detect_cpu import getcpuclass
@@ -24,6 +24,7 @@
         # - full optimizer
         # - floats neg and abs
         # - threadlocalref_get
+        # - get_errno, set_errno
 
         class Frame(object):
             _virtualizable_ = ['i']
@@ -64,6 +65,8 @@
                 if k - abs(j):  raise ValueError
                 if k - abs(-j): raise ValueError
                 if t.get().nine != 9: raise ValueError
+                rposix.set_errno(total)
+                if rposix.get_errno() != total: raise ValueError
             return chr(total % 253)
         #
         from rpython.rtyper.lltypesystem import lltype, rffi
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
@@ -2325,12 +2325,38 @@
         ed = effectinfo.extradescrs[0]
         assert isinstance(ed, ThreadLocalRefDescr)
         addr1 = rffi.cast(lltype.Signed, ed.get_tlref_addr())
+        # 'addr1' is the address is the current thread, but we assume that
+        # it is a thread-local at a constant offset from %fs/%gs.
         addr0 = stmtlocal.threadlocal_base()
         addr = addr1 - addr0
         assert rx86.fits_in_32bits(addr)
         mc = self.mc
-        mc.writechar(stmtlocal.SEGMENT_TL)     # prefix
-        mc.MOV_rj(resloc.value, addr)
+        mc.writechar(stmtlocal.SEGMENT_TL)     # prefix: %fs or %gs
+        mc.MOV_rj(resloc.value, addr)          # memory read
+
+    def get_set_errno(self, op, loc, issue_a_write):
+        # this function is only called on Linux
+        from rpython.jit.backend.x86 import stmtlocal
+        addr = stmtlocal.get_errno_tl()
+        assert rx86.fits_in_32bits(addr)
+        mc = self.mc
+        mc.writechar(stmtlocal.SEGMENT_TL)     # prefix: %fs or %gs
+        # !!important: the *next* instruction must be the one using 'addr'!!
+        if issue_a_write:
+            if isinstance(loc, RegLoc):
+                mc.MOV32_jr(addr, loc.value)       # memory write from reg
+            else:
+                assert isinstance(loc, ImmedLoc)
+                newvalue = loc.value
+                newvalue = rffi.cast(rffi.INT, newvalue)
+                newvalue = rffi.cast(lltype.Signed, newvalue)
+                mc.MOV32_ji(addr, newvalue)        # memory write immediate
+        else:
+            assert isinstance(loc, RegLoc)
+            if IS_X86_32:
+                mc.MOV_rj(loc.value, addr)         # memory read
+            elif IS_X86_64:
+                mc.MOVSX32_rj(loc.value, addr)     # memory read, sign-extend
 
 
 genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST
diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -693,6 +693,7 @@
         self.perform_math(op, [loc0], loc0)
 
     TLREF_SUPPORT = sys.platform.startswith('linux')
+    ERRNO_SUPPORT = sys.platform.startswith('linux')
 
     def _consider_threadlocalref_get(self, op):
         if self.TLREF_SUPPORT:
@@ -701,6 +702,22 @@
         else:
             self._consider_call(op)
 
+    def _consider_get_errno(self, op):
+        if self.ERRNO_SUPPORT:
+            resloc = self.force_allocate_reg(op.result)
+            self.assembler.get_set_errno(op, resloc, issue_a_write=False)
+        else:
+            self._consider_call(op)
+
+    def _consider_set_errno(self, op):
+        if self.ERRNO_SUPPORT:
+            # op.getarg(0) is the function set_errno; op.getarg(1) is
+            # the new errno value
+            loc0 = self.rm.make_sure_var_in_reg(op.getarg(1))
+            self.assembler.get_set_errno(op, loc0, issue_a_write=True)
+        else:
+            self._consider_call(op)
+
     def _call(self, op, arglocs, force_store=[], guard_not_forced_op=None):
         # we need to save registers on the stack:
         #
@@ -780,6 +797,10 @@
                 return self._consider_math_sqrt(op)
             if oopspecindex == EffectInfo.OS_THREADLOCALREF_GET:
                 return self._consider_threadlocalref_get(op)
+            if oopspecindex == EffectInfo.OS_GET_ERRNO:
+                return self._consider_get_errno(op)
+            if oopspecindex == EffectInfo.OS_SET_ERRNO:
+                return self._consider_set_errno(op)
         self._consider_call(op)
 
     def consider_call_may_force(self, op, guard_op):
diff --git a/rpython/jit/backend/x86/stmtlocal.py b/rpython/jit/backend/x86/stmtlocal.py
--- a/rpython/jit/backend/x86/stmtlocal.py
+++ b/rpython/jit/backend/x86/stmtlocal.py
@@ -21,6 +21,10 @@
     asm("%s" : "=r"(result));
     return result;
 }
+static long pypy__get_errno_tl(void)
+{
+    return ((long)&errno) - pypy__threadlocal_base();
+}
 ''' % _instruction])
 
 
@@ -30,3 +34,10 @@
     compilation_info=eci,
     _nowrapper=True,
     ) #transactionsafe=True)
+
+get_errno_tl = rffi.llexternal(
+    'pypy__get_errno_tl',
+    [], lltype.Signed,
+    compilation_info=eci,
+    _nowrapper=True,
+    ) #transactionsafe=True)


More information about the pypy-commit mailing list