Author: Armin Rigo <[email protected]>
Branch: improve-vmprof-testing
Changeset: r86052:271af761ce0b
Date: 2016-08-07 09:32 +0200
http://bitbucket.org/pypy/pypy/changeset/271af761ce0b/

Log:    in-progress

diff --git a/rpython/jit/backend/test/test_rvmprof.py 
b/rpython/jit/backend/test/test_rvmprof.py
--- a/rpython/jit/backend/test/test_rvmprof.py
+++ b/rpython/jit/backend/test/test_rvmprof.py
@@ -7,7 +7,73 @@
 from rpython.jit.backend.x86.arch import WORD
 from rpython.jit.codewriter.policy import JitPolicy
 
+
 class BaseRVMProfTest(object):
+
+    def setup_method(self, meth):
+        visited = []
+
+        def helper():
+            trace = []
+            stack = cintf.vmprof_tl_stack.getraw()
+            while stack:
+                trace.append((stack.c_kind, stack.c_value))
+                stack = stack.c_next
+            visited.append(trace)
+
+        llfn = llhelper(lltype.Ptr(lltype.FuncType([], lltype.Void)), helper)
+
+        class CodeObj(object):
+            def __init__(self, name):
+                self.name = name
+
+        def get_code_fn(codes, code, arg, c):
+            return code
+
+        def get_name(code):
+            return "foo"
+
+        _get_vmprof().use_weaklist = False
+        register_code_object_class(CodeObj, get_name)
+
+        self.misc = visited, llfn, CodeObj, get_code_fn, get_name
+
+
+    def teardown_method(self, meth):
+        del _get_vmprof().use_weaklist
+
+
+    def test_simple(self):
+        visited, llfn, CodeObj, get_code_fn, get_name = self.misc
+        driver = jit.JitDriver(greens=['code'], reds=['c', 'i', 'n', 'codes'])
+
+        @vmprof_execute_code("main", get_code_fn,
+                             _hack_update_stack_untranslated=True)
+        def f(codes, code, n, c):
+            i = 0
+            while i < n:
+                driver.jit_merge_point(code=code, c=c, i=i, codes=codes, n=n)
+                if code.name == "main":
+                    c = f(codes, codes[1], 1, c)
+                    driver.can_enter_jit(code=code, c=c, i=i, codes=codes, n=n)
+                else:
+                    llfn()
+                    c -= 1
+                i += 1
+            return c
+
+        def main(n):
+            codes = [CodeObj("main"), CodeObj("not main")]
+            for code in codes:
+                register_code(code, get_name)
+            return f(codes, codes[0], n, 8)
+
+        null = lltype.nullptr(cintf.VMPROFSTACK)
+        cintf.vmprof_tl_stack.setraw(null)
+        self.meta_interp(main, [30], inline=True)
+        assert visited[:3] == [[(1, 12), (1, 8)], [(1, 12), (1, 8)], [(1, 12), 
(1, 8)]]
+
+
     def test_one(self):
 #        py.test.skip("needs thread-locals in the JIT, which is only available 
"
 #                     "after translation")
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
@@ -2082,20 +2082,10 @@
             raise NotImplementedError(oopspec_name)
 
     def _handle_rvmprof_call(self, op, oopspec_name, args):
-        if oopspec_name == 'rvmprof.enter_code':
-            leaving = 0
-        elif oopspec_name == 'rvmprof.leave_code':
-            leaving = 1
-        else:
+        if oopspec_name != 'rvmprof.code':
             raise NotImplementedError(oopspec_name)
-        c_leaving = Constant(leaving, lltype.Signed)
-        v_uniqueid = op.args[-1]
-        ops = [SpaceOperation('rvmprof_code', [c_leaving, v_uniqueid], None)]
-        if op.result.concretetype is not lltype.Void:
-            c_null = Constant(lltype.nullptr(op.result.concretetype.TO),
-                              op.result.concretetype)
-            ops.append(c_null)
-        return ops
+        c_leaving, v_uniqueid = args
+        return SpaceOperation('rvmprof_code', [c_leaving, v_uniqueid], None)
 
     def rewrite_op_ll_read_timestamp(self, op):
         op1 = self.prepare_builtin_call(op, "ll_read_timestamp", [])
