<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE TIP SYSTEM "http://tcl.activestate.com/cgi-bin/tct/tip/tipxml.dtd">
<!-- Converted at Thu Feb 09 08:22:02 GMT 2012 -->
<!-- TIP AutoGenerator - written by Donal K. Fellows -->

<TIP number='32'>
<header><title>Add Tcl_Obj-enabled counterpart to Tcl_CreateTrace</title><author address="mailto:dacut@kanga.org">David Cuthbert</author><author address="mailto:kennykb@acm.org">Kevin Kenny</author><status type='project' state='final' tclversion="8.4a4" vote='after'>$Revision: 1.11 $</status><history></history><created day='23' month='mar' year='2001' /><discussions url='news:comp.lang.tcl'/><keyword>trace Tcl_Obj</keyword></header>
<abstract>This document proposes to add Tcl_Obj support for trace procedures written in C.</abstract>
<body><section title="Rationale">
<para>The <emph style="italic">Tcl_Obj</emph> 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.</para>
<para>In addition, the <emph style="italic">Tcl_CreateTrace</emph> 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.</para>
<para>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.</para>
<para>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:</para>
<itemize><item.i><para>It is very difficult to write useful trace procedures without resorting to <emph style="italic">tclInt.h</emph> -- in particular, the fact that only the command name and not the <emph style="italic">Tcl_Command</emph> token is passed meant that <emph style="italic">Tcl_FindCommand</emph> is needed to do virtually anything useful.</para></item.i><item.i><para>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&apos;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.</para></item.i><item.i><para>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 <emph style="italic">Tcl_GetCommandInfo</emph> and <emph style="italic">Tcl_SetCommandInfo</emph>. This overhead can be avoided only by including <emph style="italic">tclInt.h</emph> and casting the <emph style="italic">Tcl_Command</emph> object to a <emph style="italic">Command</emph> object -- in other words, by accessing the interpreter&apos;s internal data structures from the extension.</para></item.i></itemize>
<para>This TIP is an effort to rationalize the trace interface to avoid these difficulties.</para>
</section>
<section title="Specification">
<para>The following functions shall be added to the Tcl core:</para>
<enumerate><item.e index='1'><para>Tcl_CreateObjTrace</para><verbatim><vline encoding='base64'>IFRjbF9UcmFjZSBUY2xfQ3JlYXRlT2JqVHJhY2UgKCBUY2xfSW50ZXJwKiAgICAgICAgICBpbnRlcnAs</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgICAgICAgICAgICAgICAgICBsZXZlbCwg</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgICAgICAgICAgICAgICAgICBmbGFncyw=</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUY2xfQ21kT2JqVHJhY2VQcm9jKiBvYmpQcm9jLA==</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDbGllbnREYXRhICAgICAgICAgICBjbGllbnREYXRhICk7</vline></verbatim><para>The <emph style="italic">Tcl_CreateObjTrace</emph> function adds a trace to the Tcl evaluator. The <emph style="italic">interp</emph> argument is the Tcl interpreter for which tracing is being requested. The <emph style="italic">level</emph> 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 <emph style="italic">objProc</emph> 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 <emph style="italic">Tcl_CmdObjTraceProc</emph> below. The <emph style="italic">clientData</emph> argument is client data to pass to the <emph style="italic">objProc</emph> callback. Finally, the <emph style="italic">flags</emph> argument gives flags that control the tracing. Initially, the only flag supported will be <emph style="italic">TCL_ALLOW_INLINE_COMPILE</emph>. 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.</para><para>The <emph style="italic">Tcl_CreateObjTrace</emph> function returns a <emph style="italic">trace token</emph> -- an object of opaque type that may be passed to <emph style="italic">Tcl_DeleteTrace</emph> to delete the trace.</para><para>The <emph style="italic">Tcl_CmdObjTraceProc</emph> will have the following type signature.</para><verbatim><vline encoding='base64'>ICAgIHR5cGVkZWYgaW50IFRjbF9DbWRPYmpUcmFjZVByb2MoIENsaWVudERhdGEgICAgIGNsaWVudERhdGEs</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRjbF9JbnRlcnAqICAgIGludGVycCw=</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludCAgICAgICAgICAgIGxldmVsLA==</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENPTlNUIGNoYXIqICAgIGNvbW1hbmQs</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRjbF9Db21tYW5kICAgIGNvbW1hbmRJbmZvLA==</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludCAgICAgICAgICAgIG9iamMs</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRjbF9PYmogKkNPTlNUIG9ianZbXSApOw==</vline></verbatim><para>The <emph style="italic">clientData</emph> parameter is the client data that was passed to <emph style="italic">Tcl_CreateObjTrace</emph>. The <emph style="italic">interp</emph> parameter designates a Tcl interpreter. The <emph style="italic">level</emph> parameter specifies the execution level. The <emph style="italic">command</emph> parameter gives the raw UTF-8 text of the command being evaluated, before any substitutions have been performed. The <emph style="italic">commandInfo</emph> parameter is an opaque <emph style="italic">Tcl_Command</emph> object that gives information about the command. The <emph style="italic">objc</emph> and <emph style="italic">objv</emph> parameters are the command name and parameter vector after substitution.</para><para>The trace procedure is expected to return a standard Tcl status return. If it returns <emph style="italic">TCL_OK</emph>, the command is evaluated normally. If it returns <emph style="italic">TCL_ERROR</emph>, 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 <emph style="italic">TCL_BREAK</emph>, <emph style="italic">TCL_CONTINUE</emph> or <emph style="italic">TCL_RETURN</emph>, it is treated as if the command had done so.</para></item.e><item.e index='2'><para>Tcl_GetCommandInfoFromToken and Tcl_SetCommandInfoFromToken</para><verbatim><vline encoding='base64'>IGludA==</vline><vline encoding='base64'>IFRjbF9HZXRDb21tYW5kSW5mb0Zyb21Ub2tlbiggVGNsX0NvbW1hbmQgIHRva2VuLA==</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICBUY2xfQ21kSW5mbyogaW5mb1B0ciApOw==</vline></verbatim><verbatim><vline encoding='base64'>IGludA==</vline><vline encoding='base64'>IFRjbF9TZXRDb21tYW5kSW5mb0Zyb21Ub2tlbiggVGNsX0NvbW1hbmQgICAgICAgIHRva2VuLA==</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICBDT05TVCBUY2xfQ21kSW5mbyogaW5mb1B0ciApOw==</vline></verbatim><para>The <emph style="italic">Tcl_GetCommandInfoFromToken</emph> and <emph style="italic">Tcl_SetCommandInfoFromToken</emph> functions are precisely parallel to today&apos;s <emph style="italic">Tcl_GetCommandInfo</emph> and <emph style="italic">Tcl_SetCommandInfo</emph> procedures, except that they accept an opaque <emph style="italic">Tcl_Command</emph> 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 <emph style="italic">Tcl_GetCommandInfo</emph> to the result of <emph style="italic">Tcl_GetCommandName.</emph></para></item.e></enumerate>
</section>
<section title="Change History">
<para>10 February 2002 - Moved to Final Status with slight revisions in the names and arguments of Tcl_GetCommandInfoFromToken and Tcl_SetCommandInfoFromToken.</para>
<para>3 November 2001 - Reworked the entire TIP. Changed the object trace handling to work with <emph style="italic">Tcl_Command</emph> 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 <emph style="italic">slower</emph> than the string-based ones.</para>
<para>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</para>
</section>
<section title="Copyright">
<para>Copyright © 2000 by David Cuthbert. Distribution in whole or part, with or without annotations, is unlimited.</para>
<para>Copyright © 2001 by Kevin B. Kenny. Distribution in whole or part, with or without annotations, is unlimited.</para>
</section>
</body></TIP>

