components/python/python35/patches/00-dtrace.patch
changeset 4912 0b79e9575718
child 5184 6c2a9525f3a4
equal deleted inserted replaced
4911:6590570733a1 4912:0b79e9575718
       
     1 This patch comes from upstream:
       
     2 http://www.jcea.es/artic/python_dtrace-3_4_0_0de6441eedb7.txt
       
     3 http://www.jcea.es/artic/python_dtrace.htm
       
     4 Follow http://bugs.python.org/issue13405 for plans to get it
       
     5 integrated into the main tree.
       
     6 
       
     7 --- Python-3.4.0/Doc/library/debug.rst
       
     8 +++ Python-3.4.0/Doc/library/debug.rst
       
     9 @@ -15,4 +15,5 @@
       
    10     profile.rst
       
    11     timeit.rst
       
    12     trace.rst
       
    13 +   dtrace.rst
       
    14     tracemalloc.rst
       
    15 --- /dev/null
       
    16 +++ Python-3.4.0/Doc/library/dtrace.rst
       
    17 @@ -0,0 +1,183 @@
       
    18 +:mod:`dtrace` --- DTrace probes for Python
       
    19 +===============================================
       
    20 +
       
    21 +.. module:: dtrace
       
    22 +   :synopsis: DTrace probes for Python.
       
    23 +
       
    24 +**Source code:** :source:`Lib/dtrace.py`
       
    25 +
       
    26 +--------------
       
    27 +
       
    28 +The :mod:`dtrace` module indicates if the CPython executable currently
       
    29 +running has been compiled with DTrace probes support.
       
    30 +
       
    31 +.. impl-detail::
       
    32 +
       
    33 +   DTrace probes are implementation details of the CPython interpreter!
       
    34 +   No garantees are made about probe compatibility between versions of
       
    35 +   CPython. DTrace scripts can stop working or work incorrectly without
       
    36 +   warning when changing CPython versions.
       
    37 +
       
    38 +The :mod:`dtrace` module defines the following variable:
       
    39 +
       
    40 +
       
    41 +.. data:: available
       
    42 +
       
    43 +   The variable will be ``True`` if the current CPython interpreter was
       
    44 +   compiled with DTrace probe support. ``False`` if not.
       
    45 +   
       
    46 +
       
    47 +DTrace probes
       
    48 +-------------
       
    49 +
       
    50 +DTrace scripts are run externally to CPython. DTrace probes export
       
    51 +selected events inside CPython interpreter in order to make them
       
    52 +accessible to external scripts.
       
    53 +
       
    54 +The probes are exported through the "python" provider. The available
       
    55 +probes are defined in the file :file:`Include/pydtrace.d`.
       
    56 +
       
    57 +To learn how to use DTrace, read `DTrace User Guide
       
    58 +<http://docs.oracle.com/cd/E19253-01/819-5488/>`_.
       
    59 +
       
    60 +.. opcode:: function-entry (arg0, arg1, arg2)
       
    61 +
       
    62 +   Fires when python code enters a new function. *arg0* is sourcecode
       
    63 +   file path, *arg1* is the name of the funcion called, and *arg2* is
       
    64 +   line number.
       
    65 +
       
    66 +   The probe is not fired if Python code calls C functions.
       
    67 +
       
    68 +.. opcode:: function-return (arg0, arg1, arg2)
       
    69 +
       
    70 +   Fires when Python code finishes execution of a function. Parameters
       
    71 +   are the same as in ``function-entry``.
       
    72 +
       
    73 +   The probe is not fired if the finishing function is written in C.
       
    74 +
       
    75 +.. opcode:: line (arg0, arg1, arg2)
       
    76 +
       
    77 +   Fires when Python code changes the execution line. Parameters are the
       
    78 +   same as in ``function-entry``.
       
    79 +
       
    80 +   The probe is not fired in C functions.
       
    81 +
       
    82 +.. opcode:: gc-start (arg0)
       
    83 +
       
    84 +   Fires when the Python interpreter starts a garbage collection cycle.
       
    85 +   *arg0* is the generation to scan, like :func:`gc.collect()`.
       
    86 +
       
    87 +.. opcode:: gc-done (arg0)
       
    88 +
       
    89 +   Fires when the Python interpreter finishes a garbage collection
       
    90 +   cycle. *arg0* is the number of collected objects.
       
    91 +
       
    92 +.. opcode:: instance-new-start (arg0, arg1)
       
    93 +
       
    94 +   Fires when an object instanciation starts. *arg0* is the class name,
       
    95 +   *arg1* is the filename where the class is defined.
       
    96 +
       
    97 +   The probe is not fired for most C code object creations.
       
    98 +
       
    99 +.. opcode:: instance-new-done (arg0, arg1)
       
   100 +
       
   101 +   Fires when an object instanciation finishes. Parameters are the same
       
   102 +   as in ``instance-new-done``.
       
   103 +
       
   104 +   The probe is not fired for most C code object creations.
       
   105 +
       
   106 +.. opcode:: instance-delete-start (arg0, arg1)
       
   107 +
       
   108 +   Fires when an object instance is going to be destroyed. Parameters
       
   109 +   are the same as in ``instance-new-done``.
       
   110 +
       
   111 +   The probe is not fired for most C code object destructions.
       
   112 +
       
   113 +.. opcode:: instance-delete-done (arg0, arg1)
       
   114 +
       
   115 +   Fires when an object instance has been destroyed. parameters are the
       
   116 +   same as in ``instance-new-done``.
       
   117 +
       
   118 +   Between an ``instance-delete-start`` and corresponding
       
   119 +   ``instance-delete-done`` others probes can fire if, for instance,
       
   120 +   deletion of an instance creates a deletion cascade.
       
   121 +
       
   122 +   The probe is not fired for most C code object destructions.
       
   123 +
       
   124 +
       
   125 +Python stack
       
   126 +------------
       
   127 +
       
   128 +When a DTrace probe is fired, the DTrace script can examine the stack.
       
   129 +Since CPython is a Python interpreter coded in C, the stack will show C
       
   130 +functions, with no direct relation to the Python code currently being
       
   131 +executed.
       
   132 +
       
   133 +Using the special "jstack()" DTrace function, the user will be given
       
   134 +hints about the python program stack, if possible. In particular, the
       
   135 +augmented stack will show python function calls, filename, name
       
   136 +of the function or method, and the line number.
       
   137 +
       
   138 +DTrace scripts examples
       
   139 +-----------------------
       
   140 +
       
   141 +DTrace python provider is suffixed by the pid of the process to monitor.
       
   142 +In the examples, the pid will be 9876.
       
   143 +
       
   144 +Show the time spent doing garbage collection (in nanoseconds)::
       
   145 +
       
   146 +  python9876:::gc-start
       
   147 +  {
       
   148 +      self->t = timestamp;
       
   149 +  }
       
   150 +
       
   151 +  python9876:::gc-done
       
   152 +  /self->t/
       
   153 +  {
       
   154 +      printf("%d", timestamp-self->t);
       
   155 +      self->t = 0;
       
   156 +  }
       
   157 +
       
   158 +Count how many instances are created of each class::
       
   159 +
       
   160 +  python9876:::instance-new-start
       
   161 +  {
       
   162 +      @v[copyinstr(arg1), copyinstr(arg0)] = count();
       
   163 +  }
       
   164 +
       
   165 +Observe time spent in object destruction, useful if datastructures are
       
   166 +complicated and deletion of an object can create a cascade effect::
       
   167 +
       
   168 +  python9876:::instance-delete-start
       
   169 +  /self->t==0/
       
   170 +  {
       
   171 +      self->t = timestamp;
       
   172 +      self->level = 0;
       
   173 +  }
       
   174 +
       
   175 +  python9876:::instance-delete-start
       
   176 +  /self->t/
       
   177 +  {
       
   178 +      self->level += 1;
       
   179 +  }
       
   180 +
       
   181 +  python9876:::instance-delete-done
       
   182 +  /(self->level) && (self->t)/
       
   183 +  {
       
   184 +      self->level -= 1;
       
   185 +  }
       
   186 +
       
   187 +  python9876:::instance-delete-done
       
   188 +  /(self->level==0) && (self->t)/
       
   189 +  {
       
   190 +      @time = quantize(timestamp-self->t);
       
   191 +      self->t = 0;
       
   192 +  }
       
   193 +
       
   194 +To know which python source code lines create new TCP/IP connections::
       
   195 +
       
   196 +  pid9876::sock_connect:entry
       
   197 +  {
       
   198 +      @conn[jstack()] = count();
       
   199 +  }
       
   200 +
       
   201 --- Python-3.5.0a4/Include/code.h.~1~	2015-04-20 00:37:51.000000000 -0700
       
   202 +++ Python-3.5.0a4/Include/code.h	2015-04-20 12:35:52.053616933 -0700
       
   203 @@ -7,6 +7,8 @@
       
   204  extern "C" {
       
   205  #endif
       
   206  
       
   207 +#include "pyconfig.h"
       
   208 +
       
   209  /* Bytecode object */
       
   210  typedef struct {
       
   211      PyObject_HEAD
       
   212 @@ -33,6 +35,9 @@
       
   213      int co_firstlineno;		/* first source line number */
       
   214      PyObject *co_lnotab;	/* string (encoding addr<->lineno mapping) See
       
   215  				   Objects/lnotab_notes.txt for details. */
       
   216 +#ifdef WITH_DTRACE
       
   217 +    unsigned short *co_linenos; /* dtrace stack helper */
       
   218 +#endif
       
   219      void *co_zombieframe;     /* for optimization only (see frameobject.c) */
       
   220      PyObject *co_weakreflist;   /* to support weakrefs to code objects */
       
   221  } PyCodeObject;
       
   222 --- /dev/null
       
   223 +++ Python-3.4.0/Include/pydtrace.d
       
   224 @@ -0,0 +1,177 @@
       
   225 +provider python {
       
   226 +    probe function__entry(const char *, const char *, int);
       
   227 +    probe function__return(const char *, const char *, int);
       
   228 +    probe instance__new__start(const char *, const char *);
       
   229 +    probe instance__new__done(const char *, const char *);
       
   230 +    probe instance__delete__start(const char *, const char *);
       
   231 +    probe instance__delete__done(const char *, const char *);
       
   232 +    probe line(const char *, const char *, int);
       
   233 +    probe gc__start(int);
       
   234 +    probe gc__done(long);
       
   235 +};
       
   236 +
       
   237 +#pragma D attributes Evolving/Evolving/Common provider python provider
       
   238 +#pragma D attributes Private/Private/Common provider python module
       
   239 +#pragma D attributes Private/Private/Common provider python function
       
   240 +#pragma D attributes Evolving/Evolving/Common provider python name
       
   241 +#pragma D attributes Evolving/Evolving/Common provider python args
       
   242 +
       
   243 +
       
   244 +
       
   245 +#ifdef PYDTRACE_STACK_HELPER
       
   246 +/*
       
   247 + * Python ustack helper.  This relies on the first argument (PyFrame *) being
       
   248 + * on the stack; see Python/ceval.c for the contortions we go through to ensure
       
   249 + * this is the case.
       
   250 + *
       
   251 + * On x86, the PyFrame * is two slots up from the frame pointer; on SPARC, it's
       
   252 + * eight.
       
   253 + *
       
   254 + * Some details about this in "Python and DTrace in build 65":
       
   255 + * http://blogs.oracle.com/levon/entry/python_and_dtrace_in_build
       
   256 + */
       
   257 +
       
   258 +/*
       
   259 + * Yes, this is as gross as it looks. DTrace cannot handle static functions,
       
   260 + * and our stat_impl.h has them in ILP32.
       
   261 + */
       
   262 +#define _SYS_STAT_H
       
   263 +
       
   264 +/*
       
   265 +** When compiling in 32 bits:
       
   266 +** - Early inclusion to avoid problems with
       
   267 +**   _FILE_OFFSET_BITS redefined.
       
   268 +** - Also, we must "undef" _POSIX_PTHREAD_SEMANTICS
       
   269 +**   to avoid error compiling this source.
       
   270 +*/
       
   271 +#include "pyconfig.h"
       
   272 +#undef _POSIX_PTHREAD_SEMANTICS
       
   273 +
       
   274 +#include <stdio.h>
       
   275 +#include <sys/types.h>
       
   276 +
       
   277 +#include "pyport.h"
       
   278 +#include "pyatomic.h"
       
   279 +/* "string" type is used in dtrace */
       
   280 +#define string	stringDTRACE
       
   281 +#include "object.h"
       
   282 +#include "pystate.h"
       
   283 +#include "pyarena.h"
       
   284 +#include "pythonrun.h"
       
   285 +#include "compile.h"
       
   286 +#include "frameobject.h"
       
   287 +/* Avoid a compile error because a symbol (equivalent) redefinition */
       
   288 +#undef __STDC__
       
   289 +/* "self" has an special meaning for dtrace */
       
   290 +#define self	selfDTRACE
       
   291 +#include "unicodeobject.h"
       
   292 +#undef string
       
   293 +#undef self
       
   294 +
       
   295 +#include "pydtrace_offsets.h"
       
   296 +
       
   297 +#if defined(__i386)
       
   298 +#define	startframe PyEval_EvalFrameEx
       
   299 +#define	endframe AFTER_PyEval_EvalFrameEx
       
   300 +#elif defined(__amd64)
       
   301 +#define	startframe PyEval_EvalFrameExReal
       
   302 +#define	endframe AFTER_PyEval_EvalFrameExReal
       
   303 +#elif defined(__sparc)
       
   304 +#define	startframe PyEval_EvalFrameExReal
       
   305 +#define	endframe AFTER_PyEval_EvalFrameExReal
       
   306 +#endif
       
   307 +
       
   308 +#ifdef __sparcv9
       
   309 +#define	STACK_BIAS (2048-1)
       
   310 +#else
       
   311 +#define	STACK_BIAS 0
       
   312 +#endif
       
   313 +
       
   314 +#define	at_evalframe(addr) \
       
   315 +    ((uintptr_t)addr >= ((uintptr_t)&``startframe) && \
       
   316 +     (uintptr_t)addr < ((uintptr_t)&``endframe))
       
   317 +#define	probe dtrace:helper:ustack:
       
   318 +#define	print_result(r) (r)
       
   319 +
       
   320 +#if defined(__i386) || defined(__amd64)
       
   321 +#define	frame_ptr_addr ((uintptr_t)arg1 + sizeof(uintptr_t) * 2)
       
   322 +#elif defined(__sparc)
       
   323 +#define	frame_ptr_addr ((uintptr_t)arg1 + STACK_BIAS + sizeof(uintptr_t) * 8)
       
   324 +#else
       
   325 +#error unknown architecture
       
   326 +#endif
       
   327 +
       
   328 +/* startframe and endframe are macro-expansions */
       
   329 +extern uintptr_t startframe;
       
   330 +extern uintptr_t endframe;
       
   331 +
       
   332 +
       
   333 +#define	copyin_obj(addr, obj) ((obj *)copyin((uintptr_t)(addr), sizeof(obj)))
       
   334 +
       
   335 +/*
       
   336 +** Check if the string is ASCII. Don't use bitfields, because the
       
   337 +** packing in GCC and D are different. BEWARE!!!.
       
   338 +** The size of the structures are also different!. That is the reason for
       
   339 +** the negative offset. BEWARE!!!
       
   340 +*/
       
   341 +#define pystr_len(addr) ((*(((char *)addr)+PYDTRACE_ASCII_OFFSET)) & PYDTRACE_ASCII_MASK ? \
       
   342 +		(addr)->_base.length : \
       
   343 +		*(Py_ssize_t *)(((char *)(addr)) + PYDTRACE_UTF8_LENGTH_OFFSET))
       
   344 +#define pystr_addr(addr, addr2) ((*(((char *)addr)+PYDTRACE_ASCII_OFFSET)) & PYDTRACE_ASCII_MASK ? \
       
   345 +		(char *)(((char *)(addr2)) + PYDTRACE_PyASCIIObject_SIZE) : \
       
   346 +		(char *)*(uintptr_t *)(((char *)(addr)) + PYDTRACE_UTF8_OFFSET))
       
   347 +
       
   348 +#define	add_digit(nr, div) (((nr) / div) ? \
       
   349 +    (this->result[this->pos++] = '0' + (((nr) / div) % 10)) : \
       
   350 +    (this->result[this->pos] = '\0'))
       
   351 +#define	add_char(c) (this->result[this->pos++] = c)
       
   352 +
       
   353 +probe /at_evalframe(arg0)/
       
   354 +{
       
   355 +	this->framep = *(uintptr_t *)copyin(frame_ptr_addr, sizeof(uintptr_t));
       
   356 +	this->frameo = copyin_obj(this->framep, PyFrameObject);
       
   357 +	this->codep = this->frameo->f_code;
       
   358 +	this->codeo = copyin_obj(this->codep, PyCodeObject);
       
   359 +	/* If we just enter a function, show the definition line */
       
   360 +	this->lineno = this->codeo->co_firstlineno +
       
   361 +		(this->frameo->f_lasti == -1 ? 0 :
       
   362 +		*copyin_obj(this->codeo->co_linenos + this->frameo->f_lasti,
       
   363 +			unsigned short));
       
   364 +	this->filenameo = copyin_obj(this->codeo->co_filename, PyCompactUnicodeObject);
       
   365 +	this->len_filename = pystr_len(this->filenameo);
       
   366 +	this->nameo = copyin_obj(this->codeo->co_name, PyCompactUnicodeObject);
       
   367 +	this->len_name = pystr_len(this->nameo);
       
   368 +	this->len = 1 + (this->len_filename) + 1 + 5 + 2 +
       
   369 +	    (this->len_name) + 1 + 1;
       
   370 +
       
   371 +	this->result = (char *)alloca(this->len);
       
   372 +	this->pos = 0;
       
   373 +	add_char('@');
       
   374 +
       
   375 +	copyinto((uintptr_t)pystr_addr(this->filenameo, this->codeo->co_filename), this->len_filename, this->result+this->pos);
       
   376 +	this->pos += this->len_filename;
       
   377 +
       
   378 +	add_char(':');
       
   379 +	add_digit(this->lineno, 10000);
       
   380 +	add_digit(this->lineno, 1000);
       
   381 +	add_digit(this->lineno, 100);
       
   382 +	add_digit(this->lineno, 10);
       
   383 +	add_digit(this->lineno, 1);
       
   384 +	add_char(' ');
       
   385 +	add_char('(');
       
   386 +	
       
   387 +	copyinto((uintptr_t)pystr_addr(this->nameo, this->codeo->co_name), this->len_name, this->result+this->pos);
       
   388 +	this->pos += this->len_name;
       
   389 +
       
   390 +	add_char(')');
       
   391 +	this->result[this->pos] = '\0';
       
   392 +	print_result(stringof(this->result));
       
   393 +}
       
   394 +
       
   395 +probe /!at_evalframe(arg0)/
       
   396 +{
       
   397 +	NULL;
       
   398 +}
       
   399 +
       
   400 +#endif  /* PYDTRACE_STACK_HELPER */
       
   401 +
       
   402 --- /dev/null
       
   403 +++ Python-3.4.0/Include/pydtrace_offsets.c
       
   404 @@ -0,0 +1,40 @@
       
   405 +#include "Python.h"
       
   406 +#include "unicodeobject.h"
       
   407 +#include <stdlib.h>
       
   408 +#include <stdio.h>
       
   409 +
       
   410 +int main(int argc, const char* argv[]) {
       
   411 +    PyCompactUnicodeObject o;
       
   412 +    unsigned char *p = (unsigned char *)(&o);
       
   413 +
       
   414 +    if (argc != 3) {
       
   415 +        printf("Parameter number incorrect\n");
       
   416 +        exit(1);
       
   417 +    }
       
   418 +
       
   419 +    memset(&o, 0, sizeof(o));
       
   420 +    o._base.state.ascii = 1;
       
   421 +    while (!*p) p++;
       
   422 +
       
   423 +    printf("/* File autogenerated. DO NOT MODIFY MANUALLY */\n");
       
   424 +    printf("\n");
       
   425 +    printf("#ifndef PYDTRACE_OFFSETS_H\n");
       
   426 +    printf("#define PYDTRACE_OFFSETS_H\n");
       
   427 +    printf("\n");
       
   428 +    printf("#define PYDTRACE_ASCII_OFFSET %d\n",
       
   429 +            p-(unsigned char *)(&o));
       
   430 +    printf("#define PYDTRACE_ASCII_MASK %d\n", *p);
       
   431 +    printf("#define PYDTRACE_PyASCIIObject_SIZE %d\n",
       
   432 +            sizeof(PyASCIIObject));
       
   433 +    printf("#define PYDTRACE_UTF8_LENGTH_OFFSET %d\n",
       
   434 +            offsetof(PyCompactUnicodeObject, utf8_length));
       
   435 +    printf("#define PYDTRACE_UTF8_OFFSET %d\n",
       
   436 +            offsetof(PyCompactUnicodeObject, utf8));
       
   437 +    printf("\n");
       
   438 +    printf("#define AFTER_PyEval_EvalFrameEx      %s\n", argv[1]);
       
   439 +    printf("#define AFTER_PyEval_EvalFrameExReal  %s\n", argv[2]);
       
   440 +    printf("\n");
       
   441 +    printf("#endif\n");
       
   442 +    return 0;
       
   443 +}
       
   444 +
       
   445 new file mode 100755
       
   446 --- /dev/null
       
   447 +++ Python-3.4.0/Include/pydtrace_offsets.sh
       
   448 @@ -0,0 +1,32 @@
       
   449 +#!/bin/sh
       
   450 +
       
   451 +DTRACE_NM=$1
       
   452 +CEVAL_O=$2
       
   453 +PYDTRACE_OFFSETS=$3
       
   454 +if test "$DTRACE_NM" = "OTHER" ; then
       
   455 +    $PYDTRACE_OFFSETS \
       
   456 +		"`nm -n $CEVAL_O | grep \" T \" | \
       
   457 +		sed -n \"/ T PyEval_EvalFrameEx$/{n;p;}\" | \
       
   458 +		sed \"s/.* T \(.*\)$/\1/\"`" \
       
   459 +		"`nm -n $CEVAL_O | grep \" T \" | \
       
   460 +		sed -n \"/ T PyEval_EvalFrameExReal$/{n;p;}\" | \
       
   461 +		sed \"s/.* T \(.*\)$/\1/\"`"
       
   462 +fi
       
   463 +if test "$DTRACE_NM" = "SOLARIS" ; then 
       
   464 +    $PYDTRACE_OFFSETS \
       
   465 +		"`/usr/ccs/bin/nm -n $CEVAL_O | \
       
   466 +		/usr/bin/grep \"\\|FUNC \\|\" | \
       
   467 +		/usr/bin/grep -v \"\\|IGNORE \\|\" | \
       
   468 +		/usr/bin/grep -v \"\\|UNDEF  \\|\" | \
       
   469 +		/usr/bin/tr -d \"\\[\\]\\|\" | sort -n | \
       
   470 +		sed -n \"/ PyEval_EvalFrameEx$/{n;p;}\" | \
       
   471 +		sed \"s/.* \([a-zA-Z0-9_]*\)$/\1/\"`" \
       
   472 +		"`/usr/ccs/bin/nm -n $CEVAL_O | \
       
   473 +		/usr/bin/grep \"\\|FUNC \\|\" | \
       
   474 +		/usr/bin/grep -v \"\\|UNDEF  \\|\" | \
       
   475 +		/usr/bin/grep -v \"\\|IGNORE \\|\" | \
       
   476 +	       	/usr/bin/tr -d \"\\[\\]\\|\" | sort -n | \
       
   477 +		sed -n \"/ PyEval_EvalFrameExReal$/{n;p;}\" | \
       
   478 +		sed \"s/.* \([a-zA-Z0-9_]*\)$/\1/\"`"
       
   479 +fi
       
   480 +
       
   481 --- /dev/null
       
   482 +++ Python-3.4.0/Lib/test/dtrace_sample.py
       
   483 @@ -0,0 +1,80 @@
       
   484 +# Sample script for use by test_dtrace.py
       
   485 +# DO NOT MODIFY THIS FILE IN ANY WAY WITHOUT UPDATING test_dtrace.py!!!!!
       
   486 +
       
   487 +import gc
       
   488 +
       
   489 +def function_1() :
       
   490 +    pass
       
   491 +
       
   492 +# Check stacktrace
       
   493 +def function_2() :
       
   494 +    function_1()
       
   495 +
       
   496 +# CALL_FUNCTION_VAR
       
   497 +def function_3(dummy, dummy2) :
       
   498 +    pass
       
   499 +
       
   500 +# CALL_FUNCTION_KW
       
   501 +def function_4(**dummy) :
       
   502 +    pass
       
   503 +
       
   504 +# CALL_FUNCTION_VAR_KW
       
   505 +def function_5(dummy, dummy2, **dummy3) :
       
   506 +    pass
       
   507 +
       
   508 +def test_entry_return_and_stack() :
       
   509 +    function_1()
       
   510 +    function_2()
       
   511 +    function_3(*(1,2))
       
   512 +    function_4(**{"test":42})
       
   513 +    function_5(*(1,2), **{"test":42})
       
   514 +
       
   515 +def test_line() :
       
   516 +    a = 1  # Preamble
       
   517 +    for i in range(2) :
       
   518 +        a = i
       
   519 +        b = i+2
       
   520 +        c = i+3
       
   521 +        d = a + b +c
       
   522 +    a = 1  # Epilogue
       
   523 +
       
   524 +def test_unicode_entry_return_and_stack() :
       
   525 +    def únícódé() :
       
   526 +        pass
       
   527 +    únícódé()
       
   528 +
       
   529 +def test_instance_creation_destruction() :
       
   530 +    class old_style_class() :
       
   531 +        pass
       
   532 +    class new_style_class(object) :
       
   533 +        pass
       
   534 +
       
   535 +    a = old_style_class()
       
   536 +    del a
       
   537 +    gc.collect()
       
   538 +    b = new_style_class()
       
   539 +    del b
       
   540 +    gc.collect()
       
   541 +
       
   542 +    a = old_style_class()
       
   543 +    del old_style_class
       
   544 +    gc.collect()
       
   545 +    b = new_style_class()
       
   546 +    del new_style_class
       
   547 +    gc.collect()
       
   548 +    del a
       
   549 +    gc.collect()
       
   550 +    del b
       
   551 +    gc.collect()
       
   552 +
       
   553 +def test_garbage_collection() :
       
   554 +    gc.collect()
       
   555 +
       
   556 +
       
   557 +if __name__ == "__main__":
       
   558 +    test_entry_return_and_stack()
       
   559 +    test_line()
       
   560 +    test_unicode_entry_return_and_stack()
       
   561 +    test_instance_creation_destruction()
       
   562 +    test_garbage_collection()
       
   563 +
       
   564 --- /dev/null
       
   565 +++ Python-3.4.0/Lib/test/test_dtrace.py
       
   566 @@ -0,0 +1,447 @@
       
   567 +import sys, unittest, subprocess, os.path, dis, types, re
       
   568 +import dtrace
       
   569 +from test.support import TESTFN, run_unittest, findfile
       
   570 +
       
   571 +sample = os.path.abspath(findfile("dtrace_sample.py"))
       
   572 +if not dtrace.available :
       
   573 +    raise unittest.SkipTest("dtrace support not compiled in")
       
   574 +
       
   575 +def normalize(data) :
       
   576 +    # DTRACE keeps a per-CPU buffer, and when showing the fired probes,
       
   577 +    # buffers are concatenated. So if the operating system moves our
       
   578 +    # thread around, the straight result can be "non causal".
       
   579 +    # So we add timestamps to the probe firing, and sort by that field.
       
   580 +
       
   581 +    result = data if isinstance(data, str) else data.decode("ascii")
       
   582 +    # When compiling with '--with-pydebug'
       
   583 +    result = "".join(re.split("\[[0-9]+ refs\]", result))
       
   584 +
       
   585 +    try :
       
   586 +        result = [i.split("\t") \
       
   587 +                for i in result.replace("\r", "").split("\n") if len(i)]
       
   588 +        result.sort(key = lambda i: int(i[0]))
       
   589 +        result = "".join((i[1] for i in result))
       
   590 +        result = result.replace(" ", "")
       
   591 +    except :
       
   592 +        # If something goes wrong, rebuild the value so we can see the
       
   593 +        # real result when the assert fails.
       
   594 +        result = data if isinstance(data, str) else data.decode("ascii")
       
   595 +        result = result.replace("\r", "").replace("\n", "")
       
   596 +    return result
       
   597 +
       
   598 +dscript = """
       
   599 +pid$target::PyEval_EvalCode:entry
       
   600 +"""
       
   601 +dscript = dscript.replace("\r", "").replace("\n", "")
       
   602 +result, _ = subprocess.Popen(["dtrace", "-q", "-l", "-n", dscript,
       
   603 +    "-c", "%s %s" %(sys.executable, sample)], stdout=subprocess.PIPE,
       
   604 +    stderr=subprocess.STDOUT).communicate()
       
   605 +if result.decode("ascii").split("\n")[1].split()[-2:] != \
       
   606 +        ["PyEval_EvalCode", "entry"] :
       
   607 +    result2 = repr(result)
       
   608 +    raise unittest.SkipTest("dtrace seems not to be working. " + \
       
   609 +        "Please, check your privileges. " +
       
   610 +        "Result: " +result2)
       
   611 +
       
   612 +class DTraceTestsNormal(unittest.TestCase) :
       
   613 +    def setUp(self) :
       
   614 +        self.optimize = False
       
   615 +
       
   616 +    def test_function_entry_return(self) :
       
   617 +        dscript = """
       
   618 +python$target:::function-entry
       
   619 +/(copyinstr(arg0)=="%(path)s") &&
       
   620 +(copyinstr(arg1)=="test_entry_return_and_stack")/
       
   621 +{
       
   622 +    self->trace = 1;
       
   623 +}
       
   624 +python$target:::function-entry,python$target:::function-return
       
   625 +/(copyinstr(arg0)=="%(path)s") && (self->trace)/
       
   626 +{
       
   627 +    printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp,
       
   628 +        probename, copyinstr(arg0),
       
   629 +        copyinstr(arg1), arg2);
       
   630 +}
       
   631 +python$target:::function-return
       
   632 +/(copyinstr(arg0)=="%(path)s") &&
       
   633 +(copyinstr(arg1)=="test_entry_return_and_stack")/
       
   634 +{
       
   635 +    self->trace = 0;
       
   636 +}
       
   637 +""" %{"path":sample}
       
   638 +
       
   639 +        dscript = dscript.replace("\r", "").replace("\n", "")
       
   640 +        expected_result = """
       
   641 +        **function-entry*%(path)s*test_entry_return_and_stack*25
       
   642 +        **function-entry*%(path)s*function_1*6
       
   643 +        **function-return*%(path)s*function_1*7
       
   644 +        **function-entry*%(path)s*function_2*10
       
   645 +        **function-entry*%(path)s*function_1*6
       
   646 +        **function-return*%(path)s*function_1*7
       
   647 +        **function-return*%(path)s*function_2*11
       
   648 +        **function-entry*%(path)s*function_3*14
       
   649 +        **function-return*%(path)s*function_3*15
       
   650 +        **function-entry*%(path)s*function_4*18
       
   651 +        **function-return*%(path)s*function_4*19
       
   652 +        **function-entry*%(path)s*function_5*22
       
   653 +        **function-return*%(path)s*function_5*23
       
   654 +        **function-return*%(path)s*test_entry_return_and_stack*30
       
   655 +        """ %{"path":sample}
       
   656 +
       
   657 +        command = "%s %s" %(sys.executable, sample)
       
   658 +        if self.optimize :
       
   659 +            command = "%s -OO %s" %(sys.executable, sample)
       
   660 +        actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
       
   661 +            dscript,
       
   662 +            "-c", command],
       
   663 +                stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
       
   664 +
       
   665 +        actual_result = normalize(actual_result)
       
   666 +        expected_result = expected_result.replace("\r", "").replace("\n",
       
   667 +                "").replace(" ", "")
       
   668 +        self.assertEqual(actual_result, expected_result)
       
   669 +
       
   670 +    @unittest.skipIf(sys.platform == 'darwin',
       
   671 +        "MacOS X doesn't support jstack()")
       
   672 +    def test_stack(self) :
       
   673 +        dscript = """
       
   674 +python$target:::function-entry
       
   675 +/(copyinstr(arg0)=="%(path)s") &&
       
   676 +(copyinstr(arg1)=="test_entry_return_and_stack")/
       
   677 +{
       
   678 +    self->trace = 1;
       
   679 +}
       
   680 +python$target:::function-entry
       
   681 +/(copyinstr(arg0)=="%(path)s") && (self->trace)/
       
   682 +{
       
   683 +    printf("[x]");
       
   684 +    jstack();
       
   685 +}
       
   686 +python$target:::function-return
       
   687 +/(copyinstr(arg0)=="%(path)s") &&
       
   688 +(copyinstr(arg1)=="test_entry_return_and_stack")/
       
   689 +{
       
   690 +    self->trace = 0;
       
   691 +}
       
   692 +""" %{"path":sample}
       
   693 +
       
   694 +        dscript = dscript.replace("\r", "").replace("\n", "")
       
   695 +        expected_result = """
       
   696 +        [x]
       
   697 +        [%(path)s:25(test_entry_return_and_stack)]
       
   698 +        [x]
       
   699 +        [%(path)s:6(function_1)]
       
   700 +        [%(path)s:26(test_entry_return_and_stack)]
       
   701 +        [x]
       
   702 +        [%(path)s:10(function_2)]
       
   703 +        [%(path)s:27(test_entry_return_and_stack)]
       
   704 +        [x]
       
   705 +        [%(path)s:6(function_1)]
       
   706 +        [%(path)s:11(function_2)]
       
   707 +        [%(path)s:27(test_entry_return_and_stack)]
       
   708 +        [x]
       
   709 +        [%(path)s:14(function_3)]
       
   710 +        [%(path)s:28(test_entry_return_and_stack)]
       
   711 +        [x]
       
   712 +        [%(path)s:18(function_4)]
       
   713 +        [%(path)s:29(test_entry_return_and_stack)]
       
   714 +        [x]
       
   715 +        [%(path)s:22(function_5)]
       
   716 +        [%(path)s:30(test_entry_return_and_stack)]
       
   717 +        """ %{"path":sample}
       
   718 +
       
   719 +        command = "%s %s" %(sys.executable, sample)
       
   720 +        if self.optimize :
       
   721 +            command = "%s -OO %s" %(sys.executable, sample)
       
   722 +        actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
       
   723 +            dscript,
       
   724 +            "-c", command],
       
   725 +                stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
       
   726 +
       
   727 +        actual_result = actual_result.decode("ascii")
       
   728 +        # When compiling with '--with-pydebug'
       
   729 +        actual_result = "".join(re.split("\[[0-9]+ refs\]", actual_result))
       
   730 +
       
   731 +        actual_result = [i for i in actual_result.split("\n") \
       
   732 +                if (("[" in i) and not i.endswith(" (<module>) ]"))]
       
   733 +        actual_result = "".join(actual_result)
       
   734 +        actual_result = actual_result.replace("\r", "").replace("\n",
       
   735 +                "").replace(" ", "")
       
   736 +        expected_result = expected_result.replace("\r", "").replace("\n",
       
   737 +                "").replace(" ", "")
       
   738 +        self.assertEqual(actual_result, expected_result)
       
   739 +
       
   740 +    def test_garbage_collection(self) :
       
   741 +        dscript = """
       
   742 +python$target:::gc-start,python$target:::gc-done
       
   743 +{
       
   744 +    printf("%d\t**%s(%ld)\\n", timestamp, probename, arg0);
       
   745 +}
       
   746 +"""
       
   747 +
       
   748 +        dscript = dscript.replace("\r", "").replace("\n", "")
       
   749 +        command = "%s %s" %(sys.executable, sample)
       
   750 +        if self.optimize :
       
   751 +            command = "%s -OO %s" %(sys.executable, sample)
       
   752 +        actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
       
   753 +            dscript,
       
   754 +            "-c", command],
       
   755 +                stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
       
   756 +
       
   757 +        actual_result = normalize(actual_result)
       
   758 +        for i in range(10) :
       
   759 +            actual_result = actual_result.replace(str(i), "")
       
   760 +        expected_result = "**gc-start()**gc-done()" * \
       
   761 +            actual_result.count("**gc-start()**")
       
   762 +
       
   763 +        self.assertEqual(actual_result, expected_result)
       
   764 +
       
   765 +    def test_verify_opcodes(self) :
       
   766 +        # Verify that we are checking:
       
   767 +        opcodes = set(["CALL_FUNCTION", "CALL_FUNCTION_VAR",
       
   768 +            "CALL_FUNCTION_KW", "CALL_FUNCTION_VAR_KW"])
       
   769 +        with open(sample, encoding="utf-8") as f :
       
   770 +            obj = compile(f.read(), "sample", "exec")
       
   771 +        class dump() :
       
   772 +            def __init__(self) :
       
   773 +                self.buf = []
       
   774 +            def write(self, v) :
       
   775 +                self.buf.append(v)
       
   776 +
       
   777 +        dump = dump()
       
   778 +        stdout = sys.stdout
       
   779 +        sys.stdout = dump
       
   780 +        for i in obj.co_consts :
       
   781 +            if isinstance(i, types.CodeType) and \
       
   782 +                (i.co_name == 'test_entry_return_and_stack') :
       
   783 +                dis.dis(i)
       
   784 +        sys.stdout = stdout
       
   785 +        dump = "\n".join(dump.buf)
       
   786 +        dump = dump.replace("\r", "").replace("\n", "").split()
       
   787 +        for i in dump :
       
   788 +            opcodes.discard(i)
       
   789 +        # Are we verifying all the relevant opcodes?
       
   790 +        self.assertEqual(set(), opcodes)  # Are we verifying all opcodes?
       
   791 +
       
   792 +    def test_line(self) :
       
   793 +        dscript = """
       
   794 +python$target:::line
       
   795 +/(copyinstr(arg0)=="%(path)s") &&
       
   796 +(copyinstr(arg1)=="test_line")/
       
   797 +{
       
   798 +    printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp,
       
   799 +        probename, copyinstr(arg0),
       
   800 +        copyinstr(arg1), arg2);
       
   801 +}
       
   802 +""" %{"path":sample}
       
   803 +
       
   804 +        dscript = dscript.replace("\r", "").replace("\n", "")
       
   805 +        expected_result = """
       
   806 +        **line*%(path)s*test_line*33
       
   807 +        **line*%(path)s*test_line*34
       
   808 +        **line*%(path)s*test_line*35
       
   809 +        **line*%(path)s*test_line*36
       
   810 +        **line*%(path)s*test_line*37
       
   811 +        **line*%(path)s*test_line*38
       
   812 +        **line*%(path)s*test_line*34
       
   813 +        **line*%(path)s*test_line*35
       
   814 +        **line*%(path)s*test_line*36
       
   815 +        **line*%(path)s*test_line*37
       
   816 +        **line*%(path)s*test_line*38
       
   817 +        **line*%(path)s*test_line*34
       
   818 +        **line*%(path)s*test_line*39
       
   819 +        """ %{"path":sample}
       
   820 +
       
   821 +        command = "%s %s" %(sys.executable, sample)
       
   822 +        if self.optimize :
       
   823 +            command = "%s -OO %s" %(sys.executable, sample)
       
   824 +        actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
       
   825 +            dscript,
       
   826 +            "-c", command],
       
   827 +                stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
       
   828 +
       
   829 +        actual_result = normalize(actual_result)
       
   830 +        expected_result = expected_result.replace("\r", "").replace("\n",
       
   831 +                "").replace(" ", "")
       
   832 +        self.assertEqual(actual_result, expected_result)
       
   833 +
       
   834 +    def test_instance_creation_destruction(self) :
       
   835 +        dscript = """
       
   836 +python$target:::function-entry
       
   837 +/(copyinstr(arg0)=="%(path)s") &&
       
   838 +(copyinstr(arg1)=="test_instance_creation_destruction")/
       
   839 +{
       
   840 +    self->trace = 1;
       
   841 +}
       
   842 +
       
   843 +python$target:::instance-new-start,
       
   844 +python$target:::instance-new-done,
       
   845 +python$target:::instance-delete-start,
       
   846 +python$target:::instance-delete-done
       
   847 +/self->trace/
       
   848 +{
       
   849 +    printf("%%d\t**%%s* (%%s.%%s)\\n", timestamp,
       
   850 +        probename, copyinstr(arg1), copyinstr(arg0));
       
   851 +}
       
   852 +
       
   853 +python$target:::function-return
       
   854 +/(copyinstr(arg0)=="%(path)s") &&
       
   855 +(copyinstr(arg1)=="test_instance_creation_destruction")/
       
   856 +{
       
   857 +    self->trace = 0;
       
   858 +}
       
   859 +""" %{"path":sample}
       
   860 +
       
   861 +        dscript = dscript.replace("\r", "").replace("\n", "")
       
   862 +        expected_result = """
       
   863 +        **instance-new-start*(__main__.old_style_class)
       
   864 +        **instance-new-done*(__main__.old_style_class)
       
   865 +        **instance-delete-start*(__main__.old_style_class)
       
   866 +        **instance-delete-done*(__main__.old_style_class)
       
   867 +        **instance-new-start*(__main__.new_style_class)
       
   868 +        **instance-new-done*(__main__.new_style_class)
       
   869 +        **instance-delete-start*(__main__.new_style_class)
       
   870 +        **instance-delete-done*(__main__.new_style_class)
       
   871 +        **instance-new-start*(__main__.old_style_class)
       
   872 +        **instance-new-done*(__main__.old_style_class)
       
   873 +        **instance-new-start*(__main__.new_style_class)
       
   874 +        **instance-new-done*(__main__.new_style_class)
       
   875 +        **instance-delete-start*(__main__.old_style_class)
       
   876 +        **instance-delete-done*(__main__.old_style_class)
       
   877 +        **instance-delete-start*(__main__.new_style_class)
       
   878 +        **instance-delete-done*(__main__.new_style_class)
       
   879 +        """
       
   880 +
       
   881 +        command = "%s %s" %(sys.executable, sample)
       
   882 +        if self.optimize :
       
   883 +            command = "%s -OO %s" %(sys.executable, sample)
       
   884 +        actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
       
   885 +            dscript,
       
   886 +            "-c", command],
       
   887 +                stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
       
   888 +
       
   889 +        actual_result = normalize(actual_result)
       
   890 +        expected_result = expected_result.replace("\r", "").replace("\n",
       
   891 +                "").replace(" ", "")
       
   892 +        self.assertEqual(actual_result, expected_result)
       
   893 +
       
   894 +    def test_unicode_function_entry_return(self) :
       
   895 +        dscript = """
       
   896 +python$target:::function-entry
       
   897 +/(copyinstr(arg0)=="%(path)s") &&
       
   898 +(copyinstr(arg1)=="test_unicode_entry_return_and_stack")/
       
   899 +{
       
   900 +    self->trace = 1;
       
   901 +}
       
   902 +python$target:::function-entry,python$target:::function-return
       
   903 +/(copyinstr(arg0)=="%(path)s") && (self->trace)/
       
   904 +{
       
   905 +    printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp,
       
   906 +        probename, copyinstr(arg0),
       
   907 +        copyinstr(arg1), arg2);
       
   908 +}
       
   909 +python$target:::function-return
       
   910 +/(copyinstr(arg0)=="%(path)s") &&
       
   911 +(copyinstr(arg1)=="test_unicode_entry_return_and_stack")/
       
   912 +{
       
   913 +    self->trace = 0;
       
   914 +}
       
   915 +""" %{"path":sample}
       
   916 +
       
   917 +        dscript = dscript.replace("\r", "").replace("\n", "")
       
   918 +        expected_result = """
       
   919 +        **function-entry*%(path)s*test_unicode_entry_return_and_stack*41
       
   920 +        **function-entry*%(path)s*únícódé*42
       
   921 +        **function-return*%(path)s*únícódé*43
       
   922 +        **function-return*%(path)s*test_unicode_entry_return_and_stack*44
       
   923 +        """ %{"path":sample}
       
   924 +
       
   925 +        command = "%s %s" %(sys.executable, sample)
       
   926 +        if self.optimize :
       
   927 +            command = "%s -OO %s" %(sys.executable, sample)
       
   928 +        actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
       
   929 +            dscript,
       
   930 +            "-c", command],
       
   931 +                stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
       
   932 +
       
   933 +        actual_result = actual_result.decode("utf8")
       
   934 +        actual_result = normalize(actual_result)
       
   935 +        expected_result = expected_result.replace("\r", "").replace("\n",
       
   936 +                "").replace(" ", "")
       
   937 +        self.assertEqual(actual_result, expected_result)
       
   938 +
       
   939 +    @unittest.skipIf(sys.platform == 'darwin',
       
   940 +        "MacOS X doesn't support jstack()")
       
   941 +    def test_unicode_stack(self) :
       
   942 +        dscript = """
       
   943 +python$target:::function-entry
       
   944 +/(copyinstr(arg0)=="%(path)s") &&
       
   945 +(copyinstr(arg1)=="test_unicode_entry_return_and_stack")/
       
   946 +{
       
   947 +    self->trace = 1;
       
   948 +}
       
   949 +python$target:::function-entry
       
   950 +/(copyinstr(arg0)=="%(path)s") && (self->trace)/
       
   951 +{
       
   952 +    printf("[x]");
       
   953 +    jstack();
       
   954 +}
       
   955 +python$target:::function-return
       
   956 +/(copyinstr(arg0)=="%(path)s") &&
       
   957 +(copyinstr(arg1)=="test_unicode_entry_return_and_stack")/
       
   958 +{
       
   959 +    self->trace = 0;
       
   960 +}
       
   961 +""" %{"path":sample}
       
   962 +
       
   963 +        dscript = dscript.replace("\r", "").replace("\n", "")
       
   964 +        expected_result = """
       
   965 +        [x]
       
   966 +        [%(path)s:41(test_unicode_entry_return_and_stack)]
       
   967 +        [x]
       
   968 +        [%(path)s:42(únícódé)]
       
   969 +        [%(path)s:44(test_unicode_entry_return_and_stack)]
       
   970 +        """ %{"path":sample}
       
   971 +
       
   972 +        command = "%s %s" %(sys.executable, sample)
       
   973 +        if self.optimize :
       
   974 +            command = "%s -OO %s" %(sys.executable, sample)
       
   975 +        actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
       
   976 +            dscript,
       
   977 +            "-c", command],
       
   978 +                stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
       
   979 +
       
   980 +        actual_result = actual_result.decode("utf8")
       
   981 +        # When compiling with '--with-pydebug'
       
   982 +        actual_result = "".join(re.split("\[[0-9]+ refs\]", actual_result))
       
   983 +
       
   984 +        actual_result = [i for i in actual_result.split("\n") \
       
   985 +                if (("[" in i) and not i.endswith(" (<module>) ]"))]
       
   986 +        actual_result = "".join(actual_result)
       
   987 +        actual_result = actual_result.replace("\r", "").replace("\n",
       
   988 +                "").replace(" ", "")
       
   989 +        expected_result = expected_result.replace("\r", "").replace("\n",
       
   990 +                "").replace(" ", "")
       
   991 +        self.assertEqual(actual_result, expected_result)
       
   992 +
       
   993 +
       
   994 +
       
   995 +# This class try to verify that dtrace probes
       
   996 +# are still working with optimizations enabled in the bytecode.
       
   997 +#
       
   998 +# Some tests will not actually verify it. For instance,
       
   999 +# source code compilation follows optimization status of
       
  1000 +# current working Python. So, you should run the test
       
  1001 +# both with an optimizing and a non optimizing Python.
       
  1002 +class DTraceTestsOptimize(DTraceTestsNormal) :
       
  1003 +    def setUp(self) :
       
  1004 +        self.optimize = True
       
  1005 +
       
  1006 +
       
  1007 +def test_main():
       
  1008 +    run_unittest(DTraceTestsNormal)
       
  1009 +    run_unittest(DTraceTestsOptimize)
       
  1010 +
       
  1011 +if __name__ == '__main__':
       
  1012 +    test_main()
       
  1013 +
       
  1014 --- Python-3.5.0a4/Lib/test/test_sys.py.~1~	2015-04-20 00:37:52.000000000 -0700
       
  1015 +++ Python-3.5.0a4/Lib/test/test_sys.py	2015-04-20 12:38:22.235939749 -0700
       
  1016 @@ -829,6 +829,7 @@
       
  1017          self.assertEqual(sys.getsizeof(True, -1), size('') + self.longdigit)
       
  1018  
       
  1019      def test_objecttypes(self):
       
  1020 +        import dtrace
       
  1021          # check all types defined in Objects/
       
  1022          size = test.support.calcobjsize
       
  1023          vsize = test.support.calcvobjsize
       
  1024 @@ -857,13 +858,17 @@
       
  1025              return inner
       
  1026          check(get_cell().__closure__[0], size('P'))
       
  1027          # code
       
  1028 -        check(get_cell().__code__, size('5i9Pi3P'))
       
  1029 -        check(get_cell.__code__, size('5i9Pi3P'))
       
  1030 +        if dtrace.available :
       
  1031 +            code = '5i9PiPH2P'
       
  1032 +        else :
       
  1033 +            code = '5i9Pi3P'
       
  1034 +        check(get_cell().__code__, size(code))
       
  1035 +        check(get_cell.__code__, size(code))
       
  1036          def get_cell2(x):
       
  1037              def inner():
       
  1038                  return x
       
  1039              return inner
       
  1040 -        check(get_cell2.__code__, size('5i9Pi3P') + 1)
       
  1041 +        check(get_cell2.__code__, size(code) + 1)
       
  1042          # complex
       
  1043          check(complex(0,1), size('2d'))
       
  1044          # method_descriptor (descriptor object)
       
  1045 --- Python-3.5.0rc2/Makefile.pre.in.~1~	2015-08-25 10:19:13.000000000 -0700
       
  1046 +++ Python-3.5.0rc2/Makefile.pre.in	2015-09-02 11:27:31.510492090 -0700
       
  1047 @@ -52,6 +52,13 @@
       
  1048  # Use this to make a link between python$(VERSION) and python in $(BINDIR)
       
  1049  LN=		@LN@
       
  1050  
       
  1051 +DTRACE=         @DTRACE@
       
  1052 +DFLAGS=         @DFLAGS@
       
  1053 +DTRACEOBJS=     @DTRACEOBJS@
       
  1054 +DTRACE_NM=      @DTRACE_NM@
       
  1055 +DTRACE_LINKER=  @DTRACE_LINKER@
       
  1056 +
       
  1057 +
       
  1058  # Portable install script (configure doesn't always guess right)
       
  1059  INSTALL=	@INSTALL@
       
  1060  INSTALL_PROGRAM=@INSTALL_PROGRAM@
       
  1061 @@ -596,7 +603,7 @@
       
  1062  	$(AR) $(ARFLAGS) $@ $(MODOBJS)
       
  1063  	$(RANLIB) $@
       
  1064  
       
  1065 -libpython$(LDVERSION).so: $(LIBRARY_OBJS)
       
  1066 +libpython$(LDVERSION).so: $(LIBRARY_OBJS) $(DTRACEOBJS)
       
  1067  	if test $(INSTSONAME) != $(LDLIBRARY); then \
       
  1068  		$(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \
       
  1069  		$(LN) -f $(INSTSONAME) $@; \
       
  1070 @@ -607,9 +614,8 @@
       
  1071  libpython3.so:	libpython$(LDVERSION).so
       
  1072  	$(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^
       
  1073  
       
  1074 -libpython$(LDVERSION).dylib: $(LIBRARY_OBJS)
       
  1075 -	 $(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); \
       
  1076 -
       
  1077 +libpython$(LDVERSION).dylib: $(LIBRARY_OBJS) $(DTRACEOBJS)
       
  1078 +	 $(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)
       
  1079  
       
  1080  libpython$(VERSION).sl: $(LIBRARY_OBJS)
       
  1081  	$(LDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST)
       
  1082 @@ -714,12 +720,18 @@
       
  1083  		$(MODULE_OBJS) \
       
  1084  		$(SIGNAL_OBJS) \
       
  1085  		$(MODOBJS) \
       
  1086 +		$(DTRACEOBJS) \
       
  1087  		$(srcdir)/Modules/getbuildinfo.c
       
  1088  	$(CC) -c $(PY_CORE_CFLAGS) \
       
  1089  	      -DHGVERSION="\"`LC_ALL=C $(HGVERSION)`\"" \
       
  1090  	      -DHGTAG="\"`LC_ALL=C $(HGTAG)`\"" \
       
  1091  	      -DHGBRANCH="\"`LC_ALL=C $(HGBRANCH)`\"" \
       
  1092  	      -o $@ $(srcdir)/Modules/getbuildinfo.c
       
  1093 +	if test "$(DTRACEOBJS)" != "" ; then \
       
  1094 +		$(DTRACE_LINKER) --relocatable \
       
  1095 +	          $@ $(DTRACEOBJS) -o [email protected] ; \
       
  1096 +		mv [email protected] $@ ; \
       
  1097 +	fi;
       
  1098  
       
  1099  Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile
       
  1100  	$(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \
       
  1101 @@ -853,6 +865,46 @@
       
  1102  Objects/typeslots.inc: $(srcdir)/Include/typeslots.h $(srcdir)/Objects/typeslots.py
       
  1103  	$(PYTHON) $(srcdir)/Objects/typeslots.py < $(srcdir)/Include/typeslots.h > Objects/typeslots.inc
       
  1104  
       
  1105 +$(srcdir)/Include/pydtrace.h: $(srcdir)/Include/pydtrace.d
       
  1106 +	if test "$(DTRACE)" != "" ; then \
       
  1107 +		$(DTRACE) -o $@ $(DFLAGS) \
       
  1108 +			-C -h -s $(srcdir)/Include/pydtrace.d ; \
       
  1109 +	else	touch $@ ; \
       
  1110 +	fi;
       
  1111 +
       
  1112 +$(srcdir)/Include/pydtrace_offsets.h: $(srcdir)/Include/pydtrace_offsets.c Python/ceval.o
       
  1113 +	$(CC) $(PY_CORE_CFLAGS) -o $(srcdir)/Include/pydtrace_offsets \
       
  1114 +	       	$(srcdir)/Include/pydtrace_offsets.c
       
  1115 +	$(srcdir)/Include/pydtrace_offsets.sh $(DTRACE_NM) \
       
  1116 +		Python/ceval.o $(srcdir)/Include/pydtrace_offsets > \
       
  1117 +		$(srcdir)/Include/pydtrace_offsets.h
       
  1118 +
       
  1119 +Python/ceval.o: Include/pydtrace.h
       
  1120 +Modules/gcmodule.o: Include/pydtrace.h
       
  1121 +Objects/typeobject.o: Include/pydtrace.h
       
  1122 +
       
  1123 +Python/pydtrace.o: $(srcdir)/Include/pydtrace.d $(srcdir)/Include/pydtrace_offsets.h \
       
  1124 +			Python/ceval.o Modules/gcmodule.o Objects/typeobject.o
       
  1125 +	# We do the "touch" game to break a circular dependency between
       
  1126 +	# "Python/ceval.o" and "Include/pydtrace_offsets.h".
       
  1127 +	if test "$(DTRACE)" != "" ; then \
       
  1128 +		touch -r Python/ceval.o Python/ceval.o.ts_dtrace ; \
       
  1129 +		touch -r Modules/gcmodule.o Modules/gcmodule.o.ts_dtrace ; \
       
  1130 +		touch -r Objects/typeobject.o Objects/typeobject.o.ts_dtrace ; \
       
  1131 +		$(DTRACE) -o $@ -DPYDTRACE_STACK_HELPER \
       
  1132 +			$(DFLAGS) $(PY_CPPFLAGS) \
       
  1133 +			-C -G -s $(srcdir)/Include/pydtrace.d \
       
  1134 +				Python/ceval.o Modules/gcmodule.o \
       
  1135 +				Objects/typeobject.o; \
       
  1136 +		touch -r Python/ceval.o.ts_dtrace Python/ceval.o ; \
       
  1137 +		touch -r Modules/gcmodule.o.ts_dtrace Modules/gcmodule.o ; \
       
  1138 +		touch -r Objects/typeobject.o.ts_dtrace Objects/typeobject.o ; \
       
  1139 +		rm Python/ceval.o.ts_dtrace ; \
       
  1140 +		rm Modules/gcmodule.o.ts_dtrace ; \
       
  1141 +		rm Objects/typeobject.o.ts_dtrace ; \
       
  1142 +	else    touch $@ ; \
       
  1143 +	fi;
       
  1144 +
       
  1145  ############################################################################
       
  1146  # Header files
       
  1147  
       
  1148 @@ -1567,6 +1619,11 @@
       
  1149  	find build -name '*.py[co]' -exec rm -f {} ';' || true
       
  1150  	-rm -f pybuilddir.txt
       
  1151  	-rm -f Lib/lib2to3/*Grammar*.pickle
       
  1152 +	rm -f Include/pydtrace.h
       
  1153 +	rm -f Include/pydtrace_offsets Include/pydtrace_offsets.h
       
  1154 +	rm -f Python/ceval.o.ts_dtrace
       
  1155 +	rm -f Modules/gcmodule.o.ts_dtrace
       
  1156 +	rm -f Objects/typeobject.o.ts_dtrace
       
  1157  	-rm -f Programs/_testembed Programs/_freeze_importlib
       
  1158  
       
  1159  profile-removal:
       
  1160 @@ -1598,6 +1655,11 @@
       
  1161  				     -o -name '*.orig' -o -name '*.rej' \
       
  1162  				     -o -name '*.bak' ')' \
       
  1163  				     -exec rm -f {} ';'
       
  1164 +	rm -f Include/pydtrace.h
       
  1165 +	rm -f Include/pydtrace_offsets Include/pydtrace_offsets.h
       
  1166 +	rm -f Python/ceval.o.ts_dtrace
       
  1167 +	rm -f Modules/gcmodule.o.ts_dtrace
       
  1168 +	rm -f Objects/typeobject.o.ts_dtrace
       
  1169  
       
  1170  # Check for smelly exported symbols (not starting with Py/_Py)
       
  1171  smelly: all
       
  1172 --- Python-3.4.0/Modules/Setup.dist
       
  1173 +++ Python-3.4.0/Modules/Setup.dist
       
  1174 @@ -390,3 +390,5 @@
       
  1175  
       
  1176  # Another example -- the 'xxsubtype' module shows C-level subtyping in action
       
  1177  xxsubtype xxsubtype.c
       
  1178 +
       
  1179 +dtrace dtracemodule.c
       
  1180 --- /dev/null
       
  1181 +++ Python-3.4.0/Modules/dtracemodule.c
       
  1182 @@ -0,0 +1,39 @@
       
  1183 +#include "Python.h"
       
  1184 +
       
  1185 +static PyMethodDef dtrace_methods[] = {
       
  1186 +    {NULL,  NULL}   /* sentinel */
       
  1187 +};
       
  1188 +
       
  1189 +
       
  1190 +static struct PyModuleDef dtracemodule = {
       
  1191 +    PyModuleDef_HEAD_INIT,
       
  1192 +    "dtrace",
       
  1193 +    NULL,
       
  1194 +    -1,
       
  1195 +    dtrace_methods,
       
  1196 +    NULL,
       
  1197 +    NULL,
       
  1198 +    NULL,
       
  1199 +    NULL
       
  1200 +};
       
  1201 +
       
  1202 +PyMODINIT_FUNC
       
  1203 +PyInit_dtrace(void)
       
  1204 +{
       
  1205 +    PyObject *m, *v;
       
  1206 +
       
  1207 +    m = PyModule_Create(&dtracemodule);
       
  1208 +    if (m) {
       
  1209 +#ifdef WITH_DTRACE
       
  1210 +        v = Py_True;
       
  1211 +#else
       
  1212 +        v = Py_False;
       
  1213 +#endif
       
  1214 +        Py_INCREF(v);
       
  1215 +        if (PyModule_AddObject(m, "available", v) < 0) {
       
  1216 +            Py_DECREF(m);
       
  1217 +            return NULL;
       
  1218 +        }
       
  1219 +    }
       
  1220 +    return m;
       
  1221 +}
       
  1222 --- Python-3.5.0a4/Modules/gcmodule.c.~1~	2015-04-20 00:37:52.000000000 -0700
       
  1223 +++ Python-3.5.0a4/Modules/gcmodule.c	2015-04-20 12:54:18.784913115 -0700
       
  1224 @@ -27,6 +27,10 @@
       
  1225  #include "frameobject.h"        /* for PyFrame_ClearFreeList */
       
  1226  #include "pytime.h"             /* for _PyTime_GetMonotonicClock() */
       
  1227  
       
  1228 +#ifdef WITH_DTRACE
       
  1229 +#include "pydtrace.h"
       
  1230 +#endif
       
  1231 +
       
  1232  /* Get an object's GC head */
       
  1233  #define AS_GC(o) ((PyGC_Head *)(o)-1)
       
  1234  
       
  1235 @@ -897,7 +901,12 @@
       
  1236  /* This is the main function.  Read this to understand how the
       
  1237   * collection process works. */
       
  1238  static Py_ssize_t
       
  1239 -collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable,
       
  1240 +#ifdef WITH_DTRACE
       
  1241 +collect2
       
  1242 +#else
       
  1243 +collect
       
  1244 +#endif
       
  1245 +(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable,
       
  1246          int nofail)
       
  1247  {
       
  1248      int i;
       
  1249 @@ -1071,6 +1080,50 @@
       
  1250      return n+m;
       
  1251  }
       
  1252  
       
  1253 +#ifdef WITH_DTRACE
       
  1254 +static void
       
  1255 +dtrace_gc_start(int collection)
       
  1256 +{
       
  1257 +    PYTHON_GC_START(collection);
       
  1258 +
       
  1259 +    /*
       
  1260 +     * Currently a USDT tail-call will not receive the correct arguments.
       
  1261 +     * Disable the tail call here.
       
  1262 +     */
       
  1263 +#if defined(__sparc)
       
  1264 +    asm("nop");
       
  1265 +#endif
       
  1266 +}
       
  1267 +
       
  1268 +static void
       
  1269 +dtrace_gc_done(Py_ssize_t value)
       
  1270 +{
       
  1271 +    PYTHON_GC_DONE((long) value);
       
  1272 +
       
  1273 +    /*
       
  1274 +     * Currently a USDT tail-call will not receive the correct arguments.
       
  1275 +     * Disable the tail call here.
       
  1276 +     */
       
  1277 +#if defined(__sparc)
       
  1278 +    asm("nop");
       
  1279 +#endif
       
  1280 +}
       
  1281 +
       
  1282 +static Py_ssize_t
       
  1283 +collect(int collection, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable,
       
  1284 +	int nofail)
       
  1285 +{
       
  1286 +    Py_ssize_t value;
       
  1287 +
       
  1288 +    if (PYTHON_GC_START_ENABLED())
       
  1289 +        dtrace_gc_start(collection);
       
  1290 +    value = collect2(collection, n_collected, n_uncollectable, nofail);
       
  1291 +    if (PYTHON_GC_DONE_ENABLED())
       
  1292 +        dtrace_gc_done(value);
       
  1293 +    return value;
       
  1294 +}
       
  1295 +#endif /* WITH_DTRACE */
       
  1296 +
       
  1297  /* Invoke progress callbacks to notify clients that garbage collection
       
  1298   * is starting or stopping
       
  1299   */
       
  1300 --- Python-3.4.0/Objects/codeobject.c
       
  1301 +++ Python-3.4.0/Objects/codeobject.c
       
  1302 @@ -152,6 +152,37 @@
       
  1303      co->co_lnotab = lnotab;
       
  1304      co->co_zombieframe = NULL;
       
  1305      co->co_weakreflist = NULL;
       
  1306 +
       
  1307 +#ifdef WITH_DTRACE
       
  1308 +    /*
       
  1309 +    ** Cache UTF8 internally, available
       
  1310 +    ** for the pythonframe stack walker.
       
  1311 +    */
       
  1312 +    PyUnicode_AsUTF8(filename);
       
  1313 +    PyUnicode_AsUTF8(name);
       
  1314 +
       
  1315 +    i = PyBytes_Size(co->co_code);
       
  1316 +    co->co_linenos = PyMem_Malloc(sizeof(unsigned short) * i);
       
  1317 +    if (co->co_linenos) {
       
  1318 +        unsigned short *p = (unsigned short *)(co->co_linenos);
       
  1319 +        unsigned char *p2 = (unsigned char*)PyBytes_AsString(co->co_lnotab);
       
  1320 +        int size = PyBytes_Size(co->co_lnotab) / 2;
       
  1321 +        int i2;
       
  1322 +        unsigned short offset = 0;
       
  1323 +
       
  1324 +        while (size) {
       
  1325 +            size -= 1;
       
  1326 +            i2 = *p2++;
       
  1327 +            i-=i2;
       
  1328 +            while (i2--)
       
  1329 +                *p++ = offset;
       
  1330 +            offset += *p2++;
       
  1331 +        }
       
  1332 +        while(i--)
       
  1333 +            *p++ = offset;
       
  1334 +    }
       
  1335 +#endif
       
  1336 +
       
  1337      return co;
       
  1338  }
       
  1339  
       
  1340 --- Python-3.5.0rc2/Objects/frameobject.c.~1~	2015-08-25 10:19:14.000000000 -0700
       
  1341 +++ Python-3.5.0rc2/Objects/frameobject.c	2015-09-02 11:31:53.362348226 -0700
       
  1342 @@ -737,6 +737,15 @@
       
  1343      f->f_executing = 0;
       
  1344      f->f_gen = NULL;
       
  1345  
       
  1346 +#ifdef WITH_DTRACE
       
  1347 +    /*
       
  1348 +    ** Cache UTF8 internally, available
       
  1349 +    ** for the pythonframe stack walker.
       
  1350 +    */
       
  1351 +    PyUnicode_AsUTF8(f->f_code->co_filename);
       
  1352 +    PyUnicode_AsUTF8(f->f_code->co_name);
       
  1353 +#endif
       
  1354 +
       
  1355      _PyObject_GC_TRACK(f);
       
  1356      return f;
       
  1357  }
       
  1358 --- Python-3.5.0a4/Objects/typeobject.c.~1~	2015-04-20 00:37:53.000000000 -0700
       
  1359 +++ Python-3.5.0a4/Objects/typeobject.c	2015-04-20 12:55:28.246913689 -0700
       
  1360 @@ -4,6 +4,10 @@
       
  1361  #include "frameobject.h"
       
  1362  #include "structmember.h"
       
  1363  
       
  1364 +#ifdef WITH_DTRACE
       
  1365 +#include "pydtrace.h"
       
  1366 +#endif
       
  1367 +
       
  1368  #include <ctype.h>
       
  1369  
       
  1370  
       
  1371 @@ -934,8 +938,29 @@
       
  1372  PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
       
  1373  {
       
  1374      PyObject *obj;
       
  1375 -    const size_t size = _PyObject_VAR_SIZE(type, nitems+1);
       
  1376 +    size_t size;
       
  1377 +
       
  1378 +#ifdef WITH_DTRACE
       
  1379 +    PyObject *mod;
       
  1380 +    char *mod_name;
       
  1381 +
       
  1382 +    if (PYTHON_INSTANCE_NEW_START_ENABLED()) {
       
  1383 +        if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
       
  1384 +            mod = PyDict_GetItemString(type->tp_dict, "__module__");
       
  1385 +            if (mod == NULL || !PyUnicode_Check(mod)) {
       
  1386 +                mod_name = "?";
       
  1387 +            } else {
       
  1388 +                mod_name = PyUnicode_AsUTF8(mod);
       
  1389 +                if (!mod_name)
       
  1390 +                    mod_name = "?";
       
  1391 +            }
       
  1392 +            PYTHON_INSTANCE_NEW_START((char *)(type->tp_name), mod_name);
       
  1393 +        }
       
  1394 +    }
       
  1395 +#endif
       
  1396 +
       
  1397      /* note that we need to add one, for the sentinel */
       
  1398 +    size = _PyObject_VAR_SIZE(type, nitems+1);
       
  1399  
       
  1400      if (PyType_IS_GC(type))
       
  1401          obj = _PyObject_GC_Malloc(size);
       
  1402 @@ -957,6 +982,23 @@
       
  1403  
       
  1404      if (PyType_IS_GC(type))
       
  1405          _PyObject_GC_TRACK(obj);
       
  1406 +
       
  1407 +#ifdef WITH_DTRACE
       
  1408 +    if (PYTHON_INSTANCE_NEW_DONE_ENABLED()) {
       
  1409 +        if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
       
  1410 +            mod = PyDict_GetItemString(type->tp_dict, "__module__");
       
  1411 +            if (mod == NULL || !PyUnicode_Check(mod)) {
       
  1412 +                mod_name = "?";
       
  1413 +            } else {
       
  1414 +                mod_name = PyUnicode_AsUTF8(mod);
       
  1415 +                if (!mod_name)
       
  1416 +                    mod_name = "?";
       
  1417 +            }
       
  1418 +            PYTHON_INSTANCE_NEW_DONE((char *)(type->tp_name), mod_name);
       
  1419 +        }
       
  1420 +    }
       
  1421 +#endif
       
  1422 +
       
  1423      return obj;
       
  1424  }
       
  1425  
       
  1426 @@ -1077,9 +1119,56 @@
       
  1427      return 0;
       
  1428  }
       
  1429  
       
  1430 +#ifdef WITH_DTRACE
       
  1431 +static void subtype_dealloc2(PyObject *);  /* Forward declaration */
       
  1432 +
       
  1433  static void
       
  1434  subtype_dealloc(PyObject *self)
       
  1435  {
       
  1436 +    PyObject *mod;
       
  1437 +    char *mod_name;
       
  1438 +    PyTypeObject *type;
       
  1439 +
       
  1440 +    type = Py_TYPE(self);
       
  1441 +    Py_INCREF(type);
       
  1442 +
       
  1443 +    if (PYTHON_INSTANCE_DELETE_START_ENABLED()) {
       
  1444 +        mod = PyDict_GetItemString(type->tp_dict, "__module__");
       
  1445 +        if (mod == NULL || !PyUnicode_Check(mod)) {
       
  1446 +            mod_name = "?";
       
  1447 +        } else {
       
  1448 +            mod_name = PyUnicode_AsUTF8(mod);
       
  1449 +            if (!mod_name)
       
  1450 +                mod_name = "?";
       
  1451 +        }
       
  1452 +        PYTHON_INSTANCE_DELETE_START((char *)(type->tp_name), mod_name);
       
  1453 +    }
       
  1454 +
       
  1455 +    subtype_dealloc2(self);
       
  1456 +
       
  1457 +    if (PYTHON_INSTANCE_DELETE_DONE_ENABLED()) {
       
  1458 +        mod = PyDict_GetItemString(type->tp_dict, "__module__");
       
  1459 +        if (mod == NULL || !PyUnicode_Check(mod)) {
       
  1460 +            mod_name = "?";
       
  1461 +        } else {
       
  1462 +            mod_name = PyUnicode_AsUTF8(mod);
       
  1463 +            if (!mod_name)
       
  1464 +                mod_name = "?";
       
  1465 +        }
       
  1466 +        PYTHON_INSTANCE_DELETE_DONE((char *)(type->tp_name), mod_name);
       
  1467 +    }
       
  1468 +    Py_DECREF(type);
       
  1469 +}
       
  1470 +#endif
       
  1471 +
       
  1472 +static void
       
  1473 +#ifdef WITH_DTRACE
       
  1474 +subtype_dealloc2
       
  1475 +#else
       
  1476 +subtype_dealloc
       
  1477 +#endif
       
  1478 +(PyObject *self)
       
  1479 +{
       
  1480      PyTypeObject *type, *base;
       
  1481      destructor basedealloc;
       
  1482      PyThreadState *tstate = PyThreadState_GET();
       
  1483 --- Python-3.5.0rc2/Python/ceval.c.~1~	2015-08-25 10:19:14.000000000 -0700
       
  1484 +++ Python-3.5.0rc2/Python/ceval.c	2015-09-02 11:33:12.745496843 -0700
       
  1485 @@ -20,6 +20,13 @@
       
  1486  
       
  1487  #include <ctype.h>
       
  1488  
       
  1489 +#ifdef WITH_DTRACE
       
  1490 +#include "pydtrace.h"
       
  1491 +#else
       
  1492 +/* We can not have conditional compilation inside macros */
       
  1493 +#define PYTHON_LINE_ENABLED() (0)
       
  1494 +#endif
       
  1495 +
       
  1496  #ifndef WITH_TSC
       
  1497  
       
  1498  #define READ_TIMESTAMP(var)
       
  1499 @@ -123,6 +130,12 @@
       
  1500  #define CALL_FLAG_VAR 1
       
  1501  #define CALL_FLAG_KW 2
       
  1502  
       
  1503 +#ifdef WITH_DTRACE
       
  1504 +static void maybe_dtrace_line(PyFrameObject *frame,
       
  1505 +                              int *instr_lb, int *instr_ub,
       
  1506 +                              int *instr_prev);
       
  1507 +#endif
       
  1508 +
       
  1509  #ifdef LLTRACE
       
  1510  static int lltrace;
       
  1511  static int prtrace(PyObject *, char *);
       
  1512 @@ -782,6 +795,49 @@
       
  1513                        NULL, NULL);
       
  1514  }
       
  1515  
       
  1516 +#ifdef WITH_DTRACE
       
  1517 +static void
       
  1518 +dtrace_entry(PyFrameObject *f)
       
  1519 +{
       
  1520 +    char *filename;
       
  1521 +    char *name;
       
  1522 +    int lineno;
       
  1523 +
       
  1524 +    filename = PyUnicode_AsUTF8(f->f_code->co_filename);
       
  1525 +    name = PyUnicode_AsUTF8(f->f_code->co_name);
       
  1526 +    lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
       
  1527 +    PYTHON_FUNCTION_ENTRY(filename, name, lineno);
       
  1528 +
       
  1529 +    /*
       
  1530 +     * Currently a USDT tail-call will not receive the correct arguments.
       
  1531 +     * Disable the tail call here.
       
  1532 +     */
       
  1533 +#if defined(__sparc)
       
  1534 +    asm("nop");
       
  1535 +#endif
       
  1536 +}
       
  1537 +
       
  1538 +static void
       
  1539 +dtrace_return(PyFrameObject *f)
       
  1540 +{
       
  1541 +    char *filename;
       
  1542 +    char *name;
       
  1543 +    int lineno;
       
  1544 +
       
  1545 +    filename = PyUnicode_AsUTF8(f->f_code->co_filename);
       
  1546 +    name = PyUnicode_AsUTF8(f->f_code->co_name);
       
  1547 +    lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
       
  1548 +    PYTHON_FUNCTION_RETURN(filename, name, lineno);
       
  1549 +
       
  1550 +    /*
       
  1551 +     * Currently a USDT tail-call will not receive the correct arguments.
       
  1552 +     * Disable the tail call here.
       
  1553 +     */
       
  1554 +#if defined(__sparc)
       
  1555 +    asm("nop");
       
  1556 +#endif
       
  1557 +}
       
  1558 +#endif
       
  1559  
       
  1560  /* Interpreter main loop */
       
  1561  
       
  1562 @@ -793,8 +849,16 @@
       
  1563      return PyEval_EvalFrameEx(f, 0);
       
  1564  }
       
  1565  
       
  1566 +
       
  1567  PyObject *
       
  1568 +#if defined(WITH_DTRACE) && defined(__amd64)
       
  1569 +PyEval_EvalFrameExReal(long a1, long a2, long a3, long a4, long a5, long a6,
       
  1570 +    PyFrameObject *f, int throwflag)
       
  1571 +#elif defined(WITH_DTRACE) && defined(__sparc)
       
  1572 +PyEval_EvalFrameExReal(PyFrameObject *f, int throwflag)
       
  1573 +#else
       
  1574  PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
       
  1575 +#endif
       
  1576  {
       
  1577  #ifdef DXPAIRS
       
  1578      int lastopcode = 0;
       
  1579 @@ -915,7 +979,7 @@
       
  1580  #ifdef LLTRACE
       
  1581  #define FAST_DISPATCH() \
       
  1582      { \
       
  1583 -        if (!lltrace && !_Py_TracingPossible) { \
       
  1584 +        if (!lltrace && !_Py_TracingPossible && !PYTHON_LINE_ENABLED()) { \
       
  1585              f->f_lasti = INSTR_OFFSET(); \
       
  1586              goto *opcode_targets[*next_instr++]; \
       
  1587          } \
       
  1588 @@ -924,7 +988,7 @@
       
  1589  #else
       
  1590  #define FAST_DISPATCH() \
       
  1591      { \
       
  1592 -        if (!_Py_TracingPossible) { \
       
  1593 +        if (!_Py_TracingPossible && !PYTHON_LINE_ENABLED()) { \
       
  1594              f->f_lasti = INSTR_OFFSET(); \
       
  1595              goto *opcode_targets[*next_instr++]; \
       
  1596          } \
       
  1597 @@ -1160,6 +1224,11 @@
       
  1598          }
       
  1599      }
       
  1600  
       
  1601 +#ifdef WITH_DTRACE
       
  1602 +    if (PYTHON_FUNCTION_ENTRY_ENABLED())
       
  1603 +        dtrace_entry(f);
       
  1604 +#endif
       
  1605 +
       
  1606      co = f->f_code;
       
  1607      names = co->co_names;
       
  1608      consts = co->co_consts;
       
  1609 @@ -1354,6 +1423,12 @@
       
  1610          /* Main switch on opcode */
       
  1611          READ_TIMESTAMP(inst0);
       
  1612  
       
  1613 +#ifdef WITH_DTRACE
       
  1614 +        if (PYTHON_LINE_ENABLED()) {
       
  1615 +            maybe_dtrace_line(f, &instr_lb, &instr_ub, &instr_prev);
       
  1616 +        }
       
  1617 +#endif
       
  1618 +
       
  1619          switch (opcode) {
       
  1620  
       
  1621          /* BEWARE!
       
  1622 @@ -3569,6 +3644,10 @@
       
  1623  
       
  1624      /* pop frame */
       
  1625  exit_eval_frame:
       
  1626 +#ifdef WITH_DTRACE
       
  1627 +    if (PYTHON_FUNCTION_RETURN_ENABLED())
       
  1628 +        dtrace_return(f);
       
  1629 +#endif
       
  1630      Py_LeaveRecursiveCall();
       
  1631      f->f_executing = 0;
       
  1632      tstate->frame = f->f_back;
       
  1633 @@ -4319,6 +4398,57 @@
       
  1634      return result;
       
  1635  }
       
  1636  
       
  1637 +/*
       
  1638 + * These shenanigans look like utter madness, but what we're actually doing is
       
  1639 + * making sure that the ustack helper will see the PyFrameObject pointer on the
       
  1640 + * stack. We have two tricky cases:
       
  1641 + *
       
  1642 + * amd64
       
  1643 + *
       
  1644 + * We use up the six registers for passing arguments, meaning the call can't
       
  1645 + * use a register for passing 'f', and has to push it onto the stack in a known
       
  1646 + * location.
       
  1647 + *
       
  1648 + * And how does "throwflag" figure in to this? -PN
       
  1649 + *
       
  1650 + * SPARC
       
  1651 + *
       
  1652 + * Here the problem is that (on 32-bit) the compiler is re-using %i0 before
       
  1653 + * some calls inside PyEval_EvalFrameReal(), which means that when it's saved,
       
  1654 + * it's just some junk value rather than the real first argument. So, instead,
       
  1655 + * we trace our proxy PyEval_EvalFrame(), where we 'know' the compiler won't
       
  1656 + * decide to re-use %i0. We also need to defeat optimization of our proxy.
       
  1657 + */
       
  1658 +
       
  1659 +#if defined(WITH_DTRACE)
       
  1660 +
       
  1661 +#if defined(__amd64)
       
  1662 +
       
  1663 +PyObject *
       
  1664 +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
       
  1665 +{
       
  1666 +    volatile PyObject *f2;
       
  1667 +    f2 = PyEval_EvalFrameExReal(0, 0, 0, 0, 0, 0, f, throwflag);
       
  1668 +    return (PyObject *)f2;
       
  1669 +}
       
  1670 +
       
  1671 +#elif defined(__sparc)
       
  1672 +
       
  1673 +volatile int dummy;
       
  1674 +
       
  1675 +PyObject *
       
  1676 +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
       
  1677 +{
       
  1678 +    volatile PyObject *f2;
       
  1679 +    f2 = PyEval_EvalFrameExReal(f, throwflag);
       
  1680 +    dummy = f->ob_base.ob_base.ob_refcnt;
       
  1681 +    return (PyObject *)f2;
       
  1682 +}
       
  1683 +
       
  1684 +#endif
       
  1685 +#endif
       
  1686 +
       
  1687 +
       
  1688  PyObject *
       
  1689  _PyEval_CallTracing(PyObject *func, PyObject *args)
       
  1690  {
       
  1691 @@ -4336,6 +4466,51 @@
       
  1692      return result;
       
  1693  }
       
  1694  
       
  1695 +#ifdef WITH_DTRACE
       
  1696 +/* See Objects/lnotab_notes.txt for a description of how tracing works. */
       
  1697 +/* Practically a ripoff of "maybe_call_line_trace" function. */
       
  1698 +static void
       
  1699 +maybe_dtrace_line(PyFrameObject *frame,
       
  1700 +                  int *instr_lb, int *instr_ub, int *instr_prev)
       
  1701 +{
       
  1702 +    int line = frame->f_lineno;
       
  1703 +    char *co_filename, *co_name;
       
  1704 +
       
  1705 +    /* If the last instruction executed isn't in the current
       
  1706 +       instruction window, reset the window.
       
  1707 +    */
       
  1708 +    if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) {
       
  1709 +        PyAddrPair bounds;
       
  1710 +        line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti,
       
  1711 +                                       &bounds);
       
  1712 +        *instr_lb = bounds.ap_lower;
       
  1713 +        *instr_ub = bounds.ap_upper;
       
  1714 +    }
       
  1715 +    /* If the last instruction falls at the start of a line or if
       
  1716 +       it represents a jump backwards, update the frame's line
       
  1717 +       number and call the trace function. */
       
  1718 +    if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) {
       
  1719 +        frame->f_lineno = line;
       
  1720 +        co_filename = PyUnicode_AsUTF8(frame->f_code->co_filename);
       
  1721 +        if (!co_filename)
       
  1722 +            co_filename = "?";
       
  1723 +        co_name = PyUnicode_AsUTF8(frame->f_code->co_name);
       
  1724 +        if (!co_name)
       
  1725 +            co_name = "?";
       
  1726 +        PYTHON_LINE(co_filename, co_name, line);
       
  1727 +    }
       
  1728 +    *instr_prev = frame->f_lasti;
       
  1729 +
       
  1730 +    /*
       
  1731 +     * Currently a USDT tail-call will not receive the correct arguments.
       
  1732 +     * Disable the tail call here.
       
  1733 +     */
       
  1734 +#if defined(__sparc)
       
  1735 +    asm("nop");
       
  1736 +#endif
       
  1737 +}
       
  1738 +#endif
       
  1739 +
       
  1740  /* See Objects/lnotab_notes.txt for a description of how tracing works. */
       
  1741  static int
       
  1742  maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
       
  1743 --- Python-3.5.0a4/configure.~1~	2015-04-20 00:37:53.000000000 -0700
       
  1744 +++ Python-3.5.0a4/configure	2015-04-20 12:58:28.386851213 -0700
       
  1745 @@ -642,6 +642,11 @@
       
  1746  MACHDEP_OBJS
       
  1747  DYNLOADFILE
       
  1748  DLINCLDIR
       
  1749 +DTRACEOBJS
       
  1750 +DTRACE_LINKER
       
  1751 +DTRACE_NM
       
  1752 +DFLAGS
       
  1753 +DTRACE
       
  1754  THREADOBJ
       
  1755  LDLAST
       
  1756  USE_THREAD_MODULE
       
  1757 @@ -818,6 +823,7 @@
       
  1758  with_tsc
       
  1759  with_pymalloc
       
  1760  with_valgrind
       
  1761 +with_dtrace
       
  1762  with_fpectl
       
  1763  with_libm
       
  1764  with_libc
       
  1765 @@ -1506,6 +1512,7 @@
       
  1766    --with(out)-tsc         enable/disable timestamp counter profile
       
  1767    --with(out)-pymalloc    disable/enable specialized mallocs
       
  1768    --with-valgrind         Enable Valgrind support
       
  1769 +  --with(out)-dtrace      disable/enable dtrace support
       
  1770    --with-fpectl           enable SIGFPE catching
       
  1771    --with-libm=STRING      math library
       
  1772    --with-libc=STRING      C library
       
  1773 @@ -10786,6 +10793,174 @@
       
  1774      OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT"
       
  1775  fi
       
  1776  
       
  1777 +# Check for dtrace support
       
  1778 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-dtrace" >&5
       
  1779 +$as_echo_n "checking for --with-dtrace... " >&6; }
       
  1780 +
       
  1781 +# Check whether --with-dtrace was given.
       
  1782 +if test "${with_dtrace+set}" = set; then :
       
  1783 +  withval=$with_dtrace;
       
  1784 +else
       
  1785 +  with_dtrace=no
       
  1786 +fi
       
  1787 +
       
  1788 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_dtrace" >&5
       
  1789 +$as_echo "$with_dtrace" >&6; }
       
  1790 +
       
  1791 +
       
  1792 +
       
  1793 +
       
  1794 +
       
  1795 +DTRACE=
       
  1796 +DFLAGS=
       
  1797 +if test "$with_dtrace" = "yes"
       
  1798 +then
       
  1799 +    DTRACE_NM=OTHER
       
  1800 +    DTRACE_LINKER=ld
       
  1801 +    DTRACEOBJS="Python/pydtrace.o"
       
  1802 +    # Extract the first word of "dtrace", so it can be a program name with args.
       
  1803 +set dummy dtrace; ac_word=$2
       
  1804 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
       
  1805 +$as_echo_n "checking for $ac_word... " >&6; }
       
  1806 +if ${ac_cv_path_DTRACE+:} false; then :
       
  1807 +  $as_echo_n "(cached) " >&6
       
  1808 +else
       
  1809 +  case $DTRACE in
       
  1810 +  [\\/]* | ?:[\\/]*)
       
  1811 +  ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path.
       
  1812 +  ;;
       
  1813 +  *)
       
  1814 +  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
       
  1815 +for as_dir in $PATH$PATH_SEPARATOR/usr/sbin
       
  1816 +do
       
  1817 +  IFS=$as_save_IFS
       
  1818 +  test -z "$as_dir" && as_dir=.
       
  1819 +    for ac_exec_ext in '' $ac_executable_extensions; do
       
  1820 +  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
       
  1821 +    ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext"
       
  1822 +    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
       
  1823 +    break 2
       
  1824 +  fi
       
  1825 +done
       
  1826 +  done
       
  1827 +IFS=$as_save_IFS
       
  1828 +
       
  1829 +  test -z "$ac_cv_path_DTRACE" && ac_cv_path_DTRACE="dtrace"
       
  1830 +  ;;
       
  1831 +esac
       
  1832 +fi
       
  1833 +DTRACE=$ac_cv_path_DTRACE
       
  1834 +if test -n "$DTRACE"; then
       
  1835 +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5
       
  1836 +$as_echo "$DTRACE" >&6; }
       
  1837 +else
       
  1838 +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
       
  1839 +$as_echo "no" >&6; }
       
  1840 +fi
       
  1841 +
       
  1842 +
       
  1843 +    # The cast to long int works around a bug in the HP C Compiler
       
  1844 +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
       
  1845 +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
       
  1846 +# This bug is HP SR number 8606223364.
       
  1847 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
       
  1848 +$as_echo_n "checking size of long... " >&6; }
       
  1849 +if ${ac_cv_sizeof_long+:} false; then :
       
  1850 +  $as_echo_n "(cached) " >&6
       
  1851 +else
       
  1852 +  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long"        "$ac_includes_default"; then :
       
  1853 +
       
  1854 +else
       
  1855 +  if test "$ac_cv_type_long" = yes; then
       
  1856 +     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
       
  1857 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
       
  1858 +as_fn_error 77 "cannot compute sizeof (long)
       
  1859 +See \`config.log' for more details" "$LINENO" 5; }
       
  1860 +   else
       
  1861 +     ac_cv_sizeof_long=0
       
  1862 +   fi
       
  1863 +fi
       
  1864 +
       
  1865 +fi
       
  1866 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
       
  1867 +$as_echo "$ac_cv_sizeof_long" >&6; }
       
  1868 +
       
  1869 +
       
  1870 +
       
  1871 +cat >>confdefs.h <<_ACEOF
       
  1872 +#define SIZEOF_LONG $ac_cv_sizeof_long
       
  1873 +_ACEOF
       
  1874 +
       
  1875 +
       
  1876 +    if test "$ac_cv_sizeof_long" -eq 8
       
  1877 +    then
       
  1878 +        DFLAGS="-64"
       
  1879 +    else
       
  1880 +        DFLAGS="-32"
       
  1881 +    fi
       
  1882 +    sys_release="$ac_sys_release"
       
  1883 +    case $ac_sys_system/$sys_release in
       
  1884 +        SunOS/5.10)
       
  1885 +            DTRACE_NM=SOLARIS
       
  1886 +            DTRACE_LINKER=/usr/ccs/bin/ld
       
  1887 +            ;;
       
  1888 +        SunOS/5.11 | SunOS/5.12)
       
  1889 +            DTRACE_NM=SOLARIS
       
  1890 +            DTRACE_LINKER=/usr/bin/ld
       
  1891 +	    ;;
       
  1892 +        SunOS/*)
       
  1893 +            DTRACE_LINKER=/usr/ccs/bin/ld
       
  1894 +            ;;
       
  1895 +        Darwin/*)
       
  1896 +            DTRACEOBJS=""  # Not needed in Mac
       
  1897 +            # The cast to long int works around a bug in the HP C Compiler
       
  1898 +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
       
  1899 +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
       
  1900 +# This bug is HP SR number 8606223364.
       
  1901 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
       
  1902 +$as_echo_n "checking size of long... " >&6; }
       
  1903 +if ${ac_cv_sizeof_long+:} false; then :
       
  1904 +  $as_echo_n "(cached) " >&6
       
  1905 +else
       
  1906 +  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long"        "$ac_includes_default"; then :
       
  1907 +
       
  1908 +else
       
  1909 +  if test "$ac_cv_type_long" = yes; then
       
  1910 +     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
       
  1911 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
       
  1912 +as_fn_error 77 "cannot compute sizeof (long)
       
  1913 +See \`config.log' for more details" "$LINENO" 5; }
       
  1914 +   else
       
  1915 +     ac_cv_sizeof_long=0
       
  1916 +   fi
       
  1917 +fi
       
  1918 +
       
  1919 +fi
       
  1920 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
       
  1921 +$as_echo "$ac_cv_sizeof_long" >&6; }
       
  1922 +
       
  1923 +
       
  1924 +
       
  1925 +cat >>confdefs.h <<_ACEOF
       
  1926 +#define SIZEOF_LONG $ac_cv_sizeof_long
       
  1927 +_ACEOF
       
  1928 +
       
  1929 +
       
  1930 +            if test "$ac_cv_sizeof_long" -eq 8
       
  1931 +            then
       
  1932 +                DFLAGS="-arch i386"
       
  1933 +            else
       
  1934 +                DFLAGS="-arch x86_64"
       
  1935 +            fi
       
  1936 +            ;;
       
  1937 +    esac
       
  1938 +
       
  1939 +$as_echo "#define WITH_DTRACE 1" >>confdefs.h
       
  1940 +
       
  1941 +fi
       
  1942 +
       
  1943 +
       
  1944 +
       
  1945  # -I${DLINCLDIR} is added to the compile rule for importdl.o
       
  1946  
       
  1947  DLINCLDIR=.
       
  1948 --- Python-3.5.0a4/configure.ac.~1~	2015-04-20 00:37:53.000000000 -0700
       
  1949 +++ Python-3.5.0a4/configure.ac	2015-04-20 12:59:58.383305870 -0700
       
  1950 @@ -3086,6 +3086,62 @@
       
  1951      OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT"
       
  1952  fi
       
  1953  
       
  1954 +# Check for dtrace support
       
  1955 +AC_MSG_CHECKING(for --with-dtrace)
       
  1956 +AC_ARG_WITH(dtrace,
       
  1957 +  AC_HELP_STRING(--with(out)-dtrace, disable/enable dtrace support),,
       
  1958 +  with_dtrace=no)
       
  1959 +AC_MSG_RESULT($with_dtrace)
       
  1960 +
       
  1961 +AC_SUBST(DTRACE)
       
  1962 +AC_SUBST(DFLAGS)
       
  1963 +AC_SUBST(DTRACE_NM)
       
  1964 +AC_SUBST(DTRACE_LINKER)
       
  1965 +DTRACE=
       
  1966 +DFLAGS=
       
  1967 +if test "$with_dtrace" = "yes"
       
  1968 +then
       
  1969 +    DTRACE_NM=OTHER
       
  1970 +    DTRACE_LINKER=ld
       
  1971 +    DTRACEOBJS="Python/pydtrace.o"
       
  1972 +    AC_PATH_PROG(DTRACE, [dtrace], [dtrace], [$PATH$PATH_SEPARATOR/usr/sbin])
       
  1973 +    AC_CHECK_SIZEOF([long])
       
  1974 +    if [test "$ac_cv_sizeof_long" -eq 8]
       
  1975 +    then
       
  1976 +        DFLAGS="-64"
       
  1977 +    else
       
  1978 +        DFLAGS="-32"
       
  1979 +    fi
       
  1980 +    sys_release="$ac_sys_release"
       
  1981 +    case $ac_sys_system/$sys_release in
       
  1982 +        SunOS/5.10)
       
  1983 +            DTRACE_NM=SOLARIS
       
  1984 +            DTRACE_LINKER=/usr/ccs/bin/ld
       
  1985 +            ;;
       
  1986 +        SunOS/5.11 | SunOS/5.12)
       
  1987 +            DTRACE_NM=SOLARIS
       
  1988 +            DTRACE_LINKER=/usr/bin/ld
       
  1989 +	    ;;
       
  1990 +        SunOS/*)
       
  1991 +            DTRACE_LINKER=/usr/ccs/bin/ld
       
  1992 +            ;;
       
  1993 +        Darwin/*)
       
  1994 +            DTRACEOBJS=""  # Not needed in Mac
       
  1995 +            AC_CHECK_SIZEOF([long])
       
  1996 +            if [test "$ac_cv_sizeof_long" -eq 8]
       
  1997 +            then
       
  1998 +                DFLAGS="-arch i386"
       
  1999 +            else
       
  2000 +                DFLAGS="-arch x86_64"
       
  2001 +            fi
       
  2002 +            ;;
       
  2003 +    esac
       
  2004 +    AC_DEFINE(WITH_DTRACE, 1, 
       
  2005 +     [Define if you want to compile in Dtrace support])
       
  2006 +fi
       
  2007 +
       
  2008 +AC_SUBST(DTRACEOBJS)
       
  2009 +
       
  2010  # -I${DLINCLDIR} is added to the compile rule for importdl.o
       
  2011  AC_SUBST(DLINCLDIR)
       
  2012  DLINCLDIR=.
       
  2013 --- Python-3.5.0a4/pyconfig.h.in.~1~	2015-04-20 00:37:53.000000000 -0700
       
  2014 +++ Python-3.5.0a4/pyconfig.h.in	2015-04-20 13:00:52.054987861 -0700
       
  2015 @@ -1355,6 +1355,9 @@
       
  2016  /* Define if you want documentation strings in extension modules */
       
  2017  #undef WITH_DOC_STRINGS
       
  2018  
       
  2019 +/* Define if you want to compile in Dtrace support */
       
  2020 +#undef WITH_DTRACE
       
  2021 +
       
  2022  /* Define if you want to use the new-style (Openstep, Rhapsody, MacOS) dynamic
       
  2023     linker (dyld) instead of the old-style (NextStep) dynamic linker (rld).
       
  2024     Dyld is necessary to support frameworks. */
       
  2025 --- Python-3.5.0a4/setup.py.~1~	2015-04-20 00:37:53.000000000 -0700
       
  2026 +++ Python-3.5.0a4/setup.py	2015-04-20 13:01:49.596181289 -0700
       
  2027 @@ -663,6 +663,9 @@
       
  2028          # syslog daemon interface
       
  2029          exts.append( Extension('syslog', ['syslogmodule.c']) )
       
  2030  
       
  2031 +        # jcea DTRACE probes
       
  2032 +        exts.append( Extension('dtrace', ['dtracemodule.c']) )
       
  2033 +
       
  2034          #
       
  2035          # Here ends the simple stuff.  From here on, modules need certain
       
  2036          # libraries, are platform-specific, or present other surprises.