diff --git a/rpython/jit/codewriter/test/test_flatten.py 
b/rpython/jit/codewriter/test/test_flatten.py
--- a/rpython/jit/codewriter/test/test_flatten.py
+++ b/rpython/jit/codewriter/test/test_flatten.py
@@ -14,7 +14,7 @@
 from rpython.rlib.rarithmetic import ovfcheck, r_uint, r_longlong, r_ulonglong
 from rpython.rlib.jit import dont_look_inside, _we_are_jitted, JitDriver
 from rpython.rlib.objectmodel import keepalive_until_here
-from rpython.rlib import jit
+from rpython.rlib import jit, debug
 
 
 class FakeRegAlloc:
@@ -1115,14 +1115,26 @@
         from rpython.rlib.rvmprof import cintf
         class MyFakeCallControl(FakeCallControl):
             def guess_call_kind(self, op):
-                return 'builtin'
+                if '_code' in repr(op):
+                    return 'builtin'
+                return 'residual'
+        class X:
+            pass
+        def g():
+            debug.debug_print("foo")
+            return X()
+        g._dont_inline_ = True
         def f(x):
-            s = cintf.enter_code(x)
-            cintf.leave_code(s, x)
+            cintf.jit_rvmprof_code(0, x)
+            res = g()
+            cintf.jit_rvmprof_code(1, x)
+            return res
         self.encoding_test(f, [42], """
             rvmprof_code $0, %i0
+            residual_call_r_r $<* fn g>, R[], <Descr> -> %r0
+            -live-
             rvmprof_code $1, %i0
-            void_return
+            ref_return %r0
         """, transform=True, cc=MyFakeCallControl())
 
 
diff --git a/rpython/jit/metainterp/pyjitpl.py 
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -74,6 +74,8 @@
         self.parent_snapshot = None
         # counter for unrolling inlined loops
         self.unroll_iterations = 1
+        # rvmprof
+        self.rvmprof_unique_id = -1
 
     @specialize.arg(3)
     def copy_constants(self, registers, constants, ConstClass):
@@ -1456,11 +1458,7 @@
     @arguments("int", "box")
     def opimpl_rvmprof_code(self, leaving, box_unique_id):
         from rpython.rlib.rvmprof import cintf
-        unique_id = box_unique_id.getint()
-        if not leaving:
-            cintf.enter_code(unique_id)
-        else:
-            cintf.leave_code_check(unique_id)
+        cintf.jit_rvmprof_code(leaving, box_unique_id.getint())
 
     # ------------------------------
 
@@ -1813,6 +1811,7 @@
             opimpl = _get_opimpl_method(name, argcodes)
             self.opcode_implementations[value] = opimpl
         self.op_catch_exception = insns.get('catch_exception/L', -1)
+        self.op_rvmprof_code = insns.get('rvmprof_code/ii', -1)
 
     def setup_descrs(self, descrs):
         self.opcode_descrs = descrs
@@ -2080,6 +2079,10 @@
                     target = ord(code[position+1]) | (ord(code[position+2])<<8)
                     frame.pc = target
                     raise ChangeFrame
+                if opcode == self.staticdata.op_rvmprof_code:
+                    # do the 'leave_code' for rvmprof, but then continue
+                    # popping frames
+                    import pdb;pdb.set_trace()
             self.popframe()
         try:
             self.compile_exit_frame_with_exception(self.last_exc_box)
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
@@ -86,22 +86,6 @@
     ExternalCompilationInfo(includes=['vmprof_stack.h'],
                             include_dirs = [SRC]))
 
-# JIT notes:
-#
-# - When running JIT-generated assembler code, we have different custom
-#   code to build the VMPROFSTACK, so the functions below are not used.
-#
-# - The jitcode for decorated_function() in rvmprof.py still contains
-#   calls to these two oopspec functions, which are represented with
-#   the 'rvmprof_code' jitcode opcode.
-#
-# - When meta-interpreting, the 'rvmprof_code' opcode causes pyjitpl
-#   to call enter_code()/leave_code_check(), but otherwise
-#   'rvmprof_code' is ignored, i.e. doesn't produce any resop.
-#
-# - Blackhole: ...
-
[email protected]("rvmprof.enter_code(unique_id)")
 def enter_code(unique_id):
     do_use_eci()
     s = lltype.malloc(VMPROFSTACK, flavor='raw')
@@ -111,12 +95,52 @@
     vmprof_tl_stack.setraw(s)
     return s
 
[email protected]("rvmprof.leave_code(s, unique_id)")
-def leave_code(s, unique_id):
+def leave_code(s):
     vmprof_tl_stack.setraw(s.c_next)
     lltype.free(s, flavor='raw')
 
