[pypy-commit] pypy ec-threadlocal: in-progress: JIT backend support

arigo noreply at buildbot.pypy.org
Mon Jun 23 10:34:55 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: ec-threadlocal
Changeset: r72149:5c7a1c9731c5
Date: 2014-06-23 10:34 +0200
http://bitbucket.org/pypy/pypy/changeset/5c7a1c9731c5/

Log:	in-progress: JIT backend support

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
@@ -4,6 +4,8 @@
 from rpython.rlib.jit import PARAMETERS, dont_look_inside
 from rpython.rlib.jit import promote
 from rpython.rlib import jit_hooks
+from rpython.rlib.objectmodel import keepalive_until_here
+from rpython.rlib.rthread import ThreadLocalReference
 from rpython.jit.backend.detect_cpu import getcpuclass
 from rpython.jit.backend.test.support import CCompiledMixin
 from rpython.jit.codewriter.policy import StopAtXPolicy
@@ -21,6 +23,7 @@
         # - profiler
         # - full optimizer
         # - floats neg and abs
+        # - threadlocalref_get
 
         class Frame(object):
             _virtualizable_ = ['i']
@@ -28,6 +31,10 @@
             def __init__(self, i):
                 self.i = i
 
+        class Foo(object):
+            pass
+        t = ThreadLocalReference(Foo)
+
         @dont_look_inside
         def myabs(x):
             return abs(x)
@@ -56,6 +63,7 @@
                 k = myabs(j)
                 if k - abs(j):  raise ValueError
                 if k - abs(-j): raise ValueError
+                if t.get().nine != 9: raise ValueError
             return chr(total % 253)
         #
         from rpython.rtyper.lltypesystem import lltype, rffi
@@ -78,8 +86,12 @@
             return res
         #
         def main(i, j):
+            foo = Foo()
+            foo.nine = -(i + j)
+            t.set(foo)
             a_char = f(i, j)
             a_float = libffi_stuff(i, j)
+            keepalive_until_here(foo)
             return ord(a_char) * 10 + int(a_float)
         expected = main(40, -49)
         res = self.meta_interp(main, [40, -49])
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
@@ -2351,10 +2351,29 @@
         assert isinstance(reg, RegLoc)
         self.mc.MOV_rr(reg.value, ebp.value)
 
+    def threadlocalref_get(self, op, resloc):
+        # this function is only called on Linux
+        from rpython.jit.codewriter.jitcode import ThreadLocalRefDescr
+        from rpython.jit.backend.x86 import stmtlocal
+        assert isinstance(resloc, RegLoc)
+        effectinfo = op.getdescr().get_extra_info()
+        assert len(effectinfo.extradescrs) == 1
+        ed = effectinfo.extradescrs[0]
+        assert isinstance(ed, ThreadLocalRefDescr)
+        addr1 = rffi.cast(lltype.Signed, ed.get_tlref_addr())
+        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)
+
+
 genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST
 genop_list = [Assembler386.not_implemented_op] * rop._LAST
 genop_llong_list = {}
 genop_math_list = {}
+genop_tlref_list = {}
 genop_guard_list = [Assembler386.not_implemented_op_guard] * rop._LAST
 
 for name, value in Assembler386.__dict__.iteritems():
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
@@ -2,7 +2,7 @@
 """ Register allocation scheme.
 """
 
-import os
+import os, sys
 from rpython.jit.backend.llsupport import symbolic
 from rpython.jit.backend.llsupport.descr import (ArrayDescr, CallDescr,
     unpack_arraydescr, unpack_fielddescr, unpack_interiorfielddescr)
@@ -692,6 +692,15 @@
         loc0 = self.xrm.force_result_in_reg(op.result, op.getarg(1))
         self.perform_math(op, [loc0], loc0)
 
