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