[pypy-commit] pypy improve-vmprof-testing: rvmprof: record the correct Python frames during pyjitpl

arigo pypy.commits at gmail.com
Sat Aug 6 10:54:33 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: improve-vmprof-testing
Changeset: r86046:11f391e1f1d6
Date: 2016-08-06 16:56 +0200
http://bitbucket.org/pypy/pypy/changeset/11f391e1f1d6/

Log:	rvmprof: record the correct Python frames during pyjitpl

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
@@ -452,6 +452,8 @@
             prepare = self._handle_math_sqrt_call
         elif oopspec_name.startswith('rgc.'):
             prepare = self._handle_rgc_call
+        elif oopspec_name.startswith('rvmprof.'):
+            prepare = self._handle_rvmprof_call
         elif oopspec_name.endswith('dict.lookup'):
             # also ordereddict.lookup
             prepare = self._handle_dict_lookup_call
@@ -2079,6 +2081,22 @@
         else:
             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:
+            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
+
     def rewrite_op_ll_read_timestamp(self, op):
         op1 = self.prepare_builtin_call(op, "ll_read_timestamp", [])
         return self.handle_residual_call(op1,
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
@@ -140,7 +140,6 @@
 
     def encoding_test(self, func, args, expected,
                       transform=False, liveness=False, cc=None, jd=None):
-        
         graphs = self.make_graphs(func, args)
         #graphs[0].show()
         if transform:
@@ -1112,6 +1111,20 @@
         assert str(e.value).startswith("A virtualizable array is passed aroun")
         assert "<Descr>" in str(e.value)
 
+    def test_rvmprof_code(self):
+        from rpython.rlib.rvmprof import cintf
+        class MyFakeCallControl(FakeCallControl):
+            def guess_call_kind(self, op):
+                return 'builtin'
+        def f(x):
+            s = cintf.enter_code(x)
+            cintf.leave_code(s, x)
+        self.encoding_test(f, [42], """
+            rvmprof_code $0, %i0
+            rvmprof_code $1, %i0
+            void_return
+        """, transform=True, cc=MyFakeCallControl())
+
 
 def check_force_cast(FROM, TO, operations, value):
     """Check that the test is correctly written..."""
diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -1501,6 +1501,10 @@
     def bhimpl_copyunicodecontent(cpu, src, dst, srcstart, dststart, length):
         cpu.bh_copyunicodecontent(src, dst, srcstart, dststart, length)
 
+    @arguments("i", "i")
+    def bhimpl_rvmprof_code(leaving, unique_id):
+        pass #import pdb;pdb.set_trace()
+
     # ----------
     # helpers to resume running in blackhole mode when a guard failed
 
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
@@ -1453,6 +1453,15 @@
             metainterp.history.record(rop.VIRTUAL_REF_FINISH,
                                       [vrefbox, nullbox], None)
 
+    @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)
+
     # ------------------------------
 
     def setup_call(self, argboxes):
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
@@ -6,7 +6,7 @@
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.rtyper.tool import rffi_platform as platform
-from rpython.rlib import rthread
+from rpython.rlib import rthread, jit
 
 class VMProfPlatformUnsupported(Exception):
     pass
@@ -86,6 +86,22 @@
     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: ...
+
+ at jit.oopspec("rvmprof.enter_code(unique_id)")
 def enter_code(unique_id):
     do_use_eci()
     s = lltype.malloc(VMPROFSTACK, flavor='raw')
@@ -95,6 +111,12 @@
     vmprof_tl_stack.setraw(s)
     return s
 
-def leave_code(s):
+ at jit.oopspec("rvmprof.leave_code(s, unique_id)")
+def leave_code(s, unique_id):
     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)
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 jit, rposix
+from rpython.rlib import 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,12 +162,19 @@
     """
     if _hack_update_stack_untranslated:
         from rpython.rtyper.annlowlevel import llhelper
-        enter_code = llhelper(lltype.Ptr(
+        from rpython.rlib import jit
+        enter_code_untr = llhelper(lltype.Ptr(
             lltype.FuncType([lltype.Signed], cintf.PVMPROFSTACK)),
             cintf.enter_code)
-        leave_code = llhelper(lltype.Ptr(
-            lltype.FuncType([cintf.PVMPROFSTACK], lltype.Void)),
+        leave_code_untr = llhelper(lltype.Ptr(
+            lltype.FuncType([cintf.PVMPROFSTACK, lltype.Signed], 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
@@ -179,17 +186,12 @@
             return func
 
         def decorated_function(*args):
-            # If we are being JITted, we want to skip the trampoline, else the
-            # JIT cannot see through it.
-            if not jit.we_are_jitted():
-                unique_id = get_code_fn(*args)._vmprof_unique_id
-                x = enter_code(unique_id)
-                try:
-                    return func(*args)
-                finally:
-                    leave_code(x)
-            else:
+            unique_id = get_code_fn(*args)._vmprof_unique_id
+            x = enter_code(unique_id)
+            try:
                 return func(*args)
+            finally:
+                leave_code(x, unique_id)
 
         decorated_function.__name__ = func.__name__ + '_rvmprof'
         return decorated_function


More information about the pypy-commit mailing list