Author: Armin Rigo <[email protected]>
Branch: vmprof-review
Changeset: r78739:251e3d7a6609
Date: 2015-08-02 15:57 +0200
http://bitbucket.org/pypy/pypy/changeset/251e3d7a6609/

Log:    Pass the translation tests for the generated trampolines

diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py
--- a/rpython/rlib/rvmprof/cintf.py
+++ b/rpython/rlib/rvmprof/cintf.py
@@ -1,5 +1,83 @@
+from rpython.tool.udir import udir
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
 
 def vmprof_init(): pass
 def vmprof_enable(fileno, interval_usec): return 0
 def vmprof_ignore_signals(ignore): pass
+
+
+def token2lltype(tok):
+    if tok == 'i':
+        return lltype.Signed
+    if tok == 'r':
+        return llmemory.GCREF
+    raise NotImplementedError(repr(tok))
+
+def make_trampoline_function(name, func, token, restok):
+    from rpython.jit.backend import detect_cpu
+
+    cont_name = 'vmprof_f_%s_%s' % (name, token)
+    tramp_name = 'vmprof_t_%s_%s' % (name, token)
+
+    func.c_name = cont_name
+    func._dont_inline_ = True
+
+    assert detect_cpu.autodetect() == detect_cpu.MODEL_X86_64, (
+        "rvmprof only supports x86-64 CPUs for now")
+
+    # mapping of argument count (not counting the final uid argument) to
+    # the register that holds this uid argument
+    reg = {0: '%rdi',
+           1: '%rsi',
+           2: '%rdx',
+           3: '%rcx',
+           4: '%r8',
+           5: '%r9',
+           }
+    reg = reg[len(token)]
+
+    target = udir.join('module_cache')
+    target.ensure(dir=1)
+    target = target.join('trampoline_%s_%s.vmprof.s' % (name, token))
+    target.write("""\
+\t.text
+\t.globl\t%(tramp_name)s
+\t.type\t%(tramp_name)s, @function
+%(tramp_name)s:
+\t.cfi_startproc
+\tpushq\t%(reg)s
+\t.cfi_def_cfa_offset 16
+\tcall %(cont_name)s@PLT
+\taddq\t$8, %%rsp
+\t.cfi_def_cfa_offset 8
+\tret
+\t.cfi_endproc
+\t.size\t%(tramp_name)s, .-%(tramp_name)s
+""" % locals())
+
+    def tok2cname(tok):
+        if tok == 'i':
+            return 'long'
+        if tok == 'r':
+            return 'void *'
+        raise NotImplementedError(repr(tok))
+
+    header = '%s %s(%s);\n' % (
+        tok2cname(restok),
+        tramp_name,
+        ', '.join([tok2cname(tok) for tok in token] + ['long']))
+
+    eci = ExternalCompilationInfo(
+        post_include_bits = [header],
+        separate_module_files = [str(target)],
+    )
+
+    return rffi.llexternal(
+        tramp_name,
+        [token2lltype(tok) for tok in token] + [lltype.Signed],
+        token2lltype(restok),
+        compilation_info=eci,
+        _nowrapper=True, sandboxsafe=True,
+        random_effects_on_gcobjs=True)
diff --git a/rpython/rlib/rvmprof/rvmprof.py b/rpython/rlib/rvmprof/rvmprof.py
--- a/rpython/rlib/rvmprof/rvmprof.py
+++ b/rpython/rlib/rvmprof/rvmprof.py
@@ -3,6 +3,8 @@
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib import jit, rgc
 from rpython.rlib.rvmprof import cintf
+from rpython.rtyper.annlowlevel import cast_instance_to_gcref
+from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance
 
 MAX_CODES = 8000
 
@@ -161,10 +163,12 @@
         b.append(chr((l >> 56) & 0xff))
 
 
