To cope with this the mutator is modified at compile/run time to inform the GC of object updates that could lead to this situation.
During compaction of any sort, the first time an object is encountered that is to be moved it is copied somewhere else and the old copy's header is overwritten with it's forwarding address. Every time the GC encounters a reference to the old object, it re-writes the reference to the old object with it's new location (conveniently located in the old copy's header).
> Is it possible that a reference value is a pointer to a reference "object" which contains the pointer to data, which needs to be updated?
Look up something called 'Brook's style forwarding pointer', it is essentially what you've described.