Author: Armin Rigo <[email protected]>
Branch: portable-threadlocal
Changeset: r74650:5291d2692c23
Date: 2014-11-23 14:18 +0100
http://bitbucket.org/pypy/pypy/changeset/5291d2692c23/

Log:    Clean up and adpat the JIT to the new threadlocals. Still missing:
        optimization for OS_THREADLOCALREF_ADDR in the x86 and arm backends

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
@@ -2320,24 +2320,9 @@
         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
+    def threadlocalref_addr(self, resloc):
         assert isinstance(resloc, RegLoc)
-        effectinfo = op.getdescr().get_extra_info()
-        assert effectinfo.extradescrs is not None
-        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: %fs or %gs
-        mc.MOV_rj(resloc.value, addr)          # memory read
+        XXX
 
     def get_set_errno(self, op, loc, issue_a_write):
         # this function is only called on Linux
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,31 +693,9 @@
         loc0 = self.xrm.force_result_in_reg(op.result, op.getarg(1))
         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:
-            resloc = self.force_allocate_reg(op.result)
-            self.assembler.threadlocalref_get(op, resloc)
-        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 _consider_threadlocalref_addr(self, op):
+        resloc = self.force_allocate_reg(op.result)
+        self.assembler.threadlocalref_addr(resloc)
 
     def _call(self, op, arglocs, force_store=[], guard_not_forced_op=None):
         # we need to save registers on the stack:
@@ -796,12 +774,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)
-            if oopspecindex == EffectInfo.OS_GET_ERRNO:
-                return self._consider_get_errno(op)
-            if oopspecindex == EffectInfo.OS_SET_ERRNO:
-                return self._consider_set_errno(op)
+            #if oopspecindex == EffectInfo.OS_THREADLOCALREF_ADDR:
+            #    return self._consider_threadlocalref_addr(op)
             if oopspecindex == EffectInfo.OS_MATH_READ_TIMESTAMP:
                 return self._consider_math_read_timestamp(op)
         self._consider_call(op)
