wip [ci skip]
diff --git a/src/cycleCollector.js b/src/cycleCollector.js
index 6ce7689..805f76c 100644
--- a/src/cycleCollector.js
+++ b/src/cycleCollector.js
@@ -189,10 +189,13 @@
   // When constructing a CycleCollector a wasm Table must be passed in, and
   // the start index from which we can manage it.
   constructor(table, tableStartIndex, innerVM) {
-    // For simplicity our table will always store WeakRefs to objects. We
-    // will also store a strong ref on the side, which may be removed when
-    // cycle collecting.
+    // For simplicity our table will always store WeakRefs to objects, which
+    // means usage of the table does not change during a cycle collection
+    // (otherwise if we turned a strong ref to a weak one, that would be
+    // noticeable).
     this.tableManager = new WeakTableManager(table, tableStartIndex);
+    // We store strong refs here, i.e., roots for outside objects. This
+    // does change during a cycle collection.
     this.outsideRoots = new RefCountedSet(Set);
     // We also have hooks to the inner VM, and create roots there as
     // needed.
@@ -203,6 +206,8 @@
     this.incomingLinks = new WeakMap();
     // Also track all objects that have incoming links.
     this.incomingOrigins = new RefCountedSet(IterableWeakSet);
+    // Info for the current cycle collection, if any.
+    this.currCycleCollection = null;
   }
   // Increment a link between an internal object to an external one (an
   // object may have multiple links to the same place, e.g., an array with
@@ -213,19 +218,21 @@
       // We track links to the table index, rather than to the object.
       // The index is what can be stored in linear memory, and so when using
       // a compiled object is what we have to look up the outer object with.
-      links = this.outGoingLinks[ptr] = new RefCountedSet(Set);
+      links = this.outGoingLinks[ptr] = new RefCountedSet(IterableWeakSet);
     }
-    // Begin with holding a strong reference to the target object.
-    this.outsideRoots.inc(ref);
     // Store a (unique) WeakRef in the table.
     var index = this.tableManager.inc(ref);
-    links.inc(index);
+    if (links.inc(index)) {
+      // While this ptr has a link to ref, hold a strong reference on it.
+      this.outsideRoots.inc(ref);
+    }
     return index;
   }
   decOutgoingLink(ptr, ref) {
-    this.outgoingLinks[ptr].dec(ref);
+    if (this.outgoingLinks[ptr].dec(ref)) {
+      this.outsideRoots.dec(ref);
+    }
     this.tableManager.dec(ref);
-    this.outsideRoots.dec(ref);
   }
   incIncomingLink(ref, ptr) {
     if (!this.incomingLinks.has(ref)) {
@@ -309,7 +316,7 @@
     // Connect JS objects with incoming links to their mirrors. Avoid modifying
     // those objects - use a WeakMap instead.
     const externalLinksToMirrors = new WeakMap();
-    for (let ref in this.incomingOrigins.set.iter) {
+    for (let ref in this.incomingOrigins.set.iterable) {
       ref = ref.deref();
       if (!ref) continue;
       const set = this.incomingLinks[ref].set;
@@ -323,22 +330,31 @@
       }
     }
     // JS now mirrors the internal objects and their participation in
-    // possible cycles.
-    // Listen for when the mirrors go away.
-    var finalizationGroup = new FinalizationGroup(holdings => {
-      for (const holding of holdings) {
-        zzz
+    // possible cycles. The JS object graph now represents the relevant links
+    // from the inner VM, which means we can stop holding strong refs on
+    // those objects. That is, if a mirrored object has a reference to an
+    // outside object, we can make that a weak reference - if the object
+    // should be kept alive, the JS graph (with mirroring) keeps it alive,
+    // and a manual root for the JS object is not needed.
+    const deccedOutsideRoots = new WeakMap();
+    for (const mirror of mirrors.values()) {
+      const outgoing = this.outgoingLinks.get(mirror.ptr);
+      if (outgoing) {
+        for (const weak in outgoing.iterable) {
+          const ref = weak.deref();
+          if (ref) {
+            this.outsideRoots.dec(ref);
+            deccedOutsideRoots.set(ref, (deccedOutsideRoots.get(ref) | 0) + 1);
+          }
+        }
       }
-    });
-   // listen on objects, or just the incoming refs?
-zzz    this.finalizationGroup.register(x, weakRef, weakRef);
-
-
-
-// Weakify
+    }
+    // Save relevant information we need during the cycle collection.
     this.currCycleCollection = {
-      maybeDeadInside: maybeDeadInside
+      externalLinksToMirrors: externalLinksToMirrors,
+      deccedOutsideRoots: deccedOutsideRoots,
     };
+// TODO: handle the invalidation problem
   }
   // Internals
   //...