[pypy-dev] Patch: TSC support

Nicholas Riley njriley at uiuc.edu
Fri Dec 16 03:38:25 CET 2005


The attached patch provides an equivalent of CPython's --with-tsc for
pypy-c on x86, PowerPC and Alpha, for Linux and Mac OS X (where
available).  You enable it with the --tsc flag and use sys.settscdump
just as in CPython.

This was mostly "my first PyPy project", written as a learning
experience; I'm posting it in case it would be useful for others.

-- 
Nicholas Riley <njriley at uiuc.edu> | <http://www.uiuc.edu/ph/www/njriley>
-------------- next part --------------
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/interpreter/executioncontext.py pypy-njr/pypy/interpreter/executioncontext.py
--- pypy-dist/pypy/interpreter/executioncontext.py	Tue Dec  6 15:37:07 2005
+++ pypy-njr/pypy/interpreter/executioncontext.py	Thu Dec 15 17:25:35 2005
@@ -1,4 +1,4 @@
-import sys
+import os, sys
 from pypy.interpreter.miscutils import Stack
 from pypy.interpreter.error import OperationError
 
@@ -15,6 +15,9 @@
         self.ticker = 0
         self.compiler = space.createcompiler()
 
+        self.tscdump = False
+        self.ticked = False
+
     def enter(self, frame):
         if self.framestack.depth() > self.space.sys.recursionlimit:
             raise OperationError(self.space.w_RuntimeError,
@@ -59,11 +62,21 @@
     def bytecode_trace(self, frame):
         "Trace function called before each bytecode."
 
+        if self.tscdump:
+            from pypy.rpython.rtsc import read_diff, reset_diff
+            code = getattr(frame, 'pycode')
+            opcode = code is None and 0 or ord(code.co_code[frame.next_instr])
+            os.write(2, 'opcode=%d t=%d inst=%d\n' %
+                     (opcode, int(self.ticked), read_diff()))
+            self.ticked = False
+            reset_diff()
+
         # First, call yield_thread() before each Nth bytecode,
         #     as selected by sys.setcheckinterval()
         ticker = self.ticker
         if ticker <= 0:
             self.space.threadlocals.yield_thread()
+            self.ticked = True
             ticker = self.space.sys.checkinterval
         self.ticker = ticker - 1
 
@@ -142,6 +155,13 @@
         else:
             self.w_profilefunc = w_func
 
+    def settscdump(self, w_bool):
+        from pypy.rpython.objectmodel import we_are_translated
+        if not we_are_translated():
+            raise OperationError(self.space.w_NotImplementedError,
+                                 self.space.wrap("No access to timestamp counter in untranslated PyPy"))
+        self.tscdump = self.space.is_true(w_bool)
+
     def call_tracing(self, w_func, w_args):
         is_tracing = self.is_tracing
         self.is_tracing = 0
diff -uNr -x '*~' -x '*.pyc' -x _cache pypy-dist/pypy/module/sys/__init__.py pypy-njr/pypy/module/sys/__init__.py
--- pypy-dist/pypy/module/sys/__init__.py	Tue Dec  6 15:37:15 2005
+++ pypy-njr/pypy/module/sys/__init__.py	Mon Dec 12 00:56:39 2005
@@ -45,6 +45,7 @@
         'settrace'              : 'vm.settrace',
         'setprofile'            : 'vm.setprofile',
         'call_tracing'          : 'vm.call_tracing',
+        'settscdump'		: 'vm.settscdump',
         
         'executable'            : 'space.wrap("py.py")', 
         'copyright'             : 'space.wrap("MIT-License")', 
diff -uNr -x '*~' -x '*.pyc' -x _cache pypy-dist/pypy/module/sys/vm.py pypy-njr/pypy/module/sys/vm.py
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/module/sys/vm.py pypy-njr/pypy/module/sys/vm.py
--- pypy-dist/pypy/module/sys/vm.py	Tue Dec  6 15:37:15 2005
+++ pypy-njr/pypy/module/sys/vm.py	Wed Dec 14 23:34:36 2005
@@ -113,3 +113,11 @@
 saved, and restored afterwards.  This is intended to be called from
 a debugger from a checkpoint, to recursively debug some other code."""
     return space.getexecutioncontext().call_tracing(w_func, w_args)
+
+def settscdump(space, w_bool):
+    """settscdump(bool)
+
+If true, tell the Python interpreter to dump VM measurements to
+stderr.  If false, turn off dump.  The measurements are based on the
+processor's time-stamp counter."""
+    space.getexecutioncontext().settscdump(w_bool)
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/module/trans/interp_trans.py pypy-njr/pypy/module/trans/interp_trans.py
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/rpython/extfunctable.py pypy-njr/pypy/rpython/extfunctable.py
--- pypy-dist/pypy/rpython/extfunctable.py	Wed Dec 14 22:03:19 2005
+++ pypy-njr/pypy/rpython/extfunctable.py	Thu Dec 15 17:11:50 2005
@@ -231,6 +231,13 @@
                                                   'll_stackless/switch'))
 
 # ___________________________________________________________