diff --git a/rpython/jit/backend/x86/stmtlocal.py 
b/rpython/jit/backend/x86/stmtlocal.py
deleted file mode 100644
--- a/rpython/jit/backend/x86/stmtlocal.py
+++ /dev/null
@@ -1,43 +0,0 @@
-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;
-}
-static long pypy__get_errno_tl(void)
-{
-    return ((long)&errno) - pypy__threadlocal_base();
-}
-''' % _instruction])
-
-
-threadlocal_base = rffi.llexternal(
-    'pypy__threadlocal_base',
-    [], lltype.Signed,
-    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)
diff --git a/rpython/jit/codewriter/effectinfo.py 
b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -22,9 +22,7 @@
     OS_STR2UNICODE              = 2    # "str.str2unicode"
     OS_SHRINK_ARRAY             = 3    # rgc.ll_shrink_array
     OS_DICT_LOOKUP              = 4    # ll_dict_lookup
-    OS_THREADLOCALREF_GET       = 5    # llop.threadlocalref_get
-    OS_GET_ERRNO                = 6    # rposix.get_errno
-    OS_SET_ERRNO                = 7    # rposix.set_errno
+    OS_THREADLOCALREF_ADDR      = 5    # llop.threadlocalref_addr
     OS_NOT_IN_TRACE             = 8    # for calls not recorded in the jit 
trace
     #
     OS_STR_CONCAT               = 22   # "stroruni.concat"
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
@@ -117,26 +117,6 @@
         raise NotImplementedError
 
 
-class ThreadLocalRefDescr(AbstractDescr):
-    # A special descr used as the extradescr in a call to a
-    # threadlocalref_get function.  If the backend supports it,
-    # it can use this 'get_tlref_addr()' to get the address *in the
-    # current thread* of the thread-local variable.  If, on the current
-    # platform, the "__thread" variables are implemented as an offset
-    # from some base register (e.g. %fs on x86-64), then the backend will
-    # immediately substract the current value of the base register.
-    # This gives an offset from the base register, and this can be
-    # written down in an assembler instruction to load the "__thread"
-    # 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
-
-
 class LiveVarsInfo(object):
     def __init__(self, live_i, live_r, live_f):
         self.live_i = live_i
diff --git a/rpython/jit/codewriter/jtransform.py 
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -439,8 +439,6 @@
         elif oopspec_name.endswith('dict.lookup'):
             # also ordereddict.lookup
             prepare = self._handle_dict_lookup_call
-        elif oopspec_name.startswith('rposix.'):
-            prepare = self._handle_rposix_call
         else:
             prepare = self.prepare_builtin_call
         try:
@@ -1986,16 +1984,6 @@
         else:
             raise NotImplementedError(oopspec_name)
 
-    def _handle_rposix_call(self, op, oopspec_name, args):
-        if oopspec_name == 'rposix.get_errno':
-            return self._handle_oopspec_call(op, args, EffectInfo.OS_GET_ERRNO,
-                                             EffectInfo.EF_CANNOT_RAISE)
-        elif oopspec_name == 'rposix.set_errno':
-            return self._handle_oopspec_call(op, args, EffectInfo.OS_SET_ERRNO,
-                                             EffectInfo.EF_CANNOT_RAISE)
-        else:
-            raise NotImplementedError(oopspec_name)
-
     def rewrite_op_ll_read_timestamp(self, op):
         op1 = self.prepare_builtin_call(op, "ll_read_timestamp", [])
         return self.handle_residual_call(op1,
@@ -2011,17 +1999,11 @@
                              None)
         return [op0, op1]
 
-    def rewrite_op_threadlocalref_get(self, op):
-        from rpython.jit.codewriter.jitcode import ThreadLocalRefDescr
-        opaqueid = op.args[0].value
-        op1 = self.prepare_builtin_call(op, 'threadlocalref_getter', [],
-                                        extra=(opaqueid,),
-                                        extrakey=opaqueid._obj)
-        extradescr = ThreadLocalRefDescr(opaqueid)
+    def rewrite_op_threadlocalref_addr(self, op):
+        op1 = self.prepare_builtin_call(op, 'threadlocalref_addr', [])
         return self.handle_residual_call(op1,
-            oopspecindex=EffectInfo.OS_THREADLOCALREF_GET,
-            extraeffect=EffectInfo.EF_LOOPINVARIANT,
-            extradescr=[extradescr])
+            oopspecindex=EffectInfo.OS_THREADLOCALREF_ADDR,
+            extraeffect=EffectInfo.EF_CANNOT_RAISE)
 
 # ____________________________________________________________
 
diff --git a/rpython/jit/codewriter/support.py 
b/rpython/jit/codewriter/support.py
--- a/rpython/jit/codewriter/support.py
+++ b/rpython/jit/codewriter/support.py
@@ -702,10 +702,8 @@
     build_ll_1_raw_free_no_track_allocation = (
         build_raw_free_builder(track_allocation=False))
 
-    def build_ll_0_threadlocalref_getter(opaqueid):
-        def _ll_0_threadlocalref_getter():
-            return llop.threadlocalref_get(rclass.OBJECTPTR, opaqueid)
-        return _ll_0_threadlocalref_getter
+    def _ll_0_threadlocalref_addr():
+        return llop.threadlocalref_addr(llmemory.Address)
 
     def _ll_1_weakref_create(obj):
         return llop.weakref_create(llmemory.WeakRefPtr, obj)
diff --git a/rpython/jit/codewriter/test/test_jtransform.py 
b/rpython/jit/codewriter/test/test_jtransform.py
--- a/rpython/jit/codewriter/test/test_jtransform.py
+++ b/rpython/jit/codewriter/test/test_jtransform.py
@@ -148,9 +148,7 @@
              EI.OS_UNIEQ_LENGTHOK:       ([PUNICODE, PUNICODE], INT),
              EI.OS_RAW_MALLOC_VARSIZE_CHAR: ([INT], ARRAYPTR),
              EI.OS_RAW_FREE:             ([ARRAYPTR], lltype.Void),
-             EI.OS_THREADLOCALREF_GET:   ([], rclass.OBJECTPTR),
-             EI.OS_GET_ERRNO:            ([], INT),
-             EI.OS_SET_ERRNO:            ([INT], lltype.Void),
+             EI.OS_THREADLOCALREF_ADDR:  ([], llmemory.Address),
             }
             argtypes = argtypes[oopspecindex]
             assert argtypes[0] == [v.concretetype for v in op.args[1:]]
@@ -160,11 +158,8 @@
             elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE_CHAR:
                 assert extraeffect == EI.EF_CAN_RAISE
             elif oopspecindex in (EI.OS_RAW_FREE,
-                                  EI.OS_GET_ERRNO,
-                                  EI.OS_SET_ERRNO):
+                                  EI.OS_THREADLOCALREF_ADDR):
                 assert extraeffect == EI.EF_CANNOT_RAISE
-            elif oopspecindex == EI.OS_THREADLOCALREF_GET:
-                assert extraeffect == EI.EF_LOOPINVARIANT
             else:
                 assert extraeffect == EI.EF_ELIDABLE_CANNOT_RAISE
         return 'calldescr-%d' % oopspecindex
@@ -1346,54 +1341,17 @@
     assert op1.result is None
     assert op2 is None
 
-def test_threadlocalref_get():
-    from rpython.rtyper import rclass
-    from rpython.rlib.rthread import ThreadLocalReference
-    OS_THREADLOCALREF_GET = effectinfo.EffectInfo.OS_THREADLOCALREF_GET
-    class Foo: pass
-    t = ThreadLocalReference(Foo)
-    v2 = varoftype(rclass.OBJECTPTR)
-    c_opaqueid = const(t.opaque_id)
-    op = SpaceOperation('threadlocalref_get', [c_opaqueid], v2)
+def test_threadlocalref_addr():
+    OS_THREADLOCALREF_ADDR = effectinfo.EffectInfo.OS_THREADLOCALREF_ADDR
+    v = varoftype(llmemory.Address)
+    op = SpaceOperation('threadlocalref_addr', [], v)
     tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
     op0 = tr.rewrite_operation(op)
-    assert op0.opname == 'residual_call_r_r'
-    assert op0.args[0].value == 'threadlocalref_getter' # pseudo-function as 
str
+    assert op0.opname == 'residual_call_r_i'
+    assert op0.args[0].value == 'threadlocalref_addr' # pseudo-function as str
     assert op0.args[1] == ListOfKind("ref", [])
-    assert op0.args[2] == 'calldescr-%d' % OS_THREADLOCALREF_GET
-    assert op0.result == v2
-
-def test_get_errno():
-    # test that the oopspec is present and correctly transformed
-    from rpython.rlib import rposix
-    FUNC = lltype.FuncType([], lltype.Signed)
-    func = lltype.functionptr(FUNC, 'get_errno', _callable=rposix.get_errno)
-    v3 = varoftype(lltype.Signed)
-    op = SpaceOperation('direct_call', [const(func)], v3)
-    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
-    op1 = tr.rewrite_operation(op)
-    assert op1.opname == 'residual_call_r_i'
-    assert op1.args[0].value == func
-    assert op1.args[1] == ListOfKind('ref', [])
-    assert op1.args[2] == 'calldescr-%d' % effectinfo.EffectInfo.OS_GET_ERRNO
-    assert op1.result == v3
-
-def test_set_errno():
-    # test that the oopspec is present and correctly transformed
-    from rpython.rlib import rposix
-    FUNC = lltype.FuncType([lltype.Signed], lltype.Void)
-    func = lltype.functionptr(FUNC, 'set_errno', _callable=rposix.set_errno)
-    v1 = varoftype(lltype.Signed)
-    v3 = varoftype(lltype.Void)
-    op = SpaceOperation('direct_call', [const(func), v1], v3)
-    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
-    op1 = tr.rewrite_operation(op)
-    assert op1.opname == 'residual_call_ir_v'
-    assert op1.args[0].value == func
-    assert op1.args[1] == ListOfKind('int', [v1])
-    assert op1.args[2] == ListOfKind('ref', [])
-    assert op1.args[3] == 'calldescr-%d' % effectinfo.EffectInfo.OS_SET_ERRNO
-    assert op1.result == v3
+    assert op0.args[2] == 'calldescr-%d' % OS_THREADLOCALREF_ADDR
+    assert op0.result == v
 
 def test_unknown_operation():
     op = SpaceOperation('foobar', [], varoftype(lltype.Void))
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
@@ -1,29 +1,19 @@
 import py
 from rpython.jit.metainterp.test.support import LLJitMixin
-from rpython.rlib.rthread import ThreadLocalReference
-from rpython.rlib.jit import dont_look_inside
+from rpython.rtyper.lltypesystem import llmemory
+from rpython.rtyper.lltypesystem.lloperation import llop
 
 
 class ThreadLocalTest(object):
 
     def test_threadlocalref_get(self):
-        class Foo:
-            pass
-        t = ThreadLocalReference(Foo)
-        x = Foo()
-
-        @dont_look_inside
-        def setup():
-            t.set(x)
-
         def f():
-            setup()
-            if t.get() is x:
-                return 42
-            return -666
+            addr1 = llop.threadlocalref_addr(llmemory.Address)
+            # a "does not crash" test only
+            return 1
 
         res = self.interp_operations(f, [])
-        assert res == 42
+        assert res == 1
 
 
 class TestLLtype(ThreadLocalTest, LLJitMixin):
diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py
--- a/rpython/rlib/rthread.py
+++ b/rpython/rlib/rthread.py
@@ -284,17 +284,17 @@
 
         def getraw():
             _threadlocalref_seeme(self)
-            addr = llop.threadlocalref_addr(rffi.CCHARP)
+            addr = llop.threadlocalref_addr(llmemory.Address)
             return llop.raw_load(FIELDTYPE, addr, offset)
 
         def get_or_make_raw():
             _threadlocalref_seeme(self)
-            addr = llop.threadlocalref_make(rffi.CCHARP)
+            addr = llop.threadlocalref_make(llmemory.Address)
             return llop.raw_load(FIELDTYPE, addr, offset)
 
         def setraw(value):
             _threadlocalref_seeme(self)
-            addr = llop.threadlocalref_addr(rffi.CCHARP)
+            addr = llop.threadlocalref_addr(llmemory.Address)
             llop.raw_store(lltype.Void, addr, offset, value)
 
         self.getraw = getraw
@@ -315,14 +315,16 @@
         self.local = thread._local()      # <- NOT_RPYTHON
         unique_id = ThreadLocalReference._COUNT
         ThreadLocalReference._COUNT += 1
-        ThreadLocalField.__init__(self, llmemory.GCREF, 'tlref%d' % unique_id)
+        ThreadLocalField.__init__(self, lltype.Signed, 'tlref%d' % unique_id)
         getraw = self.getraw
         setraw = self.setraw
 
         def get():
             if we_are_translated():
                 from rpython.rtyper.annlowlevel import cast_gcref_to_instance
-                return cast_gcref_to_instance(Cls, getraw())
+                value = getraw()
+                value = lltype.cast_int_to_ptr(llmemory.GCREF, value)
+                return cast_gcref_to_instance(Cls, value)
             else:
                 return getattr(self.local, 'value', None)
 
@@ -337,7 +339,8 @@
                 if not running_on_llinterp:
                     if gcref:
                         _make_sure_does_not_move(gcref)
-                setraw(gcref)
+                value = lltype.cast_ptr_to_int(gcref)
+                setraw(value)
             else:
                 self.local.value = value
 
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -919,8 +919,16 @@
     def op_stack_current(self):
         return 0
 
-    def op_threadlocalref_addr(self, key, value):
+    def op_threadlocalref_addr(self):
         raise NotImplementedError("threadlocalref_addr")
+        ## class FakeThreadLocalAddr(object):
+        ##     is_fake_thread_local_addr = True
+        ##     _TYPE = llmemory.Address
+        ##     def _cast_to_int(self, symbolic=None):
+        ##         return FakeThreadLocalAddrAsInt()
+        ## class FakeThreadLocalAddrAsInt(object):
+        ##     _TYPE = lltype.Signed
+        ## return FakeThreadLocalAddr()
 
     # __________________________________________________________
     # operations on addresses
@@ -967,6 +975,9 @@
             ll_p = rffi.cast(rffi.CArrayPtr(RESTYPE),
                              rffi.ptradd(ll_p, offset))
             value = ll_p[0]
+        ## elif getattr(addr, 'is_fake_thread_local_addr', False):
+        ##     assert type(offset) is CDefinedIntSymbolic
+        ##     value = self.llinterpreter.tlobj[offset.expr]
         else:
             assert offset.TYPE == RESTYPE
             value = getattr(addr, str(RESTYPE).lower())[offset.repeat]
@@ -987,6 +998,9 @@
             ll_p = rffi.cast(rffi.CArrayPtr(ARGTYPE),
                              rffi.ptradd(ll_p, offset))
             ll_p[0] = value
+        ## elif getattr(addr, 'is_fake_thread_local_addr', False):
+        ##     assert type(offset) is CDefinedIntSymbolic
+        ##     self.llinterpreter.tlobj[offset.expr] = value
         else:
             assert offset.TYPE == ARGTYPE
             getattr(addr, str(ARGTYPE).lower())[offset.repeat] = value
diff --git a/rpython/rtyper/lltypesystem/test/test_llmemory.py 
b/rpython/rtyper/lltypesystem/test/test_llmemory.py
--- a/rpython/rtyper/lltypesystem/test/test_llmemory.py
+++ b/rpython/rtyper/lltypesystem/test/test_llmemory.py
@@ -649,3 +649,13 @@
     #assert cast_int_to_adr(i) == adr -- depends on ll2ctypes details
     i = cast_adr_to_int(NULL, mode="forced")
     assert is_valid_int(i) and i == 0
+
+def test_cast_gcref_to_int():
+    A = lltype.GcArray(Address)
+    def f():
+        ptr = lltype.malloc(A, 10)
+        gcref = lltype.cast_opaque_ptr(GCREF, ptr)
+        adr = lltype.cast_ptr_to_int(gcref)
+        assert adr == lltype.cast_ptr_to_int(ptr)
+    f()
+    interpret(f, [])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to