diff -r 3c3009f63700 -r c64a284f4309 Include/frameobject.h --- a/Include/frameobject.h Mon Nov 14 18:04:05 2011 +0200 +++ b/Include/frameobject.h Tue Nov 22 01:45:16 2011 +0100 @@ -44,6 +44,9 @@ PyCode_Addr2Line to calculate the line from the current bytecode index. */ int f_lineno; /* Current line number */ +#ifdef WITH_DTRACE + int f_calllineno; /* line number of call site */ +#endif int f_iblock; /* index in f_blockstack */ PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */ PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */ diff -r 3c3009f63700 -r c64a284f4309 Include/phelper.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Include/phelper.d Tue Nov 22 01:45:16 2011 +0100 @@ -0,0 +1,149 @@ + +/* + * Python ustack helper. This relies on the first argument (PyFrame *) being + * on the stack; see Python/ceval.c for the contortions we go through to ensure + * this is the case. + * + * On x86, the PyFrame * is two slots up from the frame pointer; on SPARC, it's + * eight. + */ + +/* + * Yes, this is as gross as it looks. DTrace cannot handle static functions, + * and our stat_impl.h has them in ILP32. + */ +#define _SYS_STAT_H + +/* +** When compiling in 32 bits: +** - Early inclusion to avoid problems with +** _FILE_OFFSET_BITS redefined. +** - Also, we must "undef" _POSIX_PTHREAD_SEMANTICS +** to avoid error compiling this source. +*/ +#include "pyconfig.h" +#undef _POSIX_PTHREAD_SEMANTICS + +#include +#include + +#include "pyport.h" +#include "object.h" +#include "pystate.h" +#include "pyarena.h" +#include "pythonrun.h" +#include "compile.h" +#include "frameobject.h" +#include "stringobject.h" + +#if defined(__i386) +#define startframe PyEval_EvalFrameEx +#define endframe PyEval_EvalCodeEx +#elif defined(__amd64) +#define PyEval_EvalFrameEx PyEval_EvalFrameExReal +#define startframe PyEval_EvalFrameExReal +#define endframe PyEval_EvalCodeEx +#elif defined(__sparc) +#define PyEval_EvalFrameEx PyEval_EvalFrameExReal +#define startframe PyEval_EvalFrameEx +#define endframe PyEval_EvalFrameExReal +#endif + +#ifdef __sparcv9 +#define STACK_BIAS (2048-1) +#else +#define STACK_BIAS 0 +#endif + +/* + * Not defining PHELPER lets us test this code as a normal D script. + */ +#ifdef PHELPER + +#define at_evalframe(addr) \ + ((uintptr_t)addr >= ((uintptr_t)&``startframe) && \ + (uintptr_t)addr < ((uintptr_t)&``endframe)) +#define probe dtrace:helper:ustack: +#define print_result(r) (r) + +#if defined(__i386) || defined(__amd64) +#define frame_ptr_addr ((uintptr_t)arg1 + sizeof(uintptr_t) * 2) +#elif defined(__sparc) +#define frame_ptr_addr ((uintptr_t)arg1 + STACK_BIAS + sizeof(uintptr_t) * 8) +#else +#error unknown architecture +#endif + +#else /* PHELPER */ + +#define at_evalframe(addr) (1) +#define probe pid$target::PyEval_EvalFrame:entry +#define print_result(r) (trace(r)) + +#if defined(__i386) || defined(__amd64) +#define frame_ptr_addr ((uintptr_t)uregs[R_SP] + sizeof(uintptr_t)) +#elif defined(__sparc) +/* + * Not implemented: we could just use R_I0, but what's the point? + */ +#else +#error unknown architecture +#endif + +#endif /* PHELPER */ + +extern uintptr_t PyEval_EvalFrameEx; +extern uintptr_t PyEval_EvalCodeEx; + +#define copyin_obj(addr, obj) ((obj *)copyin((uintptr_t)addr, sizeof(obj))) +#define pystr_addr(addr) ((char *)addr + offsetof(PyStringObject, ob_sval)) +#define copyin_str(dest, addr, obj) \ + (copyinto((uintptr_t)pystr_addr(addr), obj->ob_size, (dest))) +#define add_str(addr, obj) \ + copyin_str(this->result + this->pos, addr, obj); \ + this->pos += obj->ob_size; \ + this->result[this->pos] = '\0'; +#define add_digit(nr, div) ((nr / div) ? \ + (this->result[this->pos++] = '0' + ((nr / div) % 10)) : \ + (this->result[this->pos] = '\0')) +#define add_char(c) (this->result[this->pos++] = c) + +probe /at_evalframe(arg0)/ +{ + this->framep = *(uintptr_t *)copyin(frame_ptr_addr, sizeof(uintptr_t)); + this->frameo = copyin_obj(this->framep, PyFrameObject); + this->codep = this->frameo->f_code; + this->lineno = this->frameo->f_calllineno; + this->codeo = copyin_obj(this->codep, PyCodeObject); + this->filenamep = this->codeo->co_filename; + this->fnamep = this->codeo->co_name; + this->filenameo = copyin_obj(this->filenamep, PyStringObject); + this->fnameo = copyin_obj(this->fnamep, PyStringObject); + + this->len = 1 + this->filenameo->ob_size + 1 + 5 + 2 + + this->fnameo->ob_size + 1 + 1; + + this->result = (char *)alloca(this->len); + this->pos = 0; + + add_char('@'); + add_str(this->filenamep, this->filenameo); + add_char(':'); + add_digit(this->lineno, 10000); + add_digit(this->lineno, 1000); + add_digit(this->lineno, 100); + add_digit(this->lineno, 10); + add_digit(this->lineno, 1); + add_char(' '); + add_char('('); + add_str(this->fnamep, this->fnameo); + add_char(')'); + this->result[this->pos] = '\0'; + + print_result(stringof(this->result)); +} + +probe /!at_evalframe(arg0)/ +{ + NULL; +} diff -r 3c3009f63700 -r c64a284f4309 Include/pydtrace.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Include/pydtrace.d Tue Nov 22 01:45:16 2011 +0100 @@ -0,0 +1,17 @@ +provider python { + probe function__entry(const char *, const char *, int); + probe function__return(const char *, const char *, int); + probe instance__new__start(const char *, const char *); + probe instance__new__done(const char *, const char *); + probe instance__delete__start(const char *, const char *); + probe instance__delete__done(const char *, const char *); + probe line(const char *, const char *, int); + probe gc__start(int); + probe gc__done(long); +}; + +#pragma D attributes Evolving/Evolving/Common provider python provider +#pragma D attributes Private/Private/Common provider python module +#pragma D attributes Private/Private/Common provider python function +#pragma D attributes Evolving/Evolving/Common provider python name +#pragma D attributes Evolving/Evolving/Common provider python args diff -r 3c3009f63700 -r c64a284f4309 Include/pydtrace.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Include/pydtrace.h Tue Nov 22 01:45:16 2011 +0100 @@ -0,0 +1,101 @@ +/* + * Generated by dtrace(1M). + */ + +#ifndef _PYDTRACE_H +#define _PYDTRACE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if _DTRACE_VERSION + +#define PYTHON_FUNCTION_ENTRY(arg0, arg1, arg2) \ + __dtrace_python___function__entry(arg0, arg1, arg2) +#define PYTHON_FUNCTION_ENTRY_ENABLED() \ + __dtraceenabled_python___function__entry() +#define PYTHON_FUNCTION_RETURN(arg0, arg1, arg2) \ + __dtrace_python___function__return(arg0, arg1, arg2) +#define PYTHON_FUNCTION_RETURN_ENABLED() \ + __dtraceenabled_python___function__return() +#define PYTHON_GC_DONE(arg0) \ + __dtrace_python___gc__done(arg0) +#define PYTHON_GC_DONE_ENABLED() \ + __dtraceenabled_python___gc__done() +#define PYTHON_GC_START(arg0) \ + __dtrace_python___gc__start(arg0) +#define PYTHON_GC_START_ENABLED() \ + __dtraceenabled_python___gc__start() +#define PYTHON_INSTANCE_DELETE_DONE(arg0, arg1) \ + __dtrace_python___instance__delete__done(arg0, arg1) +#define PYTHON_INSTANCE_DELETE_DONE_ENABLED() \ + __dtraceenabled_python___instance__delete__done() +#define PYTHON_INSTANCE_DELETE_START(arg0, arg1) \ + __dtrace_python___instance__delete__start(arg0, arg1) +#define PYTHON_INSTANCE_DELETE_START_ENABLED() \ + __dtraceenabled_python___instance__delete__start() +#define PYTHON_INSTANCE_NEW_DONE(arg0, arg1) \ + __dtrace_python___instance__new__done(arg0, arg1) +#define PYTHON_INSTANCE_NEW_DONE_ENABLED() \ + __dtraceenabled_python___instance__new__done() +#define PYTHON_INSTANCE_NEW_START(arg0, arg1) \ + __dtrace_python___instance__new__start(arg0, arg1) +#define PYTHON_INSTANCE_NEW_START_ENABLED() \ + __dtraceenabled_python___instance__new__start() +#define PYTHON_LINE(arg0, arg1, arg2) \ + __dtrace_python___line(arg0, arg1, arg2) +#define PYTHON_LINE_ENABLED() \ + __dtraceenabled_python___line() + + +extern void __dtrace_python___function__entry(char *, char *, int); +extern int __dtraceenabled_python___function__entry(void); +extern void __dtrace_python___function__return(char *, char *, int); +extern int __dtraceenabled_python___function__return(void); +extern void __dtrace_python___gc__done(long); +extern int __dtraceenabled_python___gc__done(void); +extern void __dtrace_python___gc__start(int); +extern int __dtraceenabled_python___gc__start(void); +extern void __dtrace_python___instance__delete__done(char *, char *); +extern int __dtraceenabled_python___instance__delete__done(void); +extern void __dtrace_python___instance__delete__start(char *, char *); +extern int __dtraceenabled_python___instance__delete__start(void); +extern void __dtrace_python___instance__new__done(char *, char *); +extern int __dtraceenabled_python___instance__new__done(void); +extern void __dtrace_python___instance__new__start(char *, char *); +extern int __dtraceenabled_python___instance__new__start(void); +extern void __dtrace_python___line(char *, char *, int); +extern int __dtraceenabled_python___line(void); + +#else + +#define PYTHON_FUNCTION_ENTRY(arg0, arg1, arg2) +#define PYTHON_FUNCTION_ENTRY_ENABLED() (0) +#define PYTHON_FUNCTION_RETURN(arg0, arg1, arg2) +#define PYTHON_FUNCTION_RETURN_ENABLED() (0) +#define PYTHON_GC_DONE(arg0) +#define PYTHON_GC_DONE_ENABLED() (0) +#define PYTHON_GC_START(arg0) +#define PYTHON_GC_START_ENABLED() (0) +#define PYTHON_INSTANCE_DELETE_DONE(arg0, arg1) +#define PYTHON_INSTANCE_DELETE_DONE_ENABLED() (0) +#define PYTHON_INSTANCE_DELETE_START(arg0, arg1) +#define PYTHON_INSTANCE_DELETE_START_ENABLED() (0) +#define PYTHON_INSTANCE_NEW_DONE(arg0, arg1) +#define PYTHON_INSTANCE_NEW_DONE_ENABLED() (0) +#define PYTHON_INSTANCE_NEW_START(arg0, arg1) +#define PYTHON_INSTANCE_NEW_START_ENABLED() (0) +#define PYTHON_LINE(arg0, arg1, arg2) +#define PYTHON_LINE_ENABLED() (0) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _PYDTRACE_H */ diff -r 3c3009f63700 -r c64a284f4309 Lib/test/dtrace_sample.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/test/dtrace_sample.py Tue Nov 22 01:45:16 2011 +0100 @@ -0,0 +1,73 @@ +# Sample script for use by test_dtrace.py +# DO NOT MODIFY THIS FILE IN ANY WAY WITHOUT UPDATING test_dtrace.py!!!!! + +import gc + +def function_1() : + pass + +# Check stacktrace +def function_2() : + function_1() + +# CALL_FUNCTION_VAR +def function_3(dummy, dummy2) : + pass + +# CALL_FUNCTION_KW +def function_4(**dummy) : + pass + +# CALL_FUNCTION_VAR_KW +def function_5(dummy, dummy2, **dummy3) : + pass + +def test_entry_return_and_stack() : + function_1() + function_2() + function_3(*(1,2)) + function_4(**{"test":42}) + function_5(*(1,2), **{"test":42}) + +def test_line() : + a = 1 # Preamble + for i in xrange(2) : + a = i + b = i+2 + c = i+3 + d = a + b +c + a = 1 # Epilogue + +def test_instance_creation_destruction() : + class old_style_class() : + pass + class new_style_class(object) : + pass + + a = old_style_class() + del a + gc.collect() + b = new_style_class() + del b + gc.collect() + + a = old_style_class() + del old_style_class + gc.collect() + b = new_style_class() + del new_style_class + gc.collect() + del a + gc.collect() + del b + gc.collect() + +def test_garbage_collection() : + gc.collect() + +if __name__ == "__main__": + test_entry_return_and_stack() + test_line() + test_instance_creation_destruction() + test_garbage_collection() + diff -r 3c3009f63700 -r c64a284f4309 Lib/test/test_dtrace.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/test/test_dtrace.py Tue Nov 22 01:45:16 2011 +0100 @@ -0,0 +1,322 @@ +import sys, unittest, subprocess, os.path, dis, types +from test.test_support import TESTFN, run_unittest, findfile + +sample = os.path.abspath(findfile("dtrace_sample.py")) +v = sys.trace_instrumentation +if (v is None) or (v[0].lower() != "dtrace") : + raise unittest.SkipTest, "dtrace support not compiled in" + +dscript = """ +pid$target::PyEval_EvalCode:entry +""" +dscript = dscript.replace("\r", "").replace("\n", "") +result, _ = subprocess.Popen(["dtrace", "-q", "-l", "-n", dscript, + "-c", "%s %s" %(sys.executable, sample)], stdout=subprocess.PIPE, + stderr=subprocess.STDOUT).communicate() +if result.split("\n")[1].split()[-2:] != ["PyEval_EvalCode", "entry"] : + result2 = repr(result) + raise unittest.SkipTest("dtrace seems not to be working. " + \ + "Please, check your privileges. " + + "Result: " +result2) + +class DTraceTestsNormal(unittest.TestCase) : + def setUp(self) : + self.optimize = False + + def test_function_entry_return(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 1; +} +python$target:::function-entry,python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && (self->trace)/ +{ + printf("**%%s*%%s*%%s*%%d\\n", probename, copyinstr(arg0), + copyinstr(arg1), arg2); +} +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **function-entry*%(path)s*test_entry_return_and_stack*25 + **function-entry*%(path)s*function_1*6 + **function-return*%(path)s*function_1*7 + **function-entry*%(path)s*function_2*10 + **function-entry*%(path)s*function_1*6 + **function-return*%(path)s*function_1*7 + **function-return*%(path)s*function_2*11 + **function-entry*%(path)s*function_3*14 + **function-return*%(path)s*function_3*15 + **function-entry*%(path)s*function_4*18 + **function-return*%(path)s*function_4*19 + **function-entry*%(path)s*function_5*22 + **function-return*%(path)s*function_5*23 + **function-return*%(path)s*test_entry_return_and_stack*30 + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = actual_result.replace("\r", "").replace("\n", + "").replace(" ", "") + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + def test_stack(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 1; +} +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && (self->trace)/ +{ + printf("[x]"); + jstack(); +} +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + [x] + [%(path)s:25(test_entry_return_and_stack)] + [x] + [%(path)s:6(function_1)] + [%(path)s:26(test_entry_return_and_stack)] + [x] + [%(path)s:10(function_2)] + [%(path)s:27(test_entry_return_and_stack)] + [x] + [%(path)s:6(function_1)] + [%(path)s:11(function_2)] + [%(path)s:27(test_entry_return_and_stack)] + [x] + [%(path)s:14(function_3)] + [%(path)s:28(test_entry_return_and_stack)] + [x] + [%(path)s:18(function_4)] + [%(path)s:29(test_entry_return_and_stack)] + [x] + [%(path)s:22(function_5)] + [%(path)s:30(test_entry_return_and_stack)] + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = [i for i in actual_result.split("\n") if (("[" in i) + and not i.endswith(" () ]"))] + actual_result = "".join(actual_result) + actual_result = actual_result.replace("\r", "").replace("\n", + "").replace(" ", "") + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + def test_garbage_collection(self) : + dscript = """ +python$target:::gc-start,python$target:::gc-done +{ + printf("**%s(%ld)\\n", probename, arg0); +} +""" + + dscript = dscript.replace("\r", "").replace("\n", "") + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = "".join(actual_result) + actual_result = actual_result.replace("\r", "").replace("\n", + "").replace(" ", "") + for i in xrange(10) : + actual_result = actual_result.replace(str(i), "") + expected_result = "**gc-start()**gc-done()" * \ + actual_result.count("**gc-start()**") + + self.assertEqual(actual_result, expected_result) + + def test_verify_opcodes(self) : + # Verify that we are checking: + opcodes = set(["CALL_FUNCTION", "CALL_FUNCTION_VAR", + "CALL_FUNCTION_KW", "CALL_FUNCTION_VAR_KW"]) + obj = compile(open(sample).read(), "sample", "exec") + class dump() : + def __init__(self) : + self.buf = [] + def write(self, v) : + self.buf.append(v) + + dump = dump() + stdout = sys.stdout + sys.stdout = dump + for i in obj.co_consts : + if isinstance(i, types.CodeType) and \ + (i.co_name == 'test_entry_return_and_stack') : + dis.dis(i) + sys.stdout = stdout + dump = "\n".join(dump.buf) + dump = dump.replace("\r", "").replace("\n", "").split() + for i in dump : + opcodes.discard(i) + # Are we verifying all the relevant opcodes? + self.assertEqual(set(), opcodes) # Are we verifying all opcodes? + + def test_line(self) : + dscript = """ +python$target:::line +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_line")/ +{ + printf("**%%s*%%s*%%s*%%d\\n", probename, copyinstr(arg0), + copyinstr(arg1), arg2); +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **line*%(path)s*test_line*33 + **line*%(path)s*test_line*34 + **line*%(path)s*test_line*35 + **line*%(path)s*test_line*36 + **line*%(path)s*test_line*37 + **line*%(path)s*test_line*38 + **line*%(path)s*test_line*34 + **line*%(path)s*test_line*35 + **line*%(path)s*test_line*36 + **line*%(path)s*test_line*37 + **line*%(path)s*test_line*38 + **line*%(path)s*test_line*34 + **line*%(path)s*test_line*38 + **line*%(path)s*test_line*39 + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = actual_result.replace("\r", "").replace("\n", + "").replace(" ", "") + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + def test_instance_creation_destruction(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_instance_creation_destruction")/ +{ + self->trace = 1; +} + +python$target:::instance-new-start, +python$target:::instance-new-done, +python$target:::instance-delete-start, +python$target:::instance-delete-done +/self->trace/ +{ + printf("**%%s* (%%s.%%s)\\n", probename, copyinstr(arg1), copyinstr(arg0)); +} + +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_instance_creation_destruction")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **instance-new-start*(.type) + **instance-new-done*(.type) + **instance-new-start*(.getset_descriptor) + **instance-new-done*(.getset_descriptor) + **instance-new-start*(.getset_descriptor) + **instance-new-done*(.getset_descriptor) + **instance-new-start*(__main__.old_style_class) + **instance-new-done*(__main__.old_style_class) + **instance-delete-start*(__main__.old_style_class) + **instance-delete-done*(__main__.old_style_class) + **instance-new-start*(__main__.new_style_class) + **instance-new-done*(__main__.new_style_class) + **instance-new-start*(__main__.old_style_class) + **instance-new-done*(__main__.old_style_class) + **instance-new-start*(__main__.new_style_class) + **instance-new-done*(__main__.new_style_class) + **instance-delete-start*(__main__.old_style_class) + **instance-delete-done*(__main__.old_style_class) + """ + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = actual_result.replace("\r", "").replace("\n", + "").replace(" ", "") + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + + +# This class try to verify that dtrace probes +# are still working with optimizations enabled in the bytecode. +# +# Some tests will not actually verify it. For instance, +# source code compilation follows optimization status of +# current working Python. So, you should run the test +# both with an optimizing and a non optimizing Python. +class DTraceTestsOptimize(DTraceTestsNormal) : + def setUp(self) : + self.optimize = True + + +def test_main(): + run_unittest(DTraceTestsNormal) + run_unittest(DTraceTestsOptimize) + +if __name__ == '__main__': + test_main() + diff -r 3c3009f63700 -r c64a284f4309 Makefile.pre.in --- a/Makefile.pre.in Mon Nov 14 18:04:05 2011 +0200 +++ b/Makefile.pre.in Tue Nov 22 01:45:16 2011 +0100 @@ -47,6 +47,10 @@ # Use this to make a link between python$(VERSION) and python in $(BINDIR) LN= @LN@ +DTRACE= @DTRACE@ +DFLAGS= @DFLAGS@ + + # Portable install script (configure doesn't always guess right) INSTALL= @INSTALL@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ @@ -301,6 +305,7 @@ Python/formatter_unicode.o \ Python/formatter_string.o \ Python/$(DYNLOADFILE) \ + @DTRACEOBJS@ \ $(LIBOBJS) \ $(MACHDEP_OBJS) \ $(THREADOBJ) @@ -604,6 +609,43 @@ Python/formatter_string.o: $(srcdir)/Python/formatter_string.c \ $(STRINGLIB_HEADERS) +# Only generated on Solaris +Python/phelper.o: $(srcdir)/Include/phelper.d + if test "$(DTRACE)" != "" ; then \ + $(DTRACE) -o $@ -DPHELPER $(DFLAGS) \ + $(CPPFLAGS) -C -G -s $(srcdir)/Include/phelper.d ; \ + else touch $@ ; \ + fi; + +Include/pydtrace.h: $(srcdir)/Include/pydtrace.d + if test "$(DTRACE)" != "" ; then \ + $(DTRACE) -o $@ $(DFLAGS) \ + -C -h -s $(srcdir)/Include/pydtrace.d ; \ + else touch $@ ; \ + fi; + +Include/phelper.h: $(srcdir)/Include/phelper.d + if test "$(DTRACE)" != "" ; then \ + $(DTRACE) -o $@ $(DFLAGS) \ + -C -h -s $(srcdir)/Python/python.d ; \ + else touch $@ ; \ + fi; + +Python/ceval.o: Include/pydtrace.h +Modules/gcmodule.o: Include/pydtrace.h +Objects/classobject.o: Include/pydtrace.h +Objects/typeobject.o: Include/pydtrace.h + +Python/dtrace.o: $(srcdir)/Include/pydtrace.d Python/ceval.o Modules/gcmodule.o \ + Objects/classobject.o Objects/typeobject.o + if test "$(DTRACE)" != "" ; then \ + $(DTRACE) -o $@ $(DFLAGS) \ + -C -G -s $(srcdir)/Include/pydtrace.d \ + Python/ceval.o Modules/gcmodule.o \ + Objects/classobject.o Objects/typeobject.o; \ + else touch $@ ; \ + fi; + ############################################################################ # Header files @@ -1186,6 +1228,7 @@ find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' find build -name 'fficonfig.h' -exec rm -f {} ';' || true find build -name 'fficonfig.py' -exec rm -f {} ';' || true + rm -f Include/pydtrace.h Include/phelper.h -rm -f Lib/lib2to3/*Grammar*.pickle profile-removal: @@ -1214,6 +1257,7 @@ -o -name '*.orig' -o -name '*.rej' \ -o -name '*.bak' ')' \ -exec rm -f {} ';' + rm -f Include/pydtrace.h Include/phelper.h # Check for smelly exported symbols (not starting with Py/_Py) smelly: all diff -r 3c3009f63700 -r c64a284f4309 Modules/gcmodule.c --- a/Modules/gcmodule.c Mon Nov 14 18:04:05 2011 +0200 +++ b/Modules/gcmodule.c Tue Nov 22 01:45:16 2011 +0100 @@ -21,6 +21,10 @@ #include "Python.h" #include "frameobject.h" /* for PyFrame_ClearFreeList */ +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + /* Get an object's GC head */ #define AS_GC(o) ((PyGC_Head *)(o)-1) @@ -818,7 +822,12 @@ /* This is the main function. Read this to understand how the * collection process works. */ static Py_ssize_t -collect(int generation) +#ifdef WITH_DTRACE +collect2 +#else +collect +#endif +(int generation) { int i; Py_ssize_t m = 0; /* # objects collected */ @@ -975,6 +984,49 @@ return n+m; } +#ifdef WITH_DTRACE +static void +dtrace_gc_start(int collection) +{ + PYTHON_GC_START(collection); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} + +static void +dtrace_gc_done(Py_ssize_t value) +{ + PYTHON_GC_DONE((long) value); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} + +static Py_ssize_t +collect(int collection) +{ +Py_ssize_t value; + + if (PYTHON_GC_START_ENABLED()) + dtrace_gc_start(collection); + value = collect2(collection); + if (PYTHON_GC_DONE_ENABLED()) + dtrace_gc_done(value); + return value; +} +#endif /* WITH_DTRACE */ + static Py_ssize_t collect_generations(void) { diff -r 3c3009f63700 -r c64a284f4309 Objects/classobject.c --- a/Objects/classobject.c Mon Nov 14 18:04:05 2011 +0200 +++ b/Objects/classobject.c Tue Nov 22 01:45:16 2011 +0100 @@ -4,6 +4,10 @@ #include "Python.h" #include "structmember.h" +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + /* Free list for method objects to safe malloc/free overhead * The im_self element is used to chain the elements. */ @@ -543,6 +547,26 @@ PyObject *init; static PyObject *initstr; +#ifdef WITH_DTRACE + PyObject *mod; + char *mod_name; + + if (PYTHON_INSTANCE_NEW_START_ENABLED()) { + mod = PyDict_GetItemString(((PyClassObject *)klass)->cl_dict, + "__module__"); + + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + } + + PYTHON_INSTANCE_NEW_START( + PyString_AS_STRING(((PyClassObject *)klass)->cl_name), + mod_name); + } +#endif + if (initstr == NULL) { initstr = PyString_InternFromString("__init__"); if (initstr == NULL) @@ -584,6 +608,23 @@ Py_DECREF(res); } } + +#ifdef WITH_DTRACE + if (PYTHON_INSTANCE_NEW_DONE_ENABLED()) { + mod = PyDict_GetItemString(((PyClassObject *)klass)->cl_dict, + "__module__"); + + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + } + + PYTHON_INSTANCE_NEW_DONE( + PyString_AS_STRING(((PyClassObject *)klass)->cl_name), + mod_name); + } +#endif return (PyObject *)inst; } @@ -624,6 +665,31 @@ PyObject *del; static PyObject *delstr; +#ifdef WITH_DTRACE + PyObject *mod; + char *mod_name = NULL; /* Not neccesary, but save a compiler warning */ + char *cl_name = NULL; + + if (PYTHON_INSTANCE_DELETE_START_ENABLED() || + PYTHON_INSTANCE_DELETE_DONE_ENABLED()) { + /* + ** We need to save info we need, because deleting the + ** instance would delete the class too. + */ + mod = PyDict_GetItemString(inst->in_class->cl_dict, "__module__"); + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + } + cl_name = PyString_AS_STRING(inst->in_class->cl_name); + } + + if (PYTHON_INSTANCE_DELETE_START_ENABLED()) { + PYTHON_INSTANCE_DELETE_START(cl_name, mod_name); + } +#endif + _PyObject_GC_UNTRACK(inst); if (inst->in_weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) inst); @@ -693,6 +759,16 @@ --inst->ob_type->tp_allocs; #endif } + +#ifdef WITH_DTRACE + /* + ** "cl_name" can be NULL if the probe is activated between the probe + ** test at the beginning of the routine and now. + */ + if (PYTHON_INSTANCE_DELETE_DONE_ENABLED() && cl_name) { + PYTHON_INSTANCE_DELETE_DONE(cl_name, mod_name); + } +#endif } static PyObject * diff -r 3c3009f63700 -r c64a284f4309 Objects/frameobject.c --- a/Objects/frameobject.c Mon Nov 14 18:04:05 2011 +0200 +++ b/Objects/frameobject.c Tue Nov 22 01:45:16 2011 +0100 @@ -736,6 +736,9 @@ f->f_tstate = tstate; f->f_lasti = -1; +#ifdef WITH_DTRACE + f->f_calllineno = code->co_firstlineno; +#endif f->f_lineno = code->co_firstlineno; f->f_iblock = 0; diff -r 3c3009f63700 -r c64a284f4309 Objects/typeobject.c --- a/Objects/typeobject.c Mon Nov 14 18:04:05 2011 +0200 +++ b/Objects/typeobject.c Tue Nov 22 01:45:16 2011 +0100 @@ -3,6 +3,10 @@ #include "Python.h" #include "structmember.h" +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + #include @@ -746,8 +750,29 @@ PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems) { PyObject *obj; - const size_t size = _PyObject_VAR_SIZE(type, nitems+1); + size_t size; + +#ifdef WITH_DTRACE + PyObject *mod; + char *mod_name; + + if (PYTHON_INSTANCE_NEW_START_ENABLED()) { + if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + } + } else { + mod_name = ""; + } + PYTHON_INSTANCE_NEW_START((char *)(type->tp_name), mod_name); + } +#endif + /* note that we need to add one, for the sentinel */ + size = _PyObject_VAR_SIZE(type, nitems+1); if (PyType_IS_GC(type)) obj = _PyObject_GC_Malloc(size); @@ -769,6 +794,23 @@ if (PyType_IS_GC(type)) _PyObject_GC_TRACK(obj); + +#ifdef WITH_DTRACE + if (PYTHON_INSTANCE_NEW_DONE_ENABLED()) { + if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + } + } else { + mod_name = ""; + } + PYTHON_INSTANCE_NEW_DONE((char *)(type->tp_name), mod_name); + } +#endif + return obj; } diff -r 3c3009f63700 -r c64a284f4309 Python/ceval.c --- a/Python/ceval.c Mon Nov 14 18:04:05 2011 +0200 +++ b/Python/ceval.c Tue Nov 22 01:45:16 2011 +0100 @@ -19,6 +19,10 @@ #include +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + #ifndef WITH_TSC #define READ_TIMESTAMP(var) @@ -477,6 +481,7 @@ j = pendingfirst; if (j == pendinglast) { func = NULL; /* Queue empty */ + arg = NULL; } else { func = pendingcalls[j].func; arg = pendingcalls[j].arg; @@ -672,6 +677,69 @@ NULL); } +#ifdef WITH_DTRACE +static void +dtrace_line(const char *filename, const char *fname, int lineno) +{ + PYTHON_LINE((char *)filename, (char *)fname, lineno); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} + +static void +dtrace_entry(PyFrameObject *f) +{ + const char *filename; + const char *fname; + int lineno; + + filename = PyString_AsString(f->f_code->co_filename); + fname = PyString_AsString(f->f_code->co_name); + lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + + PYTHON_FUNCTION_ENTRY((char *)filename, (char *)fname, lineno); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} + +static void +dtrace_return(PyFrameObject *f) +{ + const char *filename; + const char *fname; + int lineno; + + filename = PyString_AsString(f->f_code->co_filename); + fname = PyString_AsString(f->f_code->co_name); + lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + PYTHON_FUNCTION_RETURN((char *)filename, (char *)fname, lineno); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} +#else +#define PYTHON_FUNCTION_ENTRY_ENABLED() 0 +#define PYTHON_FUNCTION_RETURN_ENABLED() 0 +#define dtrace_entry(f) +#define dtrace_return(f) +#endif /* Interpreter main loop */ @@ -683,9 +751,84 @@ return PyEval_EvalFrameEx(f, 0); } +/* + * These shenanigans look like utter madness, but what we're actually doing is + * making sure that the ustack helper will see the PyFrameObject pointer on the + * stack. We have two tricky cases: + * + * amd64 + * + * We use up the six registers for passing arguments, meaning the call can't + * use a register for passing 'f', and has to push it onto the stack in a known + * location. + * + * And how does "throwflag" figure in to this? -PN + * + * SPARC + * + * Here the problem is that (on 32-bit) the compiler is re-using %i0 before + * some calls inside PyEval_EvalFrameReal(), which means that when it's saved, + * it's just some junk value rather than the real first argument. So, instead, + * we trace our proxy PyEval_EvalFrame(), where we 'know' the compiler won't + * decide to re-use %i0. We also need to defeat optimization of our proxy. + */ + +#if defined(WITH_DTRACE) + +#if defined(__amd64) +PyObject *PyEval_EvalFrameExReal(long, long, long, long, long, long, + PyFrameObject *, int throwflag); + + + PyObject * PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) { + volatile PyObject *f2; + f2 = PyEval_EvalFrameExReal(0, 0, 0, 0, 0, 0, f, throwflag); + return (PyObject *)f2; +} + +PyObject * +PyEval_EvalFrameExReal(long a1, long a2, long a3, long a4, long a5, long a6, + PyFrameObject *f, int throwflag) +{ + +#elif defined(__sparc) + +PyObject *PyEval_EvalFrameExReal(PyFrameObject *f, int throwflag); + +volatile int dummy; + +PyObject * +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) +{ + volatile PyObject *f2; + f2 = PyEval_EvalFrameExReal(f, throwflag); + dummy = f->ob_refcnt; + return (PyObject *)f2; +} + +PyObject * +PyEval_EvalFrameExReal(PyFrameObject *f, int throwflag) +{ + +#else /* __amd64 || __sparc */ + +PyObject * +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) +{ + +#endif /* __amd64 || __sparc */ + +#else /* WITH_DTRACE not defined */ + +PyObject * +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) +{ + +#endif /* WITH_DTRACE */ + #ifdef DXPAIRS int lastopcode = 0; #endif @@ -722,6 +865,11 @@ /* Make it easier to find out where we are with a debugger */ char *filename; #endif +#ifdef WITH_DTRACE + PyCodeObject *previous_codefile = NULL; + int previous_line = -1; + int current_line; +#endif /* Tuple access macros */ @@ -910,6 +1058,9 @@ } } + if (PYTHON_FUNCTION_ENTRY_ENABLED()) + dtrace_entry(f); + co = f->f_code; names = co->co_names; consts = co->co_consts; @@ -1096,6 +1247,17 @@ /* Main switch on opcode */ READ_TIMESTAMP(inst0); + if (PYTHON_LINE_ENABLED()) { + current_line = PyCode_Addr2Line(f->f_code, f->f_lasti); + if ((previous_line != current_line) || (previous_codefile != co)) { + previous_codefile = co; + previous_line = current_line; + dtrace_line(PyString_AsString(co->co_filename), + PyString_AsString(f->f_code->co_name), + current_line); + } + } + switch (opcode) { /* BEWARE! @@ -2660,6 +2822,9 @@ PyObject **sp; PCALL(PCALL_ALL); sp = stack_pointer; +#ifdef WITH_DTRACE + f->f_calllineno = PyCode_Addr2Line(f->f_code, f->f_lasti); +#endif #ifdef WITH_TSC x = call_function(&sp, oparg, &intr0, &intr1); #else @@ -2701,6 +2866,10 @@ } else Py_INCREF(func); sp = stack_pointer; +#ifdef WITH_DTRACE + f->f_calllineno = PyCode_Addr2Line(f->f_code, f->f_lasti); +#endif + READ_TIMESTAMP(intr0); x = ext_do_call(func, &sp, flags, na, nk); READ_TIMESTAMP(intr1); @@ -3001,6 +3170,8 @@ /* pop frame */ exit_eval_frame: + if (PYTHON_FUNCTION_RETURN_ENABLED()) + dtrace_return(f); Py_LeaveRecursiveCall(); tstate->frame = f->f_back; diff -r 3c3009f63700 -r c64a284f4309 Python/sysmodule.c --- a/Python/sysmodule.c Mon Nov 14 18:04:05 2011 +0200 +++ b/Python/sysmodule.c Tue Nov 22 01:45:16 2011 +0100 @@ -1097,6 +1097,7 @@ prefix -- prefix used to find the Python library\n\ exec_prefix -- prefix used to find the machine-specific Python library\n\ float_repr_style -- string indicating the style of repr() output for floats\n\ +trace_instrumentation -- None or tuple\n\ " ) #ifdef MS_WINDOWS @@ -1398,6 +1399,14 @@ Py_XDECREF(sysout); Py_XDECREF(syserr); + SET_SYS_FROM_STRING("trace_instrumentation", +#ifdef WITH_DTRACE + Py_BuildValue("(ss)", "dtrace", "Sun") +#else + Py_BuildValue("") /* Returns None */ +#endif + ); + SET_SYS_FROM_STRING("version", PyString_FromString(Py_GetVersion())); SET_SYS_FROM_STRING("hexversion", diff -r 3c3009f63700 -r c64a284f4309 configure --- a/configure Mon Nov 14 18:04:05 2011 +0200 +++ b/configure Tue Nov 22 01:45:16 2011 +0100 @@ -611,6 +611,10 @@ MACHDEP_OBJS DYNLOADFILE DLINCLDIR +DTRACEHDRS +DTRACEOBJS +DFLAGS +DTRACE THREADOBJ LDLAST USE_THREAD_MODULE @@ -754,6 +758,7 @@ with_tsc with_pymalloc with_valgrind +with_dtrace with_wctype_functions with_fpectl with_libm @@ -1429,6 +1434,7 @@ --with(out)-tsc enable/disable timestamp counter profile --with(out)-pymalloc disable/enable specialized mallocs --with-valgrind Enable Valgrind support + --with(out)-dtrace disable/enable dtrace support --with-wctype-functions use wctype.h functions --with-fpectl enable SIGFPE catching --with-libm=STRING math library @@ -2600,7 +2606,7 @@ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi done @@ -3532,7 +3538,7 @@ test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -3647,7 +3653,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -3690,7 +3696,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 @@ -3749,7 +3755,7 @@ $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi fi fi @@ -3801,7 +3807,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi @@ -4344,7 +4350,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c @@ -6696,7 +6702,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (int) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_int=0 fi @@ -6729,7 +6735,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_long=0 fi @@ -6762,7 +6768,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (void *) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_void_p=0 fi @@ -6795,7 +6801,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (short) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_short=0 fi @@ -6828,7 +6834,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (float) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_float=0 fi @@ -6861,7 +6867,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (double) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_double=0 fi @@ -6894,7 +6900,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (fpos_t) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_fpos_t=0 fi @@ -6927,7 +6933,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (size_t) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_size_t=0 fi @@ -6960,7 +6966,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (pid_t) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_pid_t=0 fi @@ -7020,7 +7026,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long long) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_long_long=0 fi @@ -7081,7 +7087,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long double) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_long_double=0 fi @@ -7142,7 +7148,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (_Bool) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof__Bool=0 fi @@ -7190,7 +7196,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (uintptr_t) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_uintptr_t=0 fi @@ -7231,7 +7237,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (off_t) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_off_t=0 fi @@ -7293,7 +7299,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (time_t) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_time_t=0 fi @@ -7364,7 +7370,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (pthread_t) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_pthread_t=0 fi @@ -9447,6 +9453,93 @@ fi +# Check for dtrace support +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-dtrace" >&5 +$as_echo_n "checking for --with-dtrace... " >&6; } + +# Check whether --with-dtrace was given. +if test "${with_dtrace+set}" = set; then : + withval=$with_dtrace; +fi + + + + +DTRACE= +DFLAGS= +if test ! -z "$with_dtrace" +then + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if test "${ac_cv_sizeof_long+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + + if test "$ac_cv_sizeof_long" -eq 8 + then + DFLAGS="-64" + else + DFLAGS="-32" + fi + + #if dtrace -G -o /dev/null Include/pydtrace.d 2>/dev/null + if true + then + +$as_echo "#define WITH_DTRACE 1" >>confdefs.h + + with_dtrace="Sun" + DTRACEOBJS="Python/phelper.o Python/dtrace.o" + DTRADEHDRS="" + DTRACE=dtrace + elif dtrace -h -o /dev/null -s Include/pydtrace.d + then + +$as_echo "#define WITH_DTRACE 1" >>confdefs.h + + with_dtrace="Apple" + DTRACEOBJS="" + DTRADEHDRS="phelper.h pydtrace.h" + DTRACE=dtrace + else + with_dtrace="no" + fi +else + with_dtrace="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_dtrace" >&5 +$as_echo "$with_dtrace" >&6; } + + + # Check for --with-wctype-functions { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-wctype-functions" >&5 $as_echo_n "checking for --with-wctype-functions... " >&6; } @@ -12314,7 +12407,7 @@ 15|30) ;; *) - as_fn_error $? "bad value $enable_big_digits for --enable-big-digits; value should be 15 or 30" "$LINENO" 5 ;; + as_fn_error $? "bad value $enable_big_digits for --enable-big-digits; value should be 15 or 30" "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_big_digits" >&5 $as_echo "$enable_big_digits" >&6; } @@ -12366,7 +12459,7 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (wchar_t) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_wchar_t=0 fi @@ -12485,7 +12578,7 @@ $as_echo "#define Py_UNICODE_SIZE 4" >>confdefs.h ;; -*) as_fn_error $? "invalid value for --enable-unicode. Use either ucs2 or ucs4 (lowercase)." "$LINENO" 5 ;; +*) as_fn_error $? "invalid value for --enable-unicode. Use either ucs2 or ucs4 (lowercase)." "$LINENO" 5 ;; esac @@ -12751,7 +12844,7 @@ ;; #( *) as_fn_error $? "unknown endianness - presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac @@ -14551,7 +14644,7 @@ "Misc/python.pc") CONFIG_FILES="$CONFIG_FILES Misc/python.pc" ;; "Modules/ld_so_aix") CONFIG_FILES="$CONFIG_FILES Modules/ld_so_aix" ;; - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -14866,7 +14959,7 @@ esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -14894,7 +14987,7 @@ [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -14921,7 +15014,7 @@ case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac diff -r 3c3009f63700 -r c64a284f4309 configure.in --- a/configure.in Mon Nov 14 18:04:05 2011 +0200 +++ b/configure.in Tue Nov 22 01:45:16 2011 +0100 @@ -2648,6 +2648,53 @@ ) fi +# Check for dtrace support +AC_MSG_CHECKING(for --with-dtrace) +AC_ARG_WITH(dtrace, + AC_HELP_STRING(--with(out)-dtrace, disable/enable dtrace support)) + +AC_SUBST(DTRACE) +AC_SUBST(DFLAGS) +DTRACE= +DFLAGS= +if test ! -z "$with_dtrace" +then + AC_CHECK_SIZEOF([long]) + if [test "$ac_cv_sizeof_long" -eq 8] + then + DFLAGS="-64" + else + DFLAGS="-32" + fi + + #if dtrace -G -o /dev/null Include/pydtrace.d 2>/dev/null + if true + then + AC_DEFINE(WITH_DTRACE, 1, + [Define if you want to compile in Dtrace support]) + with_dtrace="Sun" + DTRACEOBJS="Python/phelper.o Python/dtrace.o" + DTRADEHDRS="" + DTRACE=dtrace + elif dtrace -h -o /dev/null -s Include/pydtrace.d + then + AC_DEFINE(WITH_DTRACE, 1, + [Define if you want to compile in Dtrace support]) + with_dtrace="Apple" + DTRACEOBJS="" + DTRADEHDRS="phelper.h pydtrace.h" + DTRACE=dtrace + else + with_dtrace="no" + fi +else + with_dtrace="no" +fi + +AC_MSG_RESULT($with_dtrace) +AC_SUBST(DTRACEOBJS) +AC_SUBST(DTRACEHDRS) + # Check for --with-wctype-functions AC_MSG_CHECKING(for --with-wctype-functions) AC_ARG_WITH(wctype-functions, diff -r 3c3009f63700 -r c64a284f4309 pyconfig.h.in --- a/pyconfig.h.in Mon Nov 14 18:04:05 2011 +0200 +++ b/pyconfig.h.in Tue Nov 22 01:45:16 2011 +0100 @@ -1080,6 +1080,9 @@ /* Define if you want documentation strings in extension modules */ #undef WITH_DOC_STRINGS +/* Define to compile in Dtrace support */ +#undef WITH_DTRACE + /* Define if you want to use the new-style (Openstep, Rhapsody, MacOS) dynamic linker (dyld) instead of the old-style (NextStep) dynamic linker (rld). Dyld is necessary to support frameworks. */