Composition records information about the execution of a composable function in the slot table in the form of a tree linearly layed out into an array (two parallel arrays actually). It is easiest to think of this as just a tree, however. It is a tree recording the call graph (tree) of the composition; each call is recorded as a node in the tree called a Group (as it contains a group of nodes). Each group has a key generated by the compiler that is unique its code location. Each group can contain any number of sub-groups. There are special groups, called node groups, that record when a node is emitted (e.g. a layout node) and each group records how many nodes it contains (but not how many nodes a node group contains).
During recomposition, as a function executes, it compares the group keys in the tree with what was recorded previously, if things are the same, nothing is recorded and it moves on. If, however, a difference is detected the remaining sibling are collected in a hash table and one of two things are true, 1) the group being generated is in the sibling list at a different location, 2) the group is not in the sibling list. If (1) is the case, a move is recorded and the composition continues as if that group was moved already, if (2) an insert of new content is recorded and composition generates new content to be inserted. At the end of the sibling list generation unused siblings are removed. An additional case is when no more siblings are present in the tree but additional groups are generated, this triggers an insert.
When inserting, moving or removing groups, the corresponding index in the container node is tracked and if a group is removed the corresponding nodes are removed. If the group is moved the corresponding nodes for the group are moved. This is made easy to track by keeping track of the number nodes each group contains.
Given the above algorithm, all edits to the recorded information are forward walking, once an edit is performed (insert, delete, or move) at a location in the tree no other changes will occur to earlier groups. Also, the changes are inserts, deletes, and moves. This screamed gap buffer to me as these operations are very efficient in a gap buffer so the call graph is stored in a gap buffer.
Also of note is that the fundamental data types is the Group. This is why the compiler focuses on reducing groups. The lower the number of groups the faster this above algorithm will work.