Bitarray Stepper

Pick a command, then step through what Tcl and bitarray.c do with it: which core function reaches which hook, and how the bits and 64-bit words change. Change the width, the index or the value and the steps are recomputed.

Shortcuts
→ next step ← back
Space start / pause auto-play
Esc close the code view
code view: double-click a name to jump, ⌫ back (then show memory)
click a marker: go to that step
Back on the first step: previous command
Command
Element width Is the array shared?

Memory a simplified drawing of the real data; each 64-bit word is shown in hex

Call history newest at the top; 0 is always the library load

script / bytecodeTcl corebitarray.cresult

Tcl_ObjType hooks the slots the core can call

Slotbitarray

Core map which core function reaches which hook (checked against the Tcl source, see below)

CommandCore pathHook
llength $aINST_LIST_LENGTH (tclExecute.c) → TclListObjLength (tclListObj.c)lengthProc → BALength
lindex $a iINST_LIST_INDEX or INST_LIST_INDEX_IMM (tclExecute.c): TclObjTypeLength, then TclObjTypeIndexindexProc → BAIndex
lset a i vINST_LSET_FLAT (tclExecute.c) → TclObjTypeSetElement; Tcl_LsetObjCmd → TclLsetList (tclListObj.c) takes the same routesetElementProc → BASetElement (it copies a shared array itself)
lrange $a i jINST_LIST_RANGE_IMM (tclExecute.c) or Tcl_LrangeObjCmd (tclCmdIL.c) → Tcl_ListObjRange (tclListTypes.c) → TclObjTypeSlicesliceProc → BASlice
lreverse $aTcl_LreverseObjCmd (tclCmdIL.c) → Tcl_ListObjReverse (tclListTypes.c) → TclObjTypeReversereverseProc → BAReverse
lreplace $a i j …INST_LREPLACE (tclExecute.c): Tcl_ListObjLength, Tcl_DuplicateObj if shared, then Tcl_ListObjReplace (tclListObj.c) → TclObjTypeReplacereplaceProc → BAReplace (copy through dupIntRepProc → BADup)
foreach e $aINST_FOREACH_STEP (tclExecute.c): Tcl_ListObjLength once, then Tcl_ListObjIndex per elementlengthProc, indexProc → BALength, BAIndex
x in $aINST_LIST_IN (tclExecute.c) → TclObjTypeInOperatorinOperProc → BAInOper
join $a ,Tcl_JoinObjCmd (tclCmdIL.c) → TclObjTypeGetElements (the same for {*}$a and others that need every element)getElementsProc → BAGetElements
puts $aTcl_GetString → the type's updateStringProcupdateStringProc → BAUpdateString
lappend a vTcl_ListObjAppendElement → TclListObjAppendElements → TclListObjGetRep → SetListFromAny (tclListObj.c)no slot; SetListFromAny calls BALength, then BAIndex per element, and the array becomes a plain list
bitarray and …none: it is an ordinary commandBitarrayCmd → BitOpCmd → BitOpWords

About this page

The steps were written from the sources: bitarray.c (Version 0.9.4) and the Tcl 9.1 source tree (GitHub mirror, commit e36db33; files tclExecute.c, tclListObj.c, tclListTypes.c, tclCmdIL.c, tclArithSeries.c). Function names are stable; line numbers and details can drift in later Tcl versions, so check the source before relying on a name. The values drawn are computed by this page's own small model of the operations. They are not captured from a running Tcl, and the page does not run Tcl or your build. The simplifications are: refcounts count only the variables shown (the real value stack holds extra references for a moment); an array has 16 elements here (real ones are as long as you like); and capWords is modelled only where a step grows the array (doubling, at least 4 words).

Timings and when to prefer a plain list are in performance_analysis.md; the full command syntax is in README.md.