public void garbageCollect() {
    // Reset the heap allocation pointer to the start of toSpace:
    hp = 0;

    // Forward any objects that are pointed to by a, b, c, or d.
    // These are the "roots" for our garbage collection.
    a = forward(a);
    b = forward(b);
    c = forward(c);
    d = forward(d);

    // Now scavenge the objects that we have already copied over
    // into toSpace and look for reachable objects in the original
    // heap that should also be forwarded into toSpace:
    int toVisit = 0;
    while (toVisit < hp) {
      toVisit += scavenge(toVisit);
    }

    // Now that we have copied all the non-garbage over into toSpace,
    // swap the two heap portions so that further allocation can
    // continue in the toSpace that we've just built without any of
    // the garbage that was lying around in the original heap.  Of
    // course we'll keep the original heap structure around too so
    // that it can be used as our toSpace on the next call to the
    // garbage collector.
    int[] newheap = toSpace;
    toSpace       = heap;
    heap          = newheap;
  }