[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