diff -r bd8afb90ebf2 -r 775eeaf1a707 .hgignore --- a/.hgignore Sat Sep 29 09:44:17 2012 +0200 +++ b/.hgignore Tue Oct 02 02:21:51 2012 +0200 @@ -88,3 +88,6 @@ .coverage coverage/ htmlcov/ +Include/pydtrace.h +Include/pydtrace_offsets +Include/pydtrace_offsets.h diff -r bd8afb90ebf2 -r 775eeaf1a707 Doc/library/debug.rst --- a/Doc/library/debug.rst Sat Sep 29 09:44:17 2012 +0200 +++ b/Doc/library/debug.rst Tue Oct 02 02:21:51 2012 +0200 @@ -15,3 +15,4 @@ profile.rst timeit.rst trace.rst + dtrace.rst diff -r bd8afb90ebf2 -r 775eeaf1a707 Doc/library/dtrace.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doc/library/dtrace.rst Tue Oct 02 02:21:51 2012 +0200 @@ -0,0 +1,183 @@ +:mod:`dtrace` --- DTrace probes for Python +=============================================== + +.. module:: dtrace + :synopsis: DTrace probes for Python. + +**Source code:** :source:`Lib/dtrace.py` + +-------------- + +The :mod:`dtrace` module indicates if the CPython executable currently +running has been compiled with DTrace probes support. + +.. impl-detail:: + + DTrace probes are implementation details of the CPython interpreter! + No garantees are made about probe compatibility between versions of + CPython. DTrace scripts can stop working or work incorrectly without + warning when changing CPython versions. + +The :mod:`dtrace` module defines the following variable: + + +.. data:: available + + The variable will be ``True`` if the current CPython interpreter was + compiled with DTrace probe support. ``False`` if not. + + +DTrace probes +------------- + +DTrace scripts are run externally to CPython. DTrace probes export +selected events inside CPython interpreter in order to make them +accessible to external scripts. + +The probes are exported through the "python" provider. The available +probes are defined in the file :file:`Include/pydtrace.d`. + +To learn how to use DTrace, read `DTrace User Guide +`_. + +.. opcode:: function-entry (arg0, arg1, arg2) + + Fires when python code enters a new function. *arg0* is sourcecode + file path, *arg1* is the name of the funcion called, and *arg2* is + line number. + + The probe is not fired if Python code calls C functions. + +.. opcode:: function-return (arg0, arg1, arg2) + + Fires when Python code finishes execution of a function. Parameters + are the same as in ``function-entry``. + + The probe is not fired if the finishing function is written in C. + +.. opcode:: line (arg0, arg1, arg2) + + Fires when Python code changes the execution line. Parameters are the + same as in ``function-entry``. + + The probe is not fired in C functions. + +.. opcode:: gc-start (arg0) + + Fires when the Python interpreter starts a garbage collection cycle. + *arg0* is the generation to scan, like :func:`gc.collect()`. + +.. opcode:: gc-done (arg0) + + Fires when the Python interpreter finishes a garbage collection + cycle. *arg0* is the number of collected objects. + +.. opcode:: instance-new-start (arg0, arg1) + + Fires when an object instanciation starts. *arg0* is the class name, + *arg1* is the filename where the class is defined. + + The probe is not fired for most C code object creations. + +.. opcode:: instance-new-done (arg0, arg1) + + Fires when an object instanciation finishes. Parameters are the same + as in ``instance-new-done``. + + The probe is not fired for most C code object creations. + +.. opcode:: instance-delete-start (arg0, arg1) + + Fires when an object instance is going to be destroyed. Parameters + are the same as in ``instance-new-done``. + + The probe is not fired for most C code object destructions. + +.. opcode:: instance-delete-done (arg0, arg1) + + Fires when an object instance has been destroyed. parameters are the + same as in ``instance-new-done``. + + Between an ``instance-delete-start`` and corresponding + ``instance-delete-done`` others probes can fire if, for instance, + deletion of an instance creates a deletion cascade. + + The probe is not fired for most C code object destructions. + + +Python stack +------------ + +When a DTrace probe is fired, the DTrace script can examine the stack. +Since CPython is a Python interpreter coded in C, the stack will show C +functions, with no direct relation to the Python code currently being +executed. + +Using the special "jstack()" DTrace function, the user will be given +hints about the python program stack, if possible. In particular, the +augmented stack will show python function calls, filename, name +of the function or method, and the line number. + +DTrace scripts examples +----------------------- + +DTrace python provider is suffixed by the pid of the process to monitor. +In the examples, the pid will be 9876. + +Show the time spent doing garbage collection (in nanoseconds):: + + python9876:::gc-start + { + self->t = timestamp; + } + + python9876:::gc-done + /self->t/ + { + printf("%d", timestamp-self->t); + self->t = 0; + } + +Count how many instances are created of each class:: + + python9876:::instance-new-start + { + @v[copyinstr(arg1), copyinstr(arg0)] = count(); + } + +Observe time spent in object destruction, useful if datastructures are +complicated and deletion of an object can create a cascade effect:: + + python9876:::instance-delete-start + /self->t==0/ + { + self->t = timestamp; + self->level = 0; + } + + python9876:::instance-delete-start + /self->t/ + { + self->level += 1; + } + + python9876:::instance-delete-done + /(self->level) && (self->t)/ + { + self->level -= 1; + } + + python9876:::instance-delete-done + /(self->level==0) && (self->t)/ + { + @time = quantize(timestamp-self->t); + self->t = 0; + } + +To know which python source code lines create new TCP/IP connections:: + + pid9876::sock_connect:entry + { + @conn[jstack()] = count(); + } + diff -r bd8afb90ebf2 -r 775eeaf1a707 Doc/library/json.rst --- a/Doc/library/json.rst Sat Sep 29 09:44:17 2012 +0200 +++ b/Doc/library/json.rst Tue Oct 02 02:21:51 2012 +0200 @@ -146,7 +146,7 @@ object members will be pretty-printed with that indent level. An indent level of 0, negative, or ``""`` will only insert newlines. ``None`` (the default) selects the most compact representation. Using a positive integer indent - indents that many spaces per level. If *indent* is a string (such at '\t'), + indents that many spaces per level. If *indent* is a string (such as ``"\t"``), that string is used to indent each level. If *separators* is an ``(item_separator, dict_separator)`` tuple, then it diff -r bd8afb90ebf2 -r 775eeaf1a707 Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst Sat Sep 29 09:44:17 2012 +0200 +++ b/Doc/library/subprocess.rst Tue Oct 02 02:21:51 2012 +0200 @@ -669,8 +669,8 @@ .. warning:: - Use :meth:`communicate` rather than :attr:`.stdin.write `, - :attr:`.stdout.read ` or :attr:`.stderr.read ` to avoid + Use :meth:`~Popen.communicate` rather than :attr:`.stdin.write `, + :attr:`.stdout.read ` or :attr:`.stderr.read ` to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process. diff -r bd8afb90ebf2 -r 775eeaf1a707 Doc/library/types.rst --- a/Doc/library/types.rst Sat Sep 29 09:44:17 2012 +0200 +++ b/Doc/library/types.rst Tue Oct 02 02:21:51 2012 +0200 @@ -69,7 +69,7 @@ the types that arise only incidentally during processing such as the ``listiterator`` type. -Typical use is of these names is for :func:`isinstance` or +Typical use of these names is for :func:`isinstance` or :func:`issubclass` checks. Standard names are defined for the following types: diff -r bd8afb90ebf2 -r 775eeaf1a707 Include/code.h --- a/Include/code.h Sat Sep 29 09:44:17 2012 +0200 +++ b/Include/code.h Tue Oct 02 02:21:51 2012 +0200 @@ -7,6 +7,8 @@ extern "C" { #endif +#include "pyconfig.h" + /* Bytecode object */ typedef struct { PyObject_HEAD @@ -28,6 +30,9 @@ int co_firstlineno; /* first source line number */ PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See Objects/lnotab_notes.txt for details. */ +#ifdef WITH_DTRACE + unsigned short *co_linenos; /* dtrace stack helper */ +#endif void *co_zombieframe; /* for optimization only (see frameobject.c) */ PyObject *co_weakreflist; /* to support weakrefs to code objects */ } PyCodeObject; diff -r bd8afb90ebf2 -r 775eeaf1a707 Include/pydtrace.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Include/pydtrace.d Tue Oct 02 02:21:51 2012 +0200 @@ -0,0 +1,177 @@ +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 + + + +#ifdef PYDTRACE_STACK_HELPER +/* + * 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. + * + * Some details about this in "Python and DTrace in build 65": + * http://blogs.oracle.com/levon/entry/python_and_dtrace_in_build + */ + +/* + * 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 "pyatomic.h" +/* "string" type is used in dtrace */ +#define string stringDTRACE +#include "object.h" +#include "pystate.h" +#include "pyarena.h" +#include "pythonrun.h" +#include "compile.h" +#include "frameobject.h" +/* Avoid a compile error because a symbol (equivalent) redefinition */ +#undef __STDC__ +/* "self" has an special meaning for dtrace */ +#define self selfDTRACE +#include "unicodeobject.h" +#undef string +#undef self + +#include "pydtrace_offsets.h" + +#if defined(__i386) +#define startframe PyEval_EvalFrameEx +#define endframe AFTER_PyEval_EvalFrameEx +#elif defined(__amd64) +#define startframe PyEval_EvalFrameExReal +#define endframe AFTER_PyEval_EvalFrameExReal +#elif defined(__sparc) +#define startframe PyEval_EvalFrameExReal +#define endframe AFTER_PyEval_EvalFrameExReal +#endif + +#ifdef __sparcv9 +#define STACK_BIAS (2048-1) +#else +#define STACK_BIAS 0 +#endif + +#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 + +/* startframe and endframe are macro-expansions */ +extern uintptr_t startframe; +extern uintptr_t endframe; + + +#define copyin_obj(addr, obj) ((obj *)copyin((uintptr_t)(addr), sizeof(obj))) + +/* +** Check if the string is ASCII. Don't use bitfields, because the +** packing in GCC and D are different. BEWARE!!!. +** The size of the structures are also different!. That is the reason for +** the negative offset. BEWARE!!! +*/ +#define pystr_len(addr) ((*(((char *)addr)+PYDTRACE_ASCII_OFFSET)) & PYDTRACE_ASCII_MASK ? \ + (addr)->_base.length : \ + *(Py_ssize_t *)(((char *)(addr)) + PYDTRACE_UTF8_LENGTH_OFFSET)) +#define pystr_addr(addr, addr2) ((*(((char *)addr)+PYDTRACE_ASCII_OFFSET)) & PYDTRACE_ASCII_MASK ? \ + (char *)(((char *)(addr2)) + PYDTRACE_PyASCIIObject_SIZE) : \ + (char *)*(uintptr_t *)(((char *)(addr)) + PYDTRACE_UTF8_OFFSET)) + +#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->codeo = copyin_obj(this->codep, PyCodeObject); + /* If we just enter a function, show the definition line */ + this->lineno = this->codeo->co_firstlineno + + (this->frameo->f_lasti == -1 ? 0 : + *copyin_obj(this->codeo->co_linenos + this->frameo->f_lasti, + unsigned short)); + this->filenameo = copyin_obj(this->codeo->co_filename, PyCompactUnicodeObject); + this->len_filename = pystr_len(this->filenameo); + this->nameo = copyin_obj(this->codeo->co_name, PyCompactUnicodeObject); + this->len_name = pystr_len(this->nameo); + this->len = 1 + (this->len_filename) + 1 + 5 + 2 + + (this->len_name) + 1 + 1; + + this->result = (char *)alloca(this->len); + this->pos = 0; + add_char('@'); + + copyinto((uintptr_t)pystr_addr(this->filenameo, this->codeo->co_filename), this->len_filename, this->result+this->pos); + this->pos += this->len_filename; + + 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('('); + + copyinto((uintptr_t)pystr_addr(this->nameo, this->codeo->co_name), this->len_name, this->result+this->pos); + this->pos += this->len_name; + + add_char(')'); + this->result[this->pos] = '\0'; + print_result(stringof(this->result)); +} + +probe /!at_evalframe(arg0)/ +{ + NULL; +} + +#endif /* PYDTRACE_STACK_HELPER */ + diff -r bd8afb90ebf2 -r 775eeaf1a707 Include/pydtrace_offsets.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Include/pydtrace_offsets.c Tue Oct 02 02:21:51 2012 +0200 @@ -0,0 +1,40 @@ +#include "Python.h" +#include "unicodeobject.h" +#include +#include + +int main(int argc, const char* argv[]) { + PyCompactUnicodeObject o; + unsigned char *p = (unsigned char *)(&o); + + if (argc != 3) { + printf("Parameter number incorrect\n"); + exit(1); + } + + memset(&o, 0, sizeof(o)); + o._base.state.ascii = 1; + while (!*p) p++; + + printf("/* File autogenerated. DO NOT MODIFY MANUALLY */\n"); + printf("\n"); + printf("#ifndef PYDTRACE_OFFSETS_H\n"); + printf("#define PYDTRACE_OFFSETS_H\n"); + printf("\n"); + printf("#define PYDTRACE_ASCII_OFFSET %d\n", + p-(unsigned char *)(&o)); + printf("#define PYDTRACE_ASCII_MASK %d\n", *p); + printf("#define PYDTRACE_PyASCIIObject_SIZE %d\n", + sizeof(PyASCIIObject)); + printf("#define PYDTRACE_UTF8_LENGTH_OFFSET %d\n", + offsetof(PyCompactUnicodeObject, utf8_length)); + printf("#define PYDTRACE_UTF8_OFFSET %d\n", + offsetof(PyCompactUnicodeObject, utf8)); + printf("\n"); + printf("#define AFTER_PyEval_EvalFrameEx %s\n", argv[1]); + printf("#define AFTER_PyEval_EvalFrameExReal %s\n", argv[2]); + printf("\n"); + printf("#endif\n"); + return 0; +} + diff -r bd8afb90ebf2 -r 775eeaf1a707 Include/pydtrace_offsets.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Include/pydtrace_offsets.sh Tue Oct 02 02:21:51 2012 +0200 @@ -0,0 +1,30 @@ +#!/bin/sh + +DTRACE_NM=$1 +CEVAL_O=$2 +PYDTRACE_OFFSETS=$3 +if test "$DTRACE_NM" = "OTHER" ; then + $PYDTRACE_OFFSETS \ + "`nm -n $CEVAL_O | grep \" T \" | \ + sed -n \"/ T PyEval_EvalFrameEx$/{n;p;}\" | \ + sed \"s/.* T \(.*\)$/\1/\"`" \ + "`nm -n $CEVAL_O | grep \" T \" | \ + sed -n \"/ T PyEval_EvalFrameExReal$/{n;p;}\" | \ + sed \"s/.* T \(.*\)$/\1/\"`" +fi +if test "$DTRACE_NM" = "SOLARIS" ; then + $PYDTRACE_OFFSETS \ + "`/usr/ccs/bin/nm -n $CEVAL_O | \ + /usr/bin/grep \"\\|FUNC \\|\" | \ + /usr/bin/grep -v \"\\|IGNORE \\|\" | \ + /usr/bin/tr -d \"\\[\\]\\|\" | sort -n | \ + sed -n \"/ PyEval_EvalFrameEx$/{n;p;}\" | \ + sed \"s/.* \([a-zA-Z0-9_]*\)$/\1/\"`" \ + "`/usr/ccs/bin/nm -n $CEVAL_O | \ + /usr/bin/grep \"\\|FUNC \\|\" | \ + /usr/bin/grep -v \"\\|IGNORE \\|\" | \ + /usr/bin/tr -d \"\\[\\]\\|\" | sort -n | \ + sed -n \"/ PyEval_EvalFrameExReal$/{n;p;}\" | \ + sed \"s/.* \([a-zA-Z0-9_]*\)$/\1/\"`" +fi + diff -r bd8afb90ebf2 -r 775eeaf1a707 Lib/test/dtrace_sample.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/test/dtrace_sample.py Tue Oct 02 02:21:51 2012 +0200 @@ -0,0 +1,80 @@ +# 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 range(2) : + a = i + b = i+2 + c = i+3 + d = a + b +c + a = 1 # Epilogue + +def test_unicode_entry_return_and_stack() : + def únícódé() : + pass + únícódé() + +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_unicode_entry_return_and_stack() + test_instance_creation_destruction() + test_garbage_collection() + diff -r bd8afb90ebf2 -r 775eeaf1a707 Lib/test/test_dtrace.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/test/test_dtrace.py Tue Oct 02 02:21:51 2012 +0200 @@ -0,0 +1,447 @@ +import sys, unittest, subprocess, os.path, dis, types, re +import dtrace +from test.support import TESTFN, run_unittest, findfile + +sample = os.path.abspath(findfile("dtrace_sample.py")) +if not dtrace.available : + raise unittest.SkipTest("dtrace support not compiled in") + +def normalize(data) : + # DTRACE keeps a per-CPU buffer, and when showing the fired probes, + # buffers are concatenated. So if the operating system moves our + # thread around, the straight result can be "non causal". + # So we add timestamps to the probe firing, and sort by that field. + + result = data if isinstance(data, str) else data.decode("ascii") + # When compiling with '--with-pydebug' + result = "".join(re.split("\[[0-9]+ refs\]", result)) + + try : + result = [i.split("\t") \ + for i in result.replace("\r", "").split("\n") if len(i)] + result.sort(key = lambda i: int(i[0])) + result = "".join((i[1] for i in result)) + result = result.replace(" ", "") + except : + # If something goes wrong, rebuild the value so we can see the + # real result when the assert fails. + result = data if isinstance(data, str) else data.decode("ascii") + result = result.replace("\r", "").replace("\n", "") + return result + +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.decode("ascii").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("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp, + 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 = normalize(actual_result) + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + @unittest.skipIf(sys.platform == 'darwin', + "MacOS X doesn't support jstack()") + 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 = actual_result.decode("ascii") + # When compiling with '--with-pydebug' + actual_result = "".join(re.split("\[[0-9]+ refs\]", actual_result)) + + 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("%d\t**%s(%ld)\\n", timestamp, 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 = normalize(actual_result) + for i in range(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"]) + with open(sample, encoding="utf-8") as f : + obj = compile(f.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("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp, + 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*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 = normalize(actual_result) + 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("%%d\t**%%s* (%%s.%%s)\\n", timestamp, + 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*(__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-delete-start*(__main__.new_style_class) + **instance-delete-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) + **instance-delete-start*(__main__.new_style_class) + **instance-delete-done*(__main__.new_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 = normalize(actual_result) + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + def test_unicode_function_entry_return(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_unicode_entry_return_and_stack")/ +{ + self->trace = 1; +} +python$target:::function-entry,python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && (self->trace)/ +{ + printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp, + probename, copyinstr(arg0), + copyinstr(arg1), arg2); +} +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_unicode_entry_return_and_stack")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **function-entry*%(path)s*test_unicode_entry_return_and_stack*41 + **function-entry*%(path)s*únícódé*42 + **function-return*%(path)s*únícódé*43 + **function-return*%(path)s*test_unicode_entry_return_and_stack*44 + """ %{"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.decode("utf8") + actual_result = normalize(actual_result) + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + @unittest.skipIf(sys.platform == 'darwin', + "MacOS X doesn't support jstack()") + def test_unicode_stack(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_unicode_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_unicode_entry_return_and_stack")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + [x] + [%(path)s:41(test_unicode_entry_return_and_stack)] + [x] + [%(path)s:42(únícódé)] + [%(path)s:44(test_unicode_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 = actual_result.decode("utf8") + # When compiling with '--with-pydebug' + actual_result = "".join(re.split("\[[0-9]+ refs\]", actual_result)) + + 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) + + + +# 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 bd8afb90ebf2 -r 775eeaf1a707 Lib/test/test_sys.py --- a/Lib/test/test_sys.py Sat Sep 29 09:44:17 2012 +0200 +++ b/Lib/test/test_sys.py Tue Oct 02 02:21:51 2012 +0200 @@ -641,6 +641,7 @@ self.assertEqual(sys.getsizeof(True, -1), size('') + self.longdigit) def test_objecttypes(self): + import dtrace # check all types defined in Objects/ size = test.support.calcobjsize vsize = test.support.calcvobjsize @@ -666,13 +667,17 @@ return inner check(get_cell().__closure__[0], size('P')) # code - check(get_cell().__code__, size('5i9Pi3P')) - check(get_cell.__code__, size('5i9Pi3P')) + if dtrace.available : + code = '5i9PiPH2P' + else : + code = '5i9Pi3P' + check(get_cell().__code__, size(code)) + check(get_cell.__code__, size(code)) def get_cell2(x): def inner(): return x return inner - check(get_cell2.__code__, size('5i9Pi3P') + 1) + check(get_cell2.__code__, size(code) + 1) # complex check(complex(0,1), size('2d')) # method_descriptor (descriptor object) diff -r bd8afb90ebf2 -r 775eeaf1a707 Makefile.pre.in --- a/Makefile.pre.in Sat Sep 29 09:44:17 2012 +0200 +++ b/Makefile.pre.in Tue Oct 02 02:21:51 2012 +0200 @@ -49,6 +49,13 @@ # Use this to make a link between python$(VERSION) and python in $(BINDIR) LN= @LN@ +DTRACE= @DTRACE@ +DFLAGS= @DFLAGS@ +DTRACEOBJS= @DTRACEOBJS@ +DTRACE_NM= @DTRACE_NM@ +DTRACE_LINKER= @DTRACE_LINKER@ + + # Portable install script (configure doesn't always guess right) INSTALL= @INSTALL@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ @@ -464,7 +471,8 @@ # Build the interpreter $(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) - $(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) + $(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/python.o \ + $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) platform: $(BUILDPYTHON) $(SYSCONFIGDATA) $(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print(get_platform()+"-"+sys.version[0:3])' >platform @@ -491,7 +499,7 @@ $(AR) $(ARFLAGS) $@ $(MODOBJS) $(RANLIB) $@ -libpython$(LDVERSION).so: $(LIBRARY_OBJS) +libpython$(LDVERSION).so: $(LIBRARY_OBJS) $(DTRACEOBJS) if test $(INSTSONAME) != $(LDLIBRARY); then \ $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ $(LN) -f $(INSTSONAME) $@; \ @@ -502,9 +510,8 @@ libpython3.so: libpython$(LDVERSION).so $(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^ -libpython$(LDVERSION).dylib: $(LIBRARY_OBJS) - $(CC) -dynamiclib -Wl,-single_module $(PY_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(LDVERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ - +libpython$(LDVERSION).dylib: $(LIBRARY_OBJS) $(DTRACEOBJS) + $(CC) -dynamiclib -Wl,-single_module $(PY_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(LDVERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(DTRACEOBJS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST) libpython$(VERSION).sl: $(LIBRARY_OBJS) $(LDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST) @@ -604,12 +611,18 @@ $(MODULE_OBJS) \ $(SIGNAL_OBJS) \ $(MODOBJS) \ + $(DTRACEOBJS) \ $(srcdir)/Modules/getbuildinfo.c $(CC) -c $(PY_CORE_CFLAGS) \ -DHGVERSION="\"`LC_ALL=C $(HGVERSION)`\"" \ -DHGTAG="\"`LC_ALL=C $(HGTAG)`\"" \ -DHGBRANCH="\"`LC_ALL=C $(HGBRANCH)`\"" \ -o $@ $(srcdir)/Modules/getbuildinfo.c + if test "$(DTRACEOBJS)" != "" ; then \ + $(DTRACE_LINKER) --relocatable \ + $@ $(DTRACEOBJS) -o $@.DTRACE ; \ + mv $@.DTRACE $@ ; \ + fi; Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile $(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ @@ -724,6 +737,35 @@ $(srcdir)/Objects/typeslots.inc: $(srcdir)/Include/typeslots.h $(srcdir)/Objects/typeslots.py $(PYTHON) $(srcdir)/Objects/typeslots.py < $(srcdir)/Include/typeslots.h > $(srcdir)/Objects/typeslots.inc +Include/pydtrace.h: Include/pydtrace.d + if test "$(DTRACE)" != "" ; then \ + $(DTRACE) -o $@ $(DFLAGS) \ + -C -h -s Include/pydtrace.d ; \ + else touch $@ ; \ + fi; + +Include/pydtrace_offsets.h: $(srcdir)/Include/pydtrace_offsets.c $(srcdir)/Python/ceval.o + $(CC) $(PY_CORE_CFLAGS) -o $(srcdir)/Include/pydtrace_offsets \ + $(srcdir)/Include/pydtrace_offsets.c + $(srcdir)/Include/pydtrace_offsets.sh $(DTRACE_NM) \ + $(srcdir)/Python/ceval.o $(srcdir)/Include/pydtrace_offsets > \ + $(srcdir)/Include/pydtrace_offsets.h + +Python/ceval.o: Include/pydtrace.h +Modules/gcmodule.o: Include/pydtrace.h +Objects/typeobject.o: Include/pydtrace.h + +Python/pydtrace.o: $(srcdir)/Include/pydtrace.d $(srcdir)/Include/pydtrace_offsets.h \ + Python/ceval.o Modules/gcmodule.o Objects/typeobject.o + if test "$(DTRACE)" != "" ; then \ + $(DTRACE) -o $@ -DPYDTRACE_STACK_HELPER \ + $(DFLAGS) $(PY_CPPFLAGS) \ + -C -G -s $(srcdir)/Include/pydtrace.d \ + Python/ceval.o Modules/gcmodule.o \ + Objects/typeobject.o; \ + else touch $@ ; \ + fi; + ############################################################################ # Header files @@ -1342,6 +1384,8 @@ 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 + rm -f Include/pydtrace_offsets Include/pydtrace_offsets.h -rm -f Lib/lib2to3/*Grammar*.pickle -rm -f $(SYSCONFIGDATA) -rm -f Modules/_testembed Modules/_freeze_importlib @@ -1373,6 +1417,8 @@ -o -name '*.orig' -o -name '*.rej' \ -o -name '*.bak' ')' \ -exec rm -f {} ';' + rm -f Include/pydtrace.h + rm -f Include/pydtrace_offsets Include/pydtrace_offsets.h # Check for smelly exported symbols (not starting with Py/_Py) smelly: all diff -r bd8afb90ebf2 -r 775eeaf1a707 Misc/NEWS --- a/Misc/NEWS Sat Sep 29 09:44:17 2012 +0200 +++ b/Misc/NEWS Tue Oct 02 02:21:51 2012 +0200 @@ -172,8 +172,6 @@ - Issue #15544: Fix Decimal.__float__ to work with payload-carrying NaNs. -- Issue #15776: Allow pyvenv to work in existing directory with --clean. - - Issue #15249: BytesGenerator now correctly mangles From lines (when requested) even if the body contains undecodable bytes. diff -r bd8afb90ebf2 -r 775eeaf1a707 Modules/dtracemodule.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Modules/dtracemodule.c Tue Oct 02 02:21:51 2012 +0200 @@ -0,0 +1,39 @@ +#include "Python.h" + +static PyMethodDef dtrace_methods[] = { + {NULL, NULL} /* sentinel */ +}; + + +static struct PyModuleDef dtracemodule = { + PyModuleDef_HEAD_INIT, + "dtrace", + NULL, + -1, + dtrace_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit_dtrace(void) +{ + PyObject *m, *v; + + m = PyModule_Create(&dtracemodule); + if (m) { +#ifdef WITH_DTRACE + v = Py_True; +#else + v = Py_False; +#endif + Py_INCREF(v); + if (PyModule_AddObject(m, "available", v) < 0) { + Py_DECREF(m); + return NULL; + } + } + return m; +} diff -r bd8afb90ebf2 -r 775eeaf1a707 Modules/gcmodule.c --- a/Modules/gcmodule.c Sat Sep 29 09:44:17 2012 +0200 +++ b/Modules/gcmodule.c Tue Oct 02 02:21:51 2012 +0200 @@ -26,6 +26,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) @@ -841,7 +845,12 @@ /* This is the main function. Read this to understand how the * collection process works. */ static Py_ssize_t -collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable) +#ifdef WITH_DTRACE +collect2 +#else +collect +#endif +(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable) { int i; Py_ssize_t m = 0; /* # objects collected */ @@ -1000,6 +1009,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 *n_collected, Py_ssize_t *n_uncollectable) +{ + Py_ssize_t value; + + if (PYTHON_GC_START_ENABLED()) + dtrace_gc_start(collection); + value = collect2(collection, n_collected, n_uncollectable); + if (PYTHON_GC_DONE_ENABLED()) + dtrace_gc_done(value); + return value; +} +#endif /* WITH_DTRACE */ + /* Invoke progress callbacks to notify clients that garbage collection * is starting or stopping */ diff -r bd8afb90ebf2 -r 775eeaf1a707 Objects/codeobject.c --- a/Objects/codeobject.c Sat Sep 29 09:44:17 2012 +0200 +++ b/Objects/codeobject.c Tue Oct 02 02:21:51 2012 +0200 @@ -147,6 +147,37 @@ co->co_lnotab = lnotab; co->co_zombieframe = NULL; co->co_weakreflist = NULL; + +#ifdef WITH_DTRACE + /* + ** Cache UTF8 internally, available + ** for the pythonframe stack walker. + */ + PyUnicode_AsUTF8(filename); + PyUnicode_AsUTF8(name); + + i = PyBytes_Size(co->co_code); + co->co_linenos = PyMem_Malloc(sizeof(unsigned short) * i); + if (co->co_linenos) { + unsigned short *p = (unsigned short *)(co->co_linenos); + unsigned char *p2 = (unsigned char*)PyBytes_AsString(co->co_lnotab); + int size = PyBytes_Size(co->co_lnotab) / 2; + int i2; + unsigned short offset = 0; + + while (size) { + size -= 1; + i2 = *p2++; + i-=i2; + while (i2--) + *p++ = offset; + offset += *p2++; + } + while(i--) + *p++ = offset; + } +#endif + return co; } diff -r bd8afb90ebf2 -r 775eeaf1a707 Objects/frameobject.c --- a/Objects/frameobject.c Sat Sep 29 09:44:17 2012 +0200 +++ b/Objects/frameobject.c Tue Oct 02 02:21:51 2012 +0200 @@ -714,6 +714,15 @@ f->f_lineno = code->co_firstlineno; f->f_iblock = 0; +#ifdef WITH_DTRACE + /* + ** Cache UTF8 internally, available + ** for the pythonframe stack walker. + */ + PyUnicode_AsUTF8(f->f_code->co_filename); + PyUnicode_AsUTF8(f->f_code->co_name); +#endif + _PyObject_GC_TRACK(f); return f; } diff -r bd8afb90ebf2 -r 775eeaf1a707 Objects/typeobject.c --- a/Objects/typeobject.c Sat Sep 29 09:44:17 2012 +0200 +++ b/Objects/typeobject.c Tue Oct 02 02:21:51 2012 +0200 @@ -4,6 +4,10 @@ #include "frameobject.h" #include "structmember.h" +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + #include @@ -743,8 +747,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 || !PyUnicode_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyUnicode_AsUTF8(mod); + if (!mod_name) + 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); @@ -766,6 +791,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 || !PyUnicode_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyUnicode_AsUTF8(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_NEW_DONE((char *)(type->tp_name), mod_name); + } + } +#endif + return obj; } @@ -886,9 +928,56 @@ return 0; } +#ifdef WITH_DTRACE +static void subtype_dealloc2(PyObject *); /* Forward declaration */ + static void subtype_dealloc(PyObject *self) { + PyObject *mod; + char *mod_name; + PyTypeObject *type; + + type = Py_TYPE(self); + Py_INCREF(type); + + if (PYTHON_INSTANCE_DELETE_START_ENABLED()) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyUnicode_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyUnicode_AsUTF8(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_DELETE_START((char *)(type->tp_name), mod_name); + } + + subtype_dealloc2(self); + + if (PYTHON_INSTANCE_DELETE_DONE_ENABLED()) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyUnicode_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyUnicode_AsUTF8(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_DELETE_DONE((char *)(type->tp_name), mod_name); + } + Py_DECREF(type); +} +#endif + +static void +#ifdef WITH_DTRACE +subtype_dealloc2 +#else +subtype_dealloc +#endif +(PyObject *self) +{ PyTypeObject *type, *base; destructor basedealloc; PyThreadState *tstate = PyThreadState_GET(); diff -r bd8afb90ebf2 -r 775eeaf1a707 Python/ceval.c --- a/Python/ceval.c Sat Sep 29 09:44:17 2012 +0200 +++ b/Python/ceval.c Tue Oct 02 02:21:51 2012 +0200 @@ -18,6 +18,13 @@ #include +#ifdef WITH_DTRACE +#include "pydtrace.h" +#else +/* We can not have conditional compilation inside macros */ +#define PYTHON_LINE_ENABLED() (0) +#endif + #ifndef WITH_TSC #define READ_TIMESTAMP(var) @@ -119,6 +126,12 @@ #define CALL_FLAG_VAR 1 #define CALL_FLAG_KW 2 +#ifdef WITH_DTRACE +static void maybe_dtrace_line(PyFrameObject *frame, + int *instr_lb, int *instr_ub, + int *instr_prev); +#endif + #ifdef LLTRACE static int lltrace; static int prtrace(PyObject *, char *); @@ -776,6 +789,49 @@ NULL, NULL); } +#ifdef WITH_DTRACE +static void +dtrace_entry(PyFrameObject *f) +{ + char *filename; + char *name; + int lineno; + + filename = PyUnicode_AsUTF8(f->f_code->co_filename); + name = PyUnicode_AsUTF8(f->f_code->co_name); + lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + PYTHON_FUNCTION_ENTRY(filename, name, 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) +{ + char *filename; + char *name; + int lineno; + + filename = PyUnicode_AsUTF8(f->f_code->co_filename); + name = PyUnicode_AsUTF8(f->f_code->co_name); + lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + PYTHON_FUNCTION_RETURN(filename, name, lineno); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} +#endif /* Interpreter main loop */ @@ -787,8 +843,16 @@ return PyEval_EvalFrameEx(f, 0); } + PyObject * +#if defined(WITH_DTRACE) && defined(__amd64) +PyEval_EvalFrameExReal(long a1, long a2, long a3, long a4, long a5, long a6, + PyFrameObject *f, int throwflag) +#elif defined(WITH_DTRACE) && defined(__sparc) +PyEval_EvalFrameExReal(PyFrameObject *f, int throwflag) +#else PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) +#endif { #ifdef DXPAIRS int lastopcode = 0; @@ -915,7 +979,7 @@ #ifdef LLTRACE #define FAST_DISPATCH() \ { \ - if (!lltrace && !_Py_TracingPossible) { \ + if (!lltrace && !_Py_TracingPossible && !PYTHON_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ goto *opcode_targets[*next_instr++]; \ } \ @@ -924,7 +988,7 @@ #else #define FAST_DISPATCH() \ { \ - if (!_Py_TracingPossible) { \ + if (!_Py_TracingPossible && !PYTHON_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ goto *opcode_targets[*next_instr++]; \ } \ @@ -1160,6 +1224,11 @@ } } +#ifdef WITH_DTRACE + if (PYTHON_FUNCTION_ENTRY_ENABLED()) + dtrace_entry(f); +#endif + co = f->f_code; names = co->co_names; consts = co->co_consts; @@ -1347,6 +1416,12 @@ /* Main switch on opcode */ READ_TIMESTAMP(inst0); +#ifdef WITH_DTRACE + if (PYTHON_LINE_ENABLED()) { + maybe_dtrace_line(f, &instr_lb, &instr_ub, &instr_prev); + } +#endif + switch (opcode) { /* BEWARE! @@ -3077,6 +3152,10 @@ /* pop frame */ exit_eval_frame: +#ifdef WITH_DTRACE + if (PYTHON_FUNCTION_RETURN_ENABLED()) + dtrace_return(f); +#endif Py_LeaveRecursiveCall(); tstate->frame = f->f_back; @@ -3766,6 +3845,57 @@ return result; } +/* + * 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_EvalFrameEx(PyFrameObject *f, int throwflag) +{ + volatile PyObject *f2; + f2 = PyEval_EvalFrameExReal(0, 0, 0, 0, 0, 0, f, throwflag); + return (PyObject *)f2; +} + +#elif defined(__sparc) + +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; +} + +#endif +#endif + + PyObject * _PyEval_CallTracing(PyObject *func, PyObject *args) { @@ -3784,6 +3914,51 @@ return result; } +#ifdef WITH_DTRACE +/* See Objects/lnotab_notes.txt for a description of how tracing works. */ +/* Practically a ripoff of "maybe_call_line_trace" function. */ +static void +maybe_dtrace_line(PyFrameObject *frame, + int *instr_lb, int *instr_ub, int *instr_prev) +{ + int line = frame->f_lineno; + char *co_filename, *co_name; + + /* If the last instruction executed isn't in the current + instruction window, reset the window. + */ + if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) { + PyAddrPair bounds; + line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti, + &bounds); + *instr_lb = bounds.ap_lower; + *instr_ub = bounds.ap_upper; + } + /* If the last instruction falls at the start of a line or if + it represents a jump backwards, update the frame's line + number and call the trace function. */ + if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) { + frame->f_lineno = line; + co_filename = PyUnicode_AsUTF8(frame->f_code->co_filename); + if (!co_filename) + co_filename = "?"; + co_name = PyUnicode_AsUTF8(frame->f_code->co_name); + if (!co_name) + co_name = "?"; + PYTHON_LINE(co_filename, co_name, line); + } + *instr_prev = frame->f_lasti; + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} +#endif + /* See Objects/lnotab_notes.txt for a description of how tracing works. */ static int maybe_call_line_trace(Py_tracefunc func, PyObject *obj, diff -r bd8afb90ebf2 -r 775eeaf1a707 configure --- a/configure Sat Sep 29 09:44:17 2012 +0200 +++ b/configure Tue Oct 02 02:21:51 2012 +0200 @@ -1,13 +1,11 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for python 3.3. +# Generated by GNU Autoconf 2.69 for python 3.3. # # Report bugs to . # # -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software -# Foundation, Inc. +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation @@ -136,6 +134,31 @@ # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh @@ -169,7 +192,8 @@ else exitcode=1; echo positional parameters were not saved. fi -test x\$exitcode = x0 || exit 1" +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && @@ -214,21 +238,25 @@ if test "x$CONFIG_SHELL" != x; then : - # We cannot yet assume a decent shell, so we have to provide a - # neutralization value for shells without unset; and this also - # works around shells that cannot unset nonexistent variables. - # Preserve -v and -x to the replacement shell. - BASH_ENV=/dev/null - ENV=/dev/null - (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV - export CONFIG_SHELL - case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; - esac - exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 fi if test x$as_have_required = xno; then : @@ -331,6 +359,14 @@ } # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take @@ -452,6 +488,10 @@ chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). @@ -486,16 +526,16 @@ # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' - fi -else - as_ln_s='cp -p' + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null @@ -507,28 +547,8 @@ as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -618,6 +638,11 @@ MACHDEP_OBJS DYNLOADFILE DLINCLDIR +DTRACEOBJS +DTRACE_LINKER +DTRACE_NM +DFLAGS +DTRACE THREADOBJ LDLAST USE_THREAD_MODULE @@ -779,6 +804,7 @@ with_tsc with_pymalloc with_valgrind +with_dtrace with_fpectl with_libm with_libc @@ -1249,8 +1275,6 @@ if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used" >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1456,6 +1480,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-fpectl enable SIGFPE catching --with-libm=STRING math library --with-libc=STRING C library @@ -1540,9 +1565,9 @@ if $ac_init_version; then cat <<\_ACEOF python configure 3.3 -generated by GNU Autoconf 2.68 - -Copyright (C) 2010 Free Software Foundation, Inc. +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1618,7 +1643,7 @@ test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext + test -x conftest$ac_exeext }; then : ac_retval=0 else @@ -1916,7 +1941,8 @@ main () { static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; -test_array [0] = 0 +test_array [0] = 0; +return test_array [0]; ; return 0; @@ -1970,7 +1996,8 @@ main () { static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; -test_array [0] = 0 +test_array [0] = 0; +return test_array [0]; ; return 0; @@ -1986,7 +2013,8 @@ { static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; -test_array [0] = 0 +test_array [0] = 0; +return test_array [0]; ; return 0; @@ -2036,7 +2064,8 @@ main () { static int test_array [1 - 2 * !(($2) >= 0)]; -test_array [0] = 0 +test_array [0] = 0; +return test_array [0]; ; return 0; @@ -2052,7 +2081,8 @@ main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; -test_array [0] = 0 +test_array [0] = 0; +return test_array [0]; ; return 0; @@ -2078,7 +2108,8 @@ main () { static int test_array [1 - 2 * !(($2) < 0)]; -test_array [0] = 0 +test_array [0] = 0; +return test_array [0]; ; return 0; @@ -2094,7 +2125,8 @@ main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; -test_array [0] = 0 +test_array [0] = 0; +return test_array [0]; ; return 0; @@ -2128,7 +2160,8 @@ main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; -test_array [0] = 0 +test_array [0] = 0; +return test_array [0]; ; return 0; @@ -2371,7 +2404,7 @@ running configure, to aid debugging if configure makes a mistake. It was created by python $as_me 3.3, which was -generated by GNU Autoconf 2.68. Invocation command line was +generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2741,7 +2774,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_HAS_HG="found" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3530,7 +3563,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3570,7 +3603,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3623,7 +3656,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3664,7 +3697,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue @@ -3722,7 +3755,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3766,7 +3799,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -4212,8 +4245,7 @@ /* end confdefs.h. */ #include #include -#include -#include +struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); @@ -4353,7 +4385,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -4396,7 +4428,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -4451,7 +4483,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -4494,7 +4526,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -4549,7 +4581,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -4592,7 +4624,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -4655,7 +4687,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -4699,7 +4731,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -4942,7 +4974,7 @@ for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in @@ -5008,7 +5040,7 @@ for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in @@ -5215,8 +5247,8 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -# define __EXTENSIONS__ 1 - $ac_includes_default +# define __EXTENSIONS__ 1 + $ac_includes_default int main () { @@ -5612,7 +5644,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5652,7 +5684,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5707,7 +5739,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5751,7 +5783,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5815,7 +5847,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_READELF="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5859,7 +5891,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_READELF="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5923,7 +5955,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_HAS_PYTHON="found" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5996,7 +6028,7 @@ # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. @@ -6065,7 +6097,7 @@ test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do - { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ @@ -8960,7 +8992,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -9003,7 +9035,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -10065,6 +10097,181 @@ OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT" 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; +else + with_dtrace=yes +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_dtrace" >&5 +$as_echo "$with_dtrace" >&6; } + + + + + +DTRACE= +DFLAGS= +if test "$with_dtrace" = "yes" +then + DTRACE_NM=OTHER + DTRACE_LINKER=ld + DTRACEOBJS="Python/pydtrace.o" + # Extract the first word of "dtrace", so it can be a program name with args. +set dummy dtrace; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTRACE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/sbin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DTRACE" && ac_cv_path_DTRACE="dtrace" + ;; +esac +fi +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # 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 ${ac_cv_sizeof_long+:} false; 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 + sys_release="$ac_sys_release" + if test $ac_sys_system = "SunOS" + then + if test $sys_release="5.11" + then + sys_release=`uname -v` + fi + fi + case $ac_sys_system/$sys_release in + SunOS/5.10) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/11.*) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/*) + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + Darwin/*) + DTRACEOBJS="" # Not needed in Mac + # 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 ${ac_cv_sizeof_long+:} false; 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="-arch i386" + else + DFLAGS="-arch x86_64" + fi + ;; + esac + +$as_echo "#define WITH_DTRACE 1" >>confdefs.h + +fi + + + # -I${DLINCLDIR} is added to the compile rule for importdl.o DLINCLDIR=. @@ -10610,7 +10817,7 @@ IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_TRUE="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -12047,7 +12254,8 @@ main () { static int test_array [1 - 2 * !(((char) -1) < 0)]; -test_array [0] = 0 +test_array [0] = 0; +return test_array [0]; ; return 0; @@ -12078,11 +12286,11 @@ int main () { -/* FIXME: Include the comments suggested by Paul. */ + #ifndef __cplusplus - /* Ultrix mips cc rejects this. */ + /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; - const charset cs; + const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; @@ -12099,8 +12307,9 @@ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; - { /* SCO 3.2v4 cc rejects this. */ - char *t; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; @@ -12116,10 +12325,10 @@ iptr p = 0; ++p; } - { /* AIX XL C 1.02.0.0 rejects this saying + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; }; - struct s *b; b->j = 5; + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; @@ -15451,16 +15660,16 @@ # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' - fi -else - as_ln_s='cp -p' + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null @@ -15520,28 +15729,16 @@ as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -15563,7 +15760,7 @@ # values after options handling. ac_log=" This file was extended by python $as_me 3.3, which was -generated by GNU Autoconf 2.68. Invocation command line was +generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -15625,10 +15822,10 @@ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ python config.status 3.3 -configured by $0, generated by GNU Autoconf 2.68, +configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -15718,7 +15915,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then - set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' diff -r bd8afb90ebf2 -r 775eeaf1a707 configure.ac --- a/configure.ac Sat Sep 29 09:44:17 2012 +0200 +++ b/configure.ac Tue Oct 02 02:21:51 2012 +0200 @@ -2678,6 +2678,69 @@ OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT" 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),, + with_dtrace=no) +AC_MSG_RESULT($with_dtrace) + +AC_SUBST(DTRACE) +AC_SUBST(DFLAGS) +AC_SUBST(DTRACE_NM) +AC_SUBST(DTRACE_LINKER) +DTRACE= +DFLAGS= +if test "$with_dtrace" = "yes" +then + DTRACE_NM=OTHER + DTRACE_LINKER=ld + DTRACEOBJS="Python/pydtrace.o" + AC_PATH_PROG(DTRACE, [dtrace], [dtrace], [$PATH$PATH_SEPARATOR/usr/sbin]) + AC_CHECK_SIZEOF([long]) + if [test "$ac_cv_sizeof_long" -eq 8] + then + DFLAGS="-64" + else + DFLAGS="-32" + fi + sys_release="$ac_sys_release" + if test $ac_sys_system = "SunOS" + then + if test $sys_release="5.11" + then + sys_release=`uname -v` + fi + fi + case $ac_sys_system/$sys_release in + SunOS/5.10) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/11.*) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/*) + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + Darwin/*) + DTRACEOBJS="" # Not needed in Mac + AC_CHECK_SIZEOF([long]) + if [test "$ac_cv_sizeof_long" -eq 8] + then + DFLAGS="-arch i386" + else + DFLAGS="-arch x86_64" + fi + ;; + esac + AC_DEFINE(WITH_DTRACE, 1, + [Define if you want to compile in Dtrace support]) +fi + +AC_SUBST(DTRACEOBJS) + # -I${DLINCLDIR} is added to the compile rule for importdl.o AC_SUBST(DLINCLDIR) DLINCLDIR=. diff -r bd8afb90ebf2 -r 775eeaf1a707 pyconfig.h.in --- a/pyconfig.h.in Sat Sep 29 09:44:17 2012 +0200 +++ b/pyconfig.h.in Tue Oct 02 02:21:51 2012 +0200 @@ -1291,6 +1291,9 @@ /* Define if you want documentation strings in extension modules */ #undef WITH_DOC_STRINGS +/* Define if you want 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. */ diff -r bd8afb90ebf2 -r 775eeaf1a707 setup.py --- a/setup.py Sat Sep 29 09:44:17 2012 +0200 +++ b/setup.py Tue Oct 02 02:21:51 2012 +0200 @@ -644,6 +644,9 @@ # syslog daemon interface exts.append( Extension('syslog', ['syslogmodule.c']) ) + # jcea DTRACE probes + exts.append( Extension('dtrace', ['dtracemodule.c']) ) + # # Here ends the simple stuff. From here on, modules need certain # libraries, are platform-specific, or present other surprises.