-def vmprof_execute_code(get_code_fn, result_class=None):
+def vmprof_execute_code(name, get_code_fn, result_class=None):
     """Decorator to be used on the function that interprets a code object.
 
-    get_code_fn(*args) is called to extract the code object from the
+    'name' must be a unique name.
+
+    'get_code_fn(*args)' is called to extract the code object from the
     arguments given to the decorated function.
 
     The original function can return None, an integer, or an instance.
@@ -174,23 +178,30 @@
     instances or plain integer arguments, and at most 5 of them
     (including 'self' if applicable).
     """
-    def lower(*args):
-        if len(args) == 0:
-            return (), ""
-        ll_args, token = lower(*args[1:])
-        ll_arg = args[0]
-        if isintance(ll_arg, int):
-            tok = "i"
-        else:
-            tok = "r"
-            ll_arg = cast_instance_to_gcref(ll_arg)
-        return (ll_arg,) + ll_args, tok + token
+    def decorate(func):
 
-    @specialize.memo()
-    def get_ll_trampoline(func, token):
-        xxx
+        def lower(*args):
+            if len(args) == 0:
+                return (), ""
+            ll_args, token = lower(*args[1:])
+            ll_arg = args[0]
+            if isinstance(ll_arg, int):
+                tok = "i"
+            else:
+                tok = "r"
+                ll_arg = cast_instance_to_gcref(ll_arg)
+            return (ll_arg,) + ll_args, tok + token
 
-    def decorate(func):
+        @specialize.memo()
+        def get_ll_trampoline(token):
+            assert len(token) <= 5, (
+                "not supported: %r takes more than 5 arguments" % (func,))
+            if result_class is None:
+                restok = "i"
+            else:
+                restok = "r"
+            return cintf.make_trampoline_function(name, func, token, restok)
+
         def decorated_function(*args):
             # go through the asm trampoline ONLY if we are translated but not
             # being JITted.
@@ -205,7 +216,7 @@
                 # if we are translated, call the trampoline
                 unique_id = get_code_fn(*args)._vmprof_unique_id
                 ll_args, token = lower(*args)
-                ll_trampoline = get_ll_trampoline(func, token)
+                ll_trampoline = get_ll_trampoline(token)
                 ll_result = ll_trampoline(*ll_args + (unique_id,))
                 if result_class is not None:
                     return cast_base_ptr_to_instance(result_class, ll_result)
@@ -215,6 +226,7 @@
                 return func(*args)
         decorated_function.__name__ = func.__name__ + '_rvmprof'
         return decorated_function
+
     return decorate
 
 
diff --git a/rpython/rlib/rvmprof/test/test_rvmprof.py 
b/rpython/rlib/rvmprof/test/test_rvmprof.py
--- a/rpython/rlib/rvmprof/test/test_rvmprof.py
+++ b/rpython/rlib/rvmprof/test/test_rvmprof.py
@@ -1,4 +1,5 @@
 from rpython.rlib.rvmprof import get_vmprof, vmprof_execute_code
+from rpython.translator.c.test.test_genc import compile
 
 
 def test_vmprof_execute_code_1():
@@ -7,8 +8,40 @@
         pass
     get_vmprof().register_code_object_class(MyCode, lambda code: 'some code')
 
-    @vmprof_execute_code(lambda code, num: code)
+    @vmprof_execute_code("xcode1", lambda code, num: code)
     def main(code, num):
         print num
+        return 42
 
-    main(MyCode(), 5)
+    def f():
+        res = main(MyCode(), 5)
+        assert res == 42
+        return 0
+
+    assert f() == 0
+    fn = compile(f, [])
+    assert fn() == 0
+
+
+def test_vmprof_execute_code_2():
+
+    class MyCode:
+        pass
+    get_vmprof().register_code_object_class(MyCode, lambda code: 'some code')
+
+    class A:
+        pass
+
+    @vmprof_execute_code("xcode2", lambda num, code: code, result_class=A)
+    def main(num, code):
+        print num
+        return A()
+
+    def f():
+        a = main(7, MyCode())
+        assert isinstance(a, A)
+        return 0
+
+    assert f() == 0
+    fn = compile(f, [])
+    assert fn() == 0
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to