+# timestamp counter
+from pypy.rpython import rtsc
+declare(rtsc.read, r_longlong, 'll_tsc/read')
+declare(rtsc.read_diff, int, 'll_tsc/read_diff')
+declare(rtsc.reset_diff, noneannotation, 'll_tsc/reset_diff')
+
+# ___________________________________________________________
 # the exceptions that can be implicitely raised by some operations
 standardexceptions = {
     TypeError        : True,
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/rpython/module/ll_trans.py pypy-njr/pypy/rpython/module/ll_trans.py
--- pypy-dist/pypy/rpython/module/ll_tsc.py	Wed Dec 31 18:00:00 1969
+++ pypy-njr/pypy/rpython/module/ll_tsc.py	Wed Dec 14 23:27:36 2005
@@ -0,0 +1,13 @@
+from pypy.rpython.rarithmetic import r_longlong
+
+def ll_tsc_read():
+    return r_longlong(0)
+ll_tsc_read.suggested_primitive = True
+
+def ll_tsc_read_diff():
+    return 0
+ll_tsc_read_diff.suggested_primitive = True
+
+def ll_tsc_reset_diff():
+    pass
+ll_tsc_reset_diff.suggested_primitive = True
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/rpython/rtsc.py pypy-njr/pypy/rpython/rtsc.py
--- pypy-dist/pypy/rpython/rtsc.py	Wed Dec 31 18:00:00 1969
+++ pypy-njr/pypy/rpython/rtsc.py	Wed Dec 14 23:28:16 2005
@@ -0,0 +1,8 @@
+def read():
+    raise NotImplementedError("only works in translated versions")
+
+def read_diff():
+    raise NotImplementedError("only works in translated versions")
+
+def reset_diff():
+    raise NotImplementedError("only works in translated versions")
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/rpython/test/test_rpbc.py pypy-njr/pypy/rpython/test/test_rpbc.py
--- pypy-dist/pypy/translator/c/extfunc.py	Fri Dec  9 16:19:28 2005
+++ pypy-njr/pypy/translator/c/extfunc.py	Wed Dec 14 23:20:08 2005
@@ -5,7 +5,7 @@
 from pypy.rpython.rstr import STR
 from pypy.rpython import rlist
 from pypy.rpython.module import ll_os, ll_time, ll_math, ll_strtod
-from pypy.rpython.module import ll_stackless, ll_stack
+from pypy.rpython.module import ll_stackless, ll_stack, ll_tsc
 from pypy.module.thread.rpython import ll_thread
 from pypy.module._socket.rpython import ll__socket
 
@@ -53,6 +54,9 @@
     ll_thread.ll_releaselock:      'LL_thread_releaselock',
     ll_thread.ll_thread_start:     'LL_thread_start',
     ll_thread.ll_thread_get_ident: 'LL_thread_get_ident',
+    ll_tsc.ll_tsc_read:      'LL_tsc_read',
+    ll_tsc.ll_tsc_read_diff: 'LL_tsc_read_diff',
+    ll_tsc.ll_tsc_reset_diff:'LL_tsc_reset_diff',
     ll_stackless.ll_stackless_switch:             'LL_stackless_switch',
     ll_stackless.ll_stackless_stack_frames_depth: 'LL_stackless_stack_frames_depth',
     ll_stack.ll_stack_unwind: 'LL_stack_unwind',
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/translator/c/genc.py pypy-njr/pypy/translator/c/genc.py
--- pypy-dist/pypy/translator/c/genc.py	Tue Dec  6 15:37:20 2005
+++ pypy-njr/pypy/translator/c/genc.py	Thu Dec 15 17:11:53 2005
@@ -19,11 +19,12 @@
     symboltable = None
     stackless = False
     
-    def __init__(self, translator, entrypoint, gcpolicy=None, libraries=None, thread_enabled=False):
+    def __init__(self, translator, entrypoint, gcpolicy=None, libraries=None, thread_enabled=False, tsc_enabled=False):
         self.translator = translator
         self.entrypoint = entrypoint
         self.gcpolicy = gcpolicy
         self.thread_enabled = thread_enabled
+        self.tsc_enabled = tsc_enabled
 
         if libraries is None:
             libraries = []
@@ -73,6 +74,8 @@
         else:
             if self.stackless:
                 defines['USE_STACKLESS'] = '1'
+            if self.tsc_enabled:
+                defines['USE_TSC'] = '1'
             cfile, extra = gen_source_standalone(db, modulename, targetdir,
                                                  entrypointname = pfname,
                                                  defines = defines)
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/translator/c/src/g_include.h pypy-njr/pypy/translator/c/src/g_include.h
--- pypy-dist/pypy/translator/c/src/g_include.h	Fri Dec  9 05:04:34 2005
+++ pypy-njr/pypy/translator/c/src/g_include.h	Tue Dec 13 22:43:40 2005
@@ -40,6 +40,7 @@
 #  include "src/ll_thread.h"
 #  include "src/ll_stackless.h"
 #  include "src/ll__socket.h"
+#  include "src/ll_tsc.h"
 #endif
 
 #include "src/stack.h"
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/translator/c/src/ll_trans.h pypy-njr/pypy/translator/c/src/ll_trans.h
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/translator/c/src/ll_tsc.h pypy-njr/pypy/translator/c/src/ll_tsc.h
--- pypy-dist/pypy/translator/c/src/ll_tsc.h	Wed Dec 31 18:00:00 1969
+++ pypy-njr/pypy/translator/c/src/ll_tsc.h	Wed Dec 14 23:25:01 2005
@@ -0,0 +1,85 @@
+/************************************************************/
+/***  C header subsection: timestamp counter access       ***/
+
+
+#if defined(USE_TSC)
+
+typedef unsigned long long uint64;
+
+/* prototypes */
+
+uint64 LL_tsc_read(void);
+long LL_tsc_read_diff(void);
+void LL_tsc_reset_diff(void);
+
+/* implementations */
+
+#ifndef PYPY_NOT_MAIN_FILE
+
+#if defined(__alpha__)
+
+#define rdtscll(pcc) asm volatile ("rpcc %0" : "=r" (pcc))
+
+#elif defined(__ppc__)
+
+#define rdtscll(var) ppc_getcounter(&var)
+
+static void
+ppc_getcounter(uint64 *v)
+{
+	register unsigned long tbu, tb, tbu2;
+
+  loop:
+	asm volatile ("mftbu %0" : "=r" (tbu) );
+	asm volatile ("mftb  %0" : "=r" (tb)  );
+	asm volatile ("mftbu %0" : "=r" (tbu2));
+	if (__builtin_expect(tbu != tbu2, 0)) goto loop;
+
+	((long*)(v))[0] = tbu;
+	((long*)(v))[1] = tb;
+}
+
+#else /* this section is for linux/x86 */
+
+#define rdtscll(val) asm volatile ("rdtsc" : "=A" (val))
+
+#endif
+
+uint64
+LL_tsc_read(void)
+{
+	uint64 tsc;
+	rdtscll(tsc);
+
+	return tsc;
+}
+
+static uint64 tsc_last = 0;
+
+/* don't use for too long a diff, overflow problems:
+   http://www.sandpile.org/post/msgs/20003444.htm */
+
+long
+LL_tsc_read_diff(void)
+{
+	uint64 new_tsc;
+	unsigned long tsc_diff;
+
+	/* returns garbage the first time you call it */
+	rdtscll(new_tsc);
+	tsc_diff = new_tsc - tsc_last;
+	tsc_last = new_tsc;
+	
+	return tsc_diff;
+}
+
+void
+LL_tsc_reset_diff(void)
+{
+	rdtscll(tsc_last);
+}
+
+#endif /* PYPY_NOT_MAIN_FILE */
+
+#endif /* defined(USE_TSC) */
+
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/translator/goal/driver.py pypy-njr/pypy/translator/goal/driver.py
--- pypy-dist/pypy/translator/goal/driver.py	Tue Dec  6 15:37:19 2005
+++ pypy-njr/pypy/translator/goal/driver.py	Thu Dec 15 17:11:52 2005
@@ -1,4 +1,4 @@
-import sys, os
+
 
 from pypy.translator.translator import TranslationContext
 from pypy.translator.tool.taskengine import SimpleTaskEngine
@@ -20,6 +20,7 @@
   'thread': False, # influences GC policy
 
   'stackless': False,
+  'tsc': False,
   'debug': True,
   'insist': False,
   'backend': 'c',
@@ -208,7 +209,8 @@
             from pypy.translator.c.genc import CExtModuleBuilder as CBuilder
         cbuilder = CBuilder(self.translator, self.entry_point,
                             gcpolicy       = gcpolicy,
-                            thread_enabled = getattr(opt, 'thread', False))
+                            thread_enabled = getattr(opt, 'thread', False),
+                            tsc_enabled    = getattr(opt, 'tsc', False))
         cbuilder.stackless = opt.stackless
         database = cbuilder.build_database()
         self.log.info("database for generating C source was created")
diff -uNr -x '*~' -x '*.pyc' -x '_*' pypy-dist/pypy/translator/goal/run_pypy-llvm.sh pypy-njr/pypy/translator/goal/run_pypy-llvm.sh
--- pypy-dist/pypy/translator/goal/translate_pypy.py	Sat Dec 10 21:57:29 2005
+++ pypy-njr/pypy/translator/goal/translate_pypy.py	Thu Dec 15 17:11:52 2005
@@ -50,6 +51,8 @@
 
     '2_gc': [OPT(('--gc',), "Garbage collector", ['boehm', 'ref', 'none'])],
     '3_stackless': [OPT(('--stackless',), "Stackless code generation", True)],
+    '4_tsc': [OPT(('--tsc',), "(x86, PowerPC, Alpha) Timestamp counter profile",
+                  True)],
     },
 
 
@@ -101,6 +105,7 @@
     'gc': 'boehm',
     'backend': 'c',
     'stackless': False,
+    'tsc': False,
     
     'batch': False,
     'text': False,


More information about the Pypy-dev mailing list