From my understanding, there is only one heap (ironically, it's usually depicted as a stack). Objects are promoted to generation 1 not when generation 0 fills, but when they survive a collection. In brief, references are not "moved," the location used to identify where the generation ends is moved.
When the heap gets close to being full, a few things occur:
- Each generation is collected, starting from 0 and ending with 2.
- If collection of generation 0 is sufficient, it will not collect generation 1 and 2.
- If collection of generation 0 is not sufficient, but collection of generation 1 is, it will not collect generation 2.
- The heap is compacted (gaps are removed)
- Promote generations
- Generation 1 survivors are tagged as generation 2.
- Generation 0 survivors are tagged as generation 1.
Objects that survive collection are then moved to generation 0 (if this is their first collection cycle) or generation 2 (if they have survived more than one collection). This is done for efficiency sake, to ensure that we don't constantly try to collect long-lived objects.
You don't run out of space in generation specific ways. See this article for a good explanation.