+    TLREF_SUPPORT = sys.platform.startswith('linux')
+
+    def _consider_threadlocalref_get(self, op):
+        if self.TLREF_SUPPORT:
+            resloc = self.force_allocate_reg(op.result)
+            self.assembler.threadlocalref_get(op, resloc)
+        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:
         #
@@ -769,6 +778,8 @@
                         return
             if oopspecindex == EffectInfo.OS_MATH_SQRT:
                 return self._consider_math_sqrt(op)
+            if oopspecindex == EffectInfo.OS_THREADLOCALREF_GET:
+                return self._consider_threadlocalref_get(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
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/x86/stmtlocal.py
@@ -0,0 +1,32 @@
+from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.jit.backend.x86.arch import WORD
+
+SEGMENT_FS = '\x64'
+SEGMENT_GS = '\x65'
+
+if WORD == 4:
+    SEGMENT_TL = SEGMENT_GS
+    _instruction = "movl %%gs:0, %0"
+else:
+    SEGMENT_TL = SEGMENT_FS
+    _instruction = "movq %%fs:0, %0"
+
+eci = ExternalCompilationInfo(post_include_bits=['''
+#define RPY_STM_JIT  1
+static long pypy__threadlocal_base(void)
+{
+    /* XXX ONLY LINUX WITH GCC/CLANG FOR NOW XXX */
+    long result;
+    asm("%s" : "=r"(result));
+    return result;
+}
+''' % _instruction])
+
+
+threadlocal_base = rffi.llexternal(
+    'pypy__threadlocal_base',
+    [], lltype.Signed,
+    compilation_info=eci,
+    _nowrapper=True,
+    ) #transactionsafe=True)
diff --git a/rpython/jit/codewriter/jitcode.py b/rpython/jit/codewriter/jitcode.py
--- a/rpython/jit/codewriter/jitcode.py
+++ b/rpython/jit/codewriter/jitcode.py
@@ -130,6 +130,8 @@
     # variable from anywhere.
 
     def __init__(self, opaque_id):
+        from rpython.rtyper.lltypesystem.lloperation import llop
+        from rpython.rtyper.lltypesystem import llmemory
         def get_tlref_addr():
             return llop.threadlocalref_getaddr(llmemory.Address, opaque_id)
         self.get_tlref_addr = get_tlref_addr
diff --git a/rpython/jit/metainterp/test/test_threadlocal.py b/rpython/jit/metainterp/test/test_threadlocal.py
--- a/rpython/jit/metainterp/test/test_threadlocal.py
+++ b/rpython/jit/metainterp/test/test_threadlocal.py
@@ -4,7 +4,7 @@
 from rpython.rlib.jit import dont_look_inside
 
 
-class TestThreadLocal(LLJitMixin):
+class ThreadLocalTest(object):
 
     def test_threadlocalref_get(self):
         class Foo:
@@ -24,3 +24,7 @@
 
         res = self.interp_operations(f, [])
         assert res == 42
+
+
+class TestLLtype(ThreadLocalTest, LLJitMixin):
+    pass
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -542,6 +542,7 @@
     'check_and_clear_exc':  LLOp(),
 
     'threadlocalref_get':   LLOp(sideeffects=False),
+    'threadlocalref_getaddr': LLOp(sideeffects=False),
     'threadlocalref_set':   LLOp(),
 
     # __________ debugging __________
diff --git a/rpython/translator/c/src/threadlocal.h b/rpython/translator/c/src/threadlocal.h
--- a/rpython/translator/c/src/threadlocal.h
+++ b/rpython/translator/c/src/threadlocal.h
@@ -28,6 +28,7 @@
 #define RPyThreadStaticTLS_Create(tls)      (void)0
 #define RPyThreadStaticTLS_Get(tls)         tls
 #define RPyThreadStaticTLS_Set(tls, value)  tls = value
+#define OP_THREADLOCALREF_GETADDR(tlref, ptr)  ptr = tlref
 
 #endif
 


More information about the pypy-commit mailing list