Don't unfold graph structure when copying
When copying a node, don't unfold the structure. This is ~critical, because unfolding can cause infinite recursion for cyclical graphs.
This is possible in two passes:
- Copy everything except descriptor values. Store the host descriptors in the descriptor positions in the interpreter. Store references to the new interpreter nodes in the descriptors on the host (with the LSB set to distinguish nodes that have been copied already).
- Resolve the descriptors and replace the original descriptors of the host.
I believe it is not possible to store a matching list of host and interpreter nodes to avoid copying a node when it has been copied in a previous step, because the nodes may be mutable and the mutations are not synchronised. But this needs to be discussed with John. This is in principle possible (the only case in which we copy a mutable data structure is when its reference from the source is lost), however, the matching will be inefficient and needs to be updated after garbage collection (on both sides). A middle ground is to keep the matching as a kind of cache until the next garbage collection.