Already bytecoded edit
On the trunk
append array **** array exists array unset array set break catch concat continue dict **** dict append dict create dict exists dict for dict get dict incr dict lappend dict map dict merge dict set dict unset dict update dict with error eval expr for foreach format global if incr info **** info commands info coroutine info exists info level info object **** info object class info object namespace lappend lassign lindex linsert list llength lmap lrange lreplace lset namespace **** namespace code namespace current namespace origin namespace qualifiers namespace tail namespace upvar namespace which next nextto regexp regsub return self **** self namespace self object set string **** string compare string equal string first string index string is alnum alpha ascii boolean control digit double entier false graph integer list lower print punct space true upper wideinteger wordchar xdigit string last string length string map string match string range string replace string tolower string totitle string toupper string trim string trimleft string trimright subst switch tailcall tcl::mathop tcl::mathop::! tcl::mathop::!= tcl::mathop::% tcl::mathop::& tcl::mathop::* tcl::mathop::** tcl::mathop::+ tcl::mathop::- tcl::mathop::/ tcl::mathop::< tcl::mathop::<< tcl::mathop::<= tcl::mathop::== tcl::mathop::> tcl::mathop::>= tcl::mathop::>> tcl::mathop::^ tcl::mathop::eq tcl::mathop::in tcl::mathop::ne tcl::mathop::ni tcl::mathop::| tcl::mathop::~ throw try unset unsupported **** tcl::unsupported::assemble upvar variable while yield yieldto
On a dev branch
These are only done on the dkf-compile-misc-info branch. (Currently none; branch was merged to trunk but remains as base for further work)AMG: lmap?DKF: Yes, indeed (and dict map too)! See TIP #405 for the details; the code was committed on Oct 18. More to the point, some commands (info coroutine, info level, namespace current and self object) aren't yet BCCed on the trunk.I chose to do those four because they're things that are relatively accessible to the bytecode engine.AMG: I'm glad to see [info coroutine], which is performance-critical to Wibble. You may have noticed SEH's contributions to the Wibble implementation, mostly driven by performance. One thing he did was try to cache [info coroutine] in a variable. It seems to me an optimized [info coroutine] ought to take less time than reading a variable.DKF: Don't get your hopes up too much; reading a local variable whose name is known at compile time is exceptionally fast (assuming it is untraced).
Potential candidates for bytecoding edit
Note that there is no consideration of whether these should be bytecoded; with many of them, it might well be a very bad idea for other reasons (e.g., costly internal algorithms).(Note also that anything marked with !!! is ultra-unlikely to be done, on the grounds that it is rare in real code.)array **** array get array names array size binary binary decode binary encode binary format binary scan dict **** dict filter dict keys dict remove dict replace dict size dict values info **** info args info body info class info class call info class constructor info class definition info class destructor info class filters info class forward info class instances info class methods info class methodtype info class mixins info class subclasses info class superclasses info class variables info complete info default info errorstack info frame info globals info locals info object **** info object call info object definition info object filters info object forward info object isa **** [info object isa class] [info object isa metaclass] [info object isa mixin] [info object isa typeof] info object methods info object methodtype info object mixins info object variables info object vars info patchlevel info procs info script info vars join lrepeat lreverse lsearch lsort mathfunc namespace **** namespace children namespace delete namespace ensemble **** [namespace ensemble configure] [namespace ensemble exists] namespace eval namespace exists namespace export namespace forget namespace import namespace inscope namespace parent namespace path namespace unknown scan self **** self call [self caller] !!! self class [self filter] !!! self method !!! [self next] !!! [self target] !!! split string **** string repeat string reverse string wordend !!! string wordstart !!! [tcl::prefix] [tcl::prefix all] [tcl::prefix longest] [tcl::prefix match] time uplevel
DKF: I'm guessing that next, tailcall, yield and yieldto would be good candidates. Maybe also some variants of array unset (those that can be based on the existing unset machinery) and some more dict subcommands. We also ought to be able to do namespace code, though I'm not sure how much of a win that is. Maybe some cases of string is could be done too, though I'm not convinced that would be a net win. uplevel would be good, but I'm really uncertain about how to do it (except in the uplevel 0 case, which is rather low-value). Also, self namespace can probably be done, and if we were to do string map we might also be able to handle some regsub cases (which would definitely benefit some users' code). We can also probably handle some format cases (e.g., “all literals” and “only %s used in format string”).DKF: Turns out to be impossible to do array unset; you get a difference in the trace behavior which you can't work around. Unless I was to add in a special instruction for doing just that particular thing (a “synch the array entries” trace)… Hmm…DKF: It also seems that join is quicker if not bytecoded (with generic instructions). It gains more from being able to do low-level buffer access than from avoiding leaving TEBC, and we'd have to just wholly code it directly as new bytecodes to benefit.AMG: I'd like to see [time] be optimized so I don't have to wrap everything I'm timing in a proc. That's probably not the same thing as bytecoding it, though. I imagine bytecoding [time] would entail adding opcodes to start and end timing, along with a stack mechanism to keep track of iteration counts and nested invocations of time. I'd be inclined to say that's too much of a hassle, but it would be nice to have an efficient fixed count loop mechanism. [for] is an awfully big, slow, and unwieldy, and [while] with [incr $count -1] is faster except for the need to either devise preincrement (while {"$count[incr count -1; list]"} {...}) or toss in an extra [incr count] before starting the loop (for {incr count} {[incr count -1]} {} {...}). How clumsy.
Filtered Candidates
dict keys | Maybe; a trivial extension from dict for, which is done. |
dict values | Maybe; a trivial extension from dict for, which is done. |
AMG: Regarding [uplevel 0]: I think the major use case for this command went away when we fixed/broke the nested array bug/feature. I recently used [uplevel 0] because I had a bunch of commands operating on a variable name that resulted from several substitutions I got tired of typing all the time, but I later redesigned the code to avoid it.AMG: Update! Oops, I meant to say [upvar 0], which isn't relevant to your discussion anyway. Sorry!
Commands that will never be bytecoded edit
Low-level details/internals
These are commands that access information that is probably not best used in production systems, or do things that are largely obsolete.array array anymore array donesearch array nextelement array startsearch array statistics dict **** dict info encoding **** encoding system info **** info cmdcount info functions info tclversion memory [memory active] [memory break_on_malloc] [memory info] [memory init] [memory objs] [memory onexit] [memory tag] [memory trace] [memory trace_on_at_malloc] [memory validate] string **** string bytelength unsupported **** tcl::unsupported::disassemble tcl::unsupported::inject tcl::unsupported::representation
DKF: I know my assertion that info tclversion is obsolete is somewhat controversial, but info patchlevel has been useful for much longer, and package's relationship to the Tcl package is probably more relevant anyway.
OS connectivity, script library
These are commands where the dominant performance factors are the OS, or they are deliberately kept as scripted commands. In either case, there's no real benefit to bytecoding (there are better choices of place to put effort).after after <ms> after cancel after idle after info auto_execok auto_import auto_load auto_mkindex auto_path auto_qualify auto_reset bgerror cd chan chan blocked chan close chan configure chan copy chan create chan eof chan event chan flush chan gets chan names chan pending chan pipe chan pop chan postevent chan push chan puts chan read chan seek chan tell chan truncate clock clock add clock clicks clock format clock microseconds clock milliseconds clock scan clock seconds close dde [dde eval] [dde execute] [dde poke] [dde request] [dde servername] [dde services] encoding encoding convertfrom encoding convertto encoding dirs encoding names eof exec exit fblocked fconfigure fcopy file file atime file attributes file channels file copy file delete file dirname file executable file exists file extension file isdirectory file isfile file join file link file lstat file mkdir file mtime file nativename file normalize file owned file pathtype file readable file readlink file rename file rootname file separator file size file split file stat file system file tail file tempfile file type file volumes file writable fileevent flush gets glob history [history add] [history change] [history clear] [history event] [history info] [history keep] [history nextid] [history redo] http http::cleanup http::code http::config http::data http::error http::formatQuery [1] http::meta http::ncode http::register http::reset http::size http::status http::unregister http::wait info **** info hostname info library info loaded info nameofexecutable info sharedlibextension interp **** interp aliases interp bgerror interp cancel interp debug interp eval interp exists interp hidden interp invokehidden interp issafe interp limit interp marktrusted interp recursionlimit interp share interp slaves interp target interp transfer load msgcat msgcat::mc msgcat::mcflmset msgcat::mcflset msgcat::mcload msgcat::mclocale msgcat::mcmax msgcat::mcmset msgcat::mcpreferences msgcat::mcset msgcat::mcunknown open package package forget package ifneeded package names package prefer package present package provide package require package require package unknown package vcompare package versions package vsatisfies parray pid pkg::create pkg_mkIndex platform platform::generic platform::identify platform::patterns platform::shell [platform::shell::generic] [platform::shell::identify] [platform::shell::platform] puts pwd read registry [registry broadcast] [registry delete] [registry get] [registry keys] [registry set] [registry type] [registry values] safe **** safe::interpAddToAccessPath safe::interpConfigure safe::interpDelete safe::interpFindInAccessPath safe::interpInit safe::setLogCmd seek socket source tcl_endOfWord tcl_findLibrary tcl_startOfNextWord tcl_startOfPreviousWord tcl_wordBreakAfter tcl_wordBreakBefore tcltest tcltest::bytestring tcltest::cleanupTests tcltest::configure tcltest::customMatch tcltest::debug tcltest::errorChannel tcltest::errorFile tcltest::interpreter tcltest::limitConstraints tcltest::loadFile tcltest::loadScript tcltest::loadTestedCommands tcltest::makeDirectory tcltest::makeFile tcltest::match tcltest::matchDirectories tcltest::matchFiles tcltest::normalizeMsg tcltest::normalizePath tcltest::outputChannel tcltest::outputFile tcltest::preserveCore tcltest::removeDirectory tcltest::removeFile tcltest::runAllTests tcltest::singleProcess tcltest::skip tcltest::skipDirectories tcltest::skipFiles tcltest::temporaryDirectory tcltest::test tcltest::testConstraint tcltest::testsDirectory tcltest::verbose tcltest::viewFile tcltest::workingDirectory tell tm tcl::tm::path tcl::tm::roots trace [trace add] [trace info] [trace remove] [trace variable] [trace vdelete] [trace vinfo] unknown unload update vwait zlib zlib adler32 zlib compress zlib crc32 zlib decompress zlib deflate zlib gunzip zlib gzip zlib inflate zlib push zlib stream
Command creation and related
These create commands and do related tricks; they mostly benefit a lot from bytecoding, but there's little value in boosting them themselves. (Though rename is a special case in that it is possible to sensibly bytecode it, but it is much more likely to trigger a progressive recompile than nearly any other command.)apply coroutine interp **** interp alias interp create interp delete interp expose interp hide my namespace **** namespace ensemble **** [namespace ensemble create] oo::class oo::copy oo::define oo::objdefine oo::object proc rename safe **** safe::interpCreate
Not actually commands edit
These have manpage links, but aren't commands as such.Tcl argc argv argv0 env errorCode errorInfo filename re_syntax refchan tcl_interactive tcl_library tcl_nonwordchars tcl_patchLevel tcl_pkgPath tcl_platform tcl_precision tcl_rcFileName tcl_traceCompile tcl_traceEval tcl_version tcl_wordchars transchan