-def leave_code_check(unique_id):
-    s = vmprof_tl_stack.getraw()
-    assert s.c_value == unique_id
-    leave_code(s, unique_id)
+#
+# JIT notes:
+#
+# - When running JIT-generated assembler code, we have different custom
+#   code to build the VMPROFSTACK, so the functions above are not used.
+#   (It uses kind == VMPROF_JITTED_TAG and the VMPROFSTACK is allocated
+#   in the C stack.)
+#
+# - The jitcode for decorated_jitted_function() in rvmprof.py, if
+#   we_are_jitted() calls the oopspec'ed function jit_rvmprof_code(),
+#   which turns into a simple jitcode opcode.  The jitcode has a
+#   simple structure:
+#
+#        rvmprof_code(0, unique_id)
+#        res = inline_call FUNC
+#        rvmprof_code(1, unique_id)
+#
+#   with no catch_exception logic for a "finally:" block.  Instead the
+#   blackhole interp looks for this simple pattern.  This is needed
+#   because, when a guard fails, the blackhole interp first rebuilds
+#   all the intermediate RPython frames; at that point it needs to
+#   call enter_code() on all intermediate RPython frames, so it does
+#   pattern matching to recognize frames and learn about unique_id.
+#
+# - The jitcode opcode 'rvmprof_code' doesn't produce any resop.  When
+#   meta-interpreting, it causes pyjitpl to call jit_enter_code(), and
+#   jit_leave_code().  There is logic to call jit_leave_code() even if
+#   we exit with an exception, even though there is no
+#   'catch_exception'.
+#
+# - When blackholing, the call to jit_enter_code() occurs imediately
+#   as described above.  For calling jit_leave_code(), we use the same
+#   logic, detecting when we need to call it even though there is no
+#   'catch_exception'.
+
[email protected]("rvmprof.code(leaving, unique_id)")
+def jit_rvmprof_code(leaving, unique_id):
+    """Marker for the JIT.  Also called directly from the metainterp and
+    the blackhole interp."""
+    if not leaving:
+        enter_code(unique_id)    # ignore the return value
+    else:
+        s = vmprof_tl_stack.getraw()
+        assert s.c_value == unique_id
+        leave_code(s)
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
@@ -1,6 +1,6 @@
 import sys, os
 from rpython.rlib.objectmodel import specialize, we_are_translated
-from rpython.rlib import rposix
+from rpython.rlib import jit, rposix
 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
@@ -162,19 +162,12 @@
     """
     if _hack_update_stack_untranslated:
         from rpython.rtyper.annlowlevel import llhelper
-        from rpython.rlib import jit
-        enter_code_untr = llhelper(lltype.Ptr(
+        enter_code = llhelper(lltype.Ptr(
             lltype.FuncType([lltype.Signed], cintf.PVMPROFSTACK)),
             cintf.enter_code)
-        leave_code_untr = llhelper(lltype.Ptr(
-            lltype.FuncType([cintf.PVMPROFSTACK, lltype.Signed], lltype.Void)),
+        leave_code = llhelper(lltype.Ptr(
+            lltype.FuncType([cintf.PVMPROFSTACK], lltype.Void)),
             cintf.leave_code)
-        @jit.oopspec("rvmprof.enter_code(unique_id)")
-        def enter_code(unique_id):
-            return enter_code_untr(unique_id)
-        @jit.oopspec("rvmprof.leave_code(s)")
-        def leave_code(s, unique_id):
-            leave_code_untr(s, unique_id)
     else:
         enter_code = cintf.enter_code
         leave_code = cintf.leave_code
@@ -185,13 +178,24 @@
         except cintf.VMProfPlatformUnsupported:
             return func
 
+        def decorated_jitted_function(unique_id, *args):
+            cintf.jit_rvmprof_code(0, unique_id)
+            res = func(*args)
+            cintf.jit_rvmprof_code(1, unique_id)   # no 'finally:', see 
cintf.py
+            return res
+        decorated_jitted_function._dont_inline_ = True
+
         def decorated_function(*args):
             unique_id = get_code_fn(*args)._vmprof_unique_id
-            x = enter_code(unique_id)
-            try:
-                return func(*args)
-            finally:
-                leave_code(x, unique_id)
+            if not jit.we_are_jitted():
+                x = enter_code(unique_id)
+                try:
+                    return func(*args)
+                finally:
+                    leave_code(x)
+            else:
+                return decorated_jitted_function(unique_id, *args)
+        decorated_function._always_inline_ = True
 
         decorated_function.__name__ = func.__name__ + '_rvmprof'
         return decorated_function
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to