In G1ParScanThreadState::copy_to_survivor_space(), alloc_purpose is just seen as a hint to allocate(). E.g. a request for an allocation in survivor region might end up being an allocation in an old region (if we're out of survivor regions). However, the alloc_purpose flags is later also used (incorrectly) to determine where the object was actually allocated to 1) determine if the object age should be adjusted and 2) for undoing the allocation.
After the object has been allocated the alloc_purpose flags should be updated to reflect the actual location of the object.