32.tip at [813de8600b]

Login

File tip/32.tip artifact a29fd2dcab part of check-in 813de8600b


TIP:            32
Title:          Add Tcl_Obj-enabled counterpart to Tcl_CreateTrace
Version:        $Revision: 1.11 $
Author:         David Cuthbert <[email protected]>
Author:         Kevin Kenny <[email protected]>
State:          Final
Type:           Project
Vote:           Done
Created:        23-Mar-2001
Post-History:   
Discussions-To: news:comp.lang.tcl
Keywords:       trace,Tcl_Obj
Tcl-Version:    8.4a4

~ Abstract

This document proposes to add Tcl_Obj support for trace procedures written
in C.

~ Rationale

The ''Tcl_Obj'' system was introduced in version 8.0, making
computations (potentially) much more efficient by eliminating many
type conversions to and from strings.  However, the trace API
continues to require character strings in both command and variable
traces.

In addition, the ''Tcl_CreateTrace'' function interacts rather badly
with the bytecode compiler, since it forbids inlining of functions.
Since many trace applications ignore the built-in functions that would
have been inlined, this restriction is not needed by many
applications.  This TIP proposes to make it optional in the revised API.

The trace mechanism in the Tcl library has been underused for some
time, partly because it is awkward.  While the profiler, tracer and
debugger from TclX and the debugger from Expect have seen some limited
success, they are certainly not familiar to the majority of Tcl users.

The second author of this TIP has experimented with using the trace
mechanism to build a profiler for Tcl that does not depend on source
code instrumentation.  His experience was that:

  * It is very difficult to write useful trace procedures without
    resorting to ''tclInt.h'' -- in particular, the fact that only the
    command name and not the ''Tcl_Command'' token is passed meant
    that ''Tcl_FindCommand'' is needed to do virtually anything
    useful.

  * The profiler often perturbs the run-time behavior of the program,
    often violently.  The reason is twofold.  First, the string
    representation of all of a traced command's arguments must be
    constructed, even though the trace procedure has no need for
    them.  Second, the presence of the trace procedure defeats the
    bytecode compiler.  Since the user of a profiler is unlikely to
    care about each individual built-in command (the common usage is
    to profile the time spent in procedures), turning off inline
    compilation of commands is neither needed nor wanted.

  * The profiler traces returns from commands by subsituting the
    command procedure with one that is internal to the profiler
    itself, and restoring the command procedure upon exit.  Doing so
    requires many needless lookups of the command name, because only
    the name is presented to the trace procedure, and the name is the
    only way to access ''Tcl_GetCommandInfo'' and
    ''Tcl_SetCommandInfo''.  This overhead can be avoided only by
    including ''tclInt.h'' and casting the ''Tcl_Command'' object to a
    ''Command'' object -- in other words, by accessing the
    interpreter's internal data structures from the extension.

This TIP is an effort to rationalize the trace interface to avoid
these difficulties.

~ Specification

The following functions shall be added to the Tcl core:

 1. Tcl_CreateObjTrace

| Tcl_Trace Tcl_CreateObjTrace ( Tcl_Interp*          interp,
|                                int                  level, 
|                                int                  flags,
|                                Tcl_CmdObjTraceProc* objProc,
|                                ClientData           clientData );

  > The ''Tcl_CreateObjTrace'' function adds a trace to the Tcl evaluator.
    The ''interp'' argument is the Tcl interpreter for which tracing is
    being requested.  The ''level'' argument is the maximum depth of
    recursive calls; when the execution depth of the interpreter exceeds
    this number, the trace callback does not execute.  The ''objProc''
    argument is the callback procedure to execute each time a Tcl command
    is evaluated; it is expected to have arguments and result type that
    match ''Tcl_CmdObjTraceProc'' below.  The ''clientData'' argument is
    client data to pass to the ''objProc'' callback.  Finally, the
    ''flags'' argument gives flags that control the tracing.  Initially,
    the only flag supported will be ''TCL_ALLOW_INLINE_COMPILE''.  If this
    flag is set, the bytecode compiler is permitted to compile in-line
    code for the Tcl built-in commands; any command that has been compiled
    in-line will not be traced.

  > The ''Tcl_CreateObjTrace'' function returns a ''trace token'' -- an
    object of opaque type that may be passed to ''Tcl_DeleteTrace'' to
    delete the trace.

  > The ''Tcl_CmdObjTraceProc'' will have the following type signature.

|    typedef int Tcl_CmdObjTraceProc( ClientData     clientData,
|                                     Tcl_Interp*    interp,
|                                     int            level,
|                                     CONST char*    command,
|                                     Tcl_Command    commandInfo,
|                                     int            objc,
|                                     Tcl_Obj *CONST objv[] );

 >  The ''clientData'' parameter is the client data that was passed to
    ''Tcl_CreateObjTrace''.  The ''interp'' parameter designates a Tcl
    interpreter.  The ''level'' parameter specifies the execution level.
    The ''command'' parameter gives the raw UTF-8 text of the command
    being evaluated, before any substitutions have been performed.  The
    ''commandInfo'' parameter is an opaque ''Tcl_Command'' object that
    gives information about the command.  The ''objc'' and ''objv''
    parameters are the command name and parameter vector after
    substitution.

  > The trace procedure is expected to return a standard Tcl status
    return.  If it returns ''TCL_OK'', the command is evaluated
    normally.  If it returns ''TCL_ERROR'', evaluation of the command
    does not take place.  The interpreter result is expected to
    contain an error message.  If it returns any other status, such as
    ''TCL_BREAK'', ''TCL_CONTINUE'' or ''TCL_RETURN'', it is treated
    as if the command had done so.

 1. Tcl_GetCommandInfoFromToken and Tcl_SetCommandInfoFromToken

| int
| Tcl_GetCommandInfoFromToken( Tcl_Command  token,
|                          Tcl_CmdInfo* infoPtr );

| int
| Tcl_SetCommandInfoFromToken( Tcl_Command        token,
|                          CONST Tcl_CmdInfo* infoPtr );

  > The ''Tcl_GetCommandInfoFromToken'' and ''Tcl_SetCommandInfoFromToken''
    functions are precisely parallel to today's ''Tcl_GetCommandInfo''
    and ''Tcl_SetCommandInfo'' procedures, except that they accept an
    opaque ''Tcl_Command'' object instead of a command name.  They are
    provided so that trace procedures (and other extensions that have
    such an object) can adjust command information without having to
    go through two extra lookups in the command hash by applying
    ''Tcl_GetCommandInfo'' to the result of ''Tcl_GetCommandName.''

~ Change History

10 February 2002 - Moved to Final Status with slight revisions in the names
and arguments of Tcl_GetCommandInfoFromToken and Tcl_SetCommandInfoFromToken.

3 November 2001 - Reworked the entire TIP.  Changed the object trace
handling to work with ''Tcl_Command'' objects instead of command
names.  Removed the object-based variable trace procedures.  Since Tcl
variable names really are character strings and not Tcl objects,
object-based variable trace procedures would be ''slower'' than the
string-based ones.

30 March 2001 - Changed return value of objProc to a Tcl_Obj * instead
of int (and using the interpreter result to indicate an error).  This
is more consistent with the current behavior (but without the bug).  -dac

~ Copyright

Copyright � 2000 by David Cuthbert.  Distribution in whole or part,
with or without annotations, is unlimited.

Copyright � 2001 by Kevin B. Kenny.  Distribution in whole or part,
with or without annotations, is unlimited.