diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp
index 8f4ce81b432..6c607b1ad55 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp
@@ -309,14 +309,6 @@ void ShenandoahConcurrentGC::entry_init_mark() {
                               ShenandoahWorkerPolicy::calc_workers_for_init_marking(),
                               "init marking");
 
-  if (ShenandoahHeap::heap()->mode()->is_generational()
-    && (_generation->generation_mode() == YOUNG || (_generation->generation_mode() == GLOBAL && ShenandoahVerify))) {
-    // The current implementation of swap_remembered_set() copies the write-card-table
-    // to the read-card-table. The remembered sets are also swapped for GLOBAL collections
-    // so that the verifier works with the correct copy of the card table when verifying.
-    _generation->swap_remembered_set();
-  }
-
   op_init_mark();
 }
 
@@ -607,6 +599,25 @@ void ShenandoahConcurrentGC::op_init_mark() {
   assert(!_generation->is_mark_complete(), "should not be complete");
   assert(!heap->has_forwarded_objects(), "No forwarded objects on this path");
 
+
+  if (heap->mode()->is_generational()) {
+      if (_generation->generation_mode() == YOUNG || (_generation->generation_mode() == GLOBAL && ShenandoahVerify)) {
+      // The current implementation of swap_remembered_set() copies the write-card-table
+      // to the read-card-table. The remembered sets are also swapped for GLOBAL collections
+      // so that the verifier works with the correct copy of the card table when verifying.
+      _generation->swap_remembered_set();
+    }
+
+    if (_generation->generation_mode() == GLOBAL) {
+      heap->cancel_old_gc();
+    } else if (heap->is_concurrent_old_mark_in_progress()) {
+      // Purge the SATB buffers, transferring any valid, old pointers to the
+      // old generation mark queue. Any pointers in a young region will be
+      // abandoned.
+      heap->transfer_old_pointers_from_satb();
+    }
+  }
+
   if (ShenandoahVerify) {
     heap->verifier()->verify_before_concmark();
   }
@@ -1131,13 +1142,6 @@ void ShenandoahConcurrentGC::op_final_updaterefs() {
 
   heap->update_heap_region_states(true /*concurrent*/);
 
-  if (heap->is_concurrent_old_mark_in_progress()) {
-    // Purge the SATB buffers, transferring any valid, old pointers to the
-    // old generation mark queue. From here on, no mutator will have access
-    // to anything that will be trashed and recycled.
-    heap->purge_old_satb_buffers(false /* abandon */);
-  }
-
   heap->set_update_refs_in_progress(false);
   heap->set_has_forwarded_objects(false);
 
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
index 5d1e09b6c76..48d4789522c 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
@@ -467,7 +467,11 @@ void ShenandoahControlThread::service_concurrent_old_cycle(const ShenandoahHeap*
   young_generation->set_mark_incomplete();
   old_generation->set_mark_incomplete();
   service_concurrent_cycle(young_generation, cause, true);
-  if (!heap->cancelled_gc()) {
+  if (heap->cancelled_gc()) {
+    // Young generation bootstrap cycle has failed. Concurrent mark for old generation
+    // is not going to resume after degenerated young cycle completes.
+    log_info(gc)("Bootstrap cycle for old generation was cancelled.");
+  } else {
     // Reset the degenerated point. Normally this would happen at the top
     // of the control loop, but here we have just completed a young cycle
     // which has bootstrapped the old concurrent marking.
@@ -663,15 +667,13 @@ bool ShenandoahControlThread::service_stw_degenerated_cycle(GCCause::Cause cause
   ShenandoahGCSession session(cause, _degen_generation);
 
   ShenandoahDegenGC gc(point, _degen_generation);
-
-  // Just in case degenerated cycle preempted old-gen marking, clear the old-gen task queues.
-  heap->young_generation()->set_old_gen_task_queues(NULL);
-
   gc.collect(cause);
 
   assert(heap->young_generation()->task_queues()->is_empty(), "Unexpected young generation marking tasks");
-  assert(heap->old_generation()->task_queues()->is_empty(), "Unexpected old generation marking tasks");
-  assert(heap->global_generation()->task_queues()->is_empty(), "Unexpected global generation marking tasks");
+  if (_degen_generation->generation_mode() == GLOBAL) {
+    assert(heap->old_generation()->task_queues()->is_empty(), "Unexpected old generation marking tasks");
+    assert(heap->global_generation()->task_queues()->is_empty(), "Unexpected global generation marking tasks");
+  }
 
   _degen_generation->heuristics()->record_success_degenerated();
   heap->shenandoah_policy()->record_success_degenerated();
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp
index 5a38a0e600f..9fafda229cc 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp
@@ -90,13 +90,21 @@ void ShenandoahDegenGC::op_degenerated() {
   // some phase, we have to upgrade the Degenerate GC to Full GC.
   heap->clear_cancelled_gc(true /* clear oom handler */);
 
-  // We can't easily clear the old mark in progress flag because it must be done
-  // on a safepoint (not sure if that is a hard requirement). At any rate, once
-  // we are in a degenerated cycle, there should be no more old marking.
-  if (heap->is_concurrent_old_mark_in_progress()) {
-    heap->old_generation()->cancel_marking();
+#ifdef ASSERT
+  if (heap->mode()->is_generational()) {
+    if (_generation->generation_mode() == GenerationMode::GLOBAL) {
+      // We can only get to a degenerated global cycle _after_ a concurrent global cycle
+      // has been cancelled. In which case, we expect the concurrent global cycle to have
+      // cancelled the old gc already.
+      assert(!heap->is_old_gc_active(), "Old GC should not be active during global cycle.");
+    }
+
+    if (!heap->is_concurrent_old_mark_in_progress()) {
+      // If we are not marking the old generation, there should be nothing in the old mark queues
+      assert(heap->old_generation()->task_queues()->is_empty(), "Old gen task queues should be empty.");
+    }
   }
-  assert(heap->old_generation()->task_queues()->is_empty(), "Old gen task queues should be empty.");
+#endif
 
   ShenandoahMetricsSnapshot metrics;
   metrics.snap_before();
@@ -113,6 +121,14 @@ void ShenandoahDegenGC::op_degenerated() {
       // we can do the most aggressive degen cycle, which includes processing references and
       // class unloading, unless those features are explicitly disabled.
 
+      if (heap->is_concurrent_old_mark_in_progress()) {
+        // We have come straight into a degenerated cycle without running a concurrent cycle
+        // first and the SATB barrier is enabled to support concurrent old marking. The SATB buffer
+        // may hold a mix of old and young pointers. The old pointers need to be transferred
+        // to the old generation mark queues and the young pointers are _not_ part of this
+        // snapshot, so they must be dropped here.
+        heap->transfer_old_pointers_from_satb();
+      }
 
       // Note that we can only do this for "outside-cycle" degens, otherwise we would risk
       // changing the cycle parameters mid-cycle during concurrent -> degenerated handover.
@@ -125,8 +141,17 @@ void ShenandoahDegenGC::op_degenerated() {
 
     case _degenerated_roots:
       // Degenerated from concurrent root mark, reset the flag for STW mark
-      if (heap->is_concurrent_mark_in_progress()) {
-        heap->cancel_concurrent_mark();
+      if (!heap->mode()->is_generational()) {
+        if (heap->is_concurrent_mark_in_progress()) {
+          heap->cancel_concurrent_mark();
+        }
+      } else {
+        if (_generation->is_concurrent_mark_in_progress()) {
+          // We want to allow old generation marking to be punctuated by young collections
+          // (even if they have degenerated). If this is a global cycle, we'd have cancelled
+          // the entire old gc before coming into this switch.
+          _generation->cancel_marking();
+        }
       }
 
       if (_degen_point == ShenandoahDegenPoint::_degenerated_roots) {
@@ -293,7 +318,7 @@ void ShenandoahDegenGC::op_reset() {
 }
 
 void ShenandoahDegenGC::op_mark() {
-  assert(!ShenandoahHeap::heap()->is_concurrent_mark_in_progress(), "Should be reset");
+  assert(!_generation->is_concurrent_mark_in_progress(), "Should be reset");
   ShenandoahGCPhase phase(ShenandoahPhaseTimings::degen_gc_stw_mark);
   ShenandoahSTWMark mark(_generation, false /*full gc*/);
   mark.mark();
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
index 7286ce9dbde..25349704d62 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
@@ -194,6 +194,11 @@ void ShenandoahFullGC::do_it(GCCause::Cause gc_cause) {
   heap->reset_old_evac_expended();
   heap->set_promotion_reserve(0);
 
+  if (heap->mode()->is_generational()) {
+    // Full GC supersedes any marking or coalescing in old generation.
+    heap->cancel_old_gc();
+  }
+
   if (ShenandoahVerify) {
     heap->verifier()->verify_before_fullgc();
   }
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
index 40967f4407b..f6f36541094 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
@@ -397,12 +397,11 @@ ShenandoahMarkingContext* ShenandoahGeneration::complete_marking_context() {
 
 void ShenandoahGeneration::cancel_marking() {
   if (is_concurrent_mark_in_progress()) {
-    set_concurrent_mark_in_progress(false);
+    set_mark_incomplete();
   }
-  set_mark_incomplete();
   _task_queues->clear();
-
   ref_processor()->abandon_partial_discovery();
+  set_concurrent_mark_in_progress(false);
 }
 
 ShenandoahGeneration::ShenandoahGeneration(GenerationMode generation_mode,
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp
index d01170b8f9c..5669ffc12bd 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp
@@ -109,13 +109,13 @@ class ShenandoahGeneration : public CHeapObj<mtGC> {
   void merge_write_table();
 
   // Used by concurrent and degenerated GC to reset regions.
-  virtual void prepare_gc(bool do_old_gc_bootstrap);
+  void prepare_gc(bool do_old_gc_bootstrap);
 
   // Return true iff prepared collection set includes at least one old-gen HeapRegion.
   virtual bool prepare_regions_and_collection_set(bool concurrent);
 
   // Cancel marking (used by Full collect and when cancelling cycle).
-  void cancel_marking();
+  virtual void cancel_marking();
 
   // Return true if this region is affiliated with this generation.
   virtual bool contains(ShenandoahHeapRegion* region) const = 0;
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp
index b4a22df2f1b..a7299fab186 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp
@@ -58,14 +58,12 @@ size_t ShenandoahGlobalGeneration::available() const {
 
 void ShenandoahGlobalGeneration::set_concurrent_mark_in_progress(bool in_progress) {
   ShenandoahHeap* heap = ShenandoahHeap::heap();
-  if (in_progress && heap->is_concurrent_old_mark_in_progress()) {
+  if (in_progress && heap->mode()->is_generational()) {
     // Global collection has preempted an old generation mark. This is fine
     // because the global generation includes the old generation, but we
     // want the global collect to start from a clean slate and we don't want
     // any stale state in the old generation.
-    heap->purge_old_satb_buffers(true /* abandon */);
-    heap->old_generation()->cancel_marking();
-    heap->young_generation()->set_old_gen_task_queues(nullptr);
+    heap->cancel_old_gc();
   }
 
   heap->set_concurrent_young_mark_in_progress(in_progress);
@@ -88,13 +86,3 @@ bool ShenandoahGlobalGeneration::is_concurrent_mark_in_progress() {
   ShenandoahHeap* heap = ShenandoahHeap::heap();
   return heap->is_concurrent_mark_in_progress();
 }
-
-void ShenandoahGlobalGeneration::prepare_gc(bool do_old_gc_bootstrap) {
-  ShenandoahGeneration::prepare_gc(do_old_gc_bootstrap);
-
-  ShenandoahHeap* heap = ShenandoahHeap::heap();
-  if (heap->mode()->is_generational()) {
-    heap->cancel_mixed_collections();
-  }
-}
-
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp
index 24b4b81fd42..098aad6fa6c 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp
@@ -42,8 +42,6 @@ class ShenandoahGlobalGeneration : public ShenandoahGeneration {
   virtual size_t used() const override;
   virtual size_t available() const override;
 
-  virtual void prepare_gc(bool do_old_gc_bootstrap) override;
-
   virtual void set_concurrent_mark_in_progress(bool in_progress)  override;
 
   bool contains(ShenandoahHeapRegion* region) const  override;
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
index ffe1fc89003..9202c983333 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
@@ -981,9 +981,26 @@ void ShenandoahHeap::retire_plab(PLAB* plab) {
   }
 }
 
-void ShenandoahHeap::cancel_mixed_collections() {
+void ShenandoahHeap::cancel_old_gc() {
+  shenandoah_assert_safepoint();
   assert(_old_generation != NULL, "Should only have mixed collections in generation mode.");
+  log_info(gc)("Terminating old gc cycle.");
+
+  // Stop marking
+  old_generation()->cancel_marking();
+  // Stop coalescing undead objects
+  set_concurrent_prep_for_mixed_evacuation_in_progress(false);
+  // Stop tracking old regions
   old_heuristics()->abandon_collection_candidates();
+  // Remove old generation access to young generation mark queues
+  young_generation()->set_old_gen_task_queues(nullptr);
+}
+
+bool ShenandoahHeap::is_old_gc_active() {
+  return is_concurrent_old_mark_in_progress()
+      || is_concurrent_prep_for_mixed_evacuation_in_progress()
+      || old_heuristics()->unprocessed_old_or_hidden_collection_candidates() > 0
+      || young_generation()->old_gen_task_queues() != nullptr;
 }
 
 void ShenandoahHeap::coalesce_and_fill_old_regions() {
@@ -2111,18 +2128,10 @@ bool ShenandoahHeap::try_cancel_gc() {
     assert(prev == NOT_CANCELLED, "must be NOT_CANCELLED");
     Thread* thread = Thread::current();
     if (thread->is_Java_thread()) {
-      JavaThread* java_thread = JavaThread::cast(thread);
-      if (java_thread->thread_state() == _thread_in_Java) {
-        // ThreadBlockInVM requires thread state to be _thread_in_vm.  If we are in Java, safely transition thread state.
-        ThreadInVMfromJava transition(java_thread);
-        // We need to provide a safepoint here.  Otherwise we might spin forever if a SP is pending.
-        ThreadBlockInVM sp(JavaThread::cast(thread));
-        SpinPause();
-      } else {
-        // We need to provide a safepoint here.  Otherwise we might spin forever if a SP is pending.
-        ThreadBlockInVM sp(JavaThread::cast(thread));
-        SpinPause();
-      }
+      // We need to provide a safepoint here, otherwise we might
+      // spin forever if a SP is pending.
+      ThreadBlockInVM sp(JavaThread::cast(thread));
+      SpinPause();
     }
   }
 }
@@ -2810,8 +2819,8 @@ void ShenandoahHeap::flush_liveness_cache(uint worker_id) {
   }
 }
 
-void ShenandoahHeap::purge_old_satb_buffers(bool abandon) {
-  ((ShenandoahOldGeneration*)_old_generation)->purge_satb_buffers(abandon);
+void ShenandoahHeap::transfer_old_pointers_from_satb() {
+  ((ShenandoahOldGeneration*) _old_generation)->transfer_pointers_from_satb();
 }
 
 template<>
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
index 2ad657831af..e87cc157234 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
@@ -810,7 +810,8 @@ class ShenandoahHeap : public CollectedHeap {
   void clear_cards(HeapWord* start, HeapWord* end);
   void mark_card_as_dirty(void* location);
   void retire_plab(PLAB* plab);
-  void cancel_mixed_collections();
+  void cancel_old_gc();
+  bool is_old_gc_active();
   void coalesce_and_fill_old_regions();
 
 // ---------- Helper functions
@@ -838,7 +839,7 @@ class ShenandoahHeap : public CollectedHeap {
 
   static inline void increase_object_age(oop obj, uint additional_age);
 
-  void purge_old_satb_buffers(bool abandon);
+  void transfer_old_pointers_from_satb();
 private:
   void trash_cset_regions();
 
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp
index 127f4037d06..6ec2cffb8ec 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp
@@ -825,7 +825,7 @@ void ShenandoahHeapRegion::set_affiliation(ShenandoahRegionAffiliation new_affil
   {
     ShenandoahMarkingContext* const ctx = heap->complete_marking_context();
     log_debug(gc)("Setting affiliation of Region " SIZE_FORMAT " from %s to %s, top: " PTR_FORMAT ", TAMS: " PTR_FORMAT
-                  ", watermark: " PTR_FORMAT ", top_bitmap: " PTR_FORMAT "\n",
+                  ", watermark: " PTR_FORMAT ", top_bitmap: " PTR_FORMAT,
                   index(), affiliation_name(_affiliation), affiliation_name(new_affiliation),
                   p2i(top()), p2i(ctx->top_at_mark_start(this)), p2i(_update_watermark), p2i(ctx->top_bitmap(this)));
   }
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp
index 34940f83f0e..af8f5029239 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp
@@ -300,8 +300,10 @@ inline void ShenandoahMark::mark_through_ref(T *p, ShenandoahObjToScanQueue* q,
       // Old mark, found a young pointer.
       // TODO:  Rethink this: may be redundant with dirtying of cards identified during young-gen remembered set scanning
       // and by mutator write barriers.  Assert
-      assert(heap->is_in_young(obj), "Expected young object.");
-      heap->mark_card_as_dirty(p);
+      if (heap->is_in(p)) {
+        assert(heap->is_in_young(obj), "Expected young object.");
+        heap->mark_card_as_dirty(p);
+      }
     }
   }
 }
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp
index 2099726fa8e..90a6ca2345b 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp
@@ -89,7 +89,7 @@ inline void ShenandoahMarkingContext::capture_top_at_mark_start(ShenandoahHeapRe
            "Region " SIZE_FORMAT ", bitmap should be clear while adjusting TAMS: " PTR_FORMAT " -> " PTR_FORMAT,
            idx, p2i(old_tams), p2i(new_tams));
 
-    log_debug(gc)("Capturing TAMS for %s Region " SIZE_FORMAT ", was: %llx, now: %llx\n",
+    log_debug(gc)("Capturing TAMS for %s Region " SIZE_FORMAT ", was: %llx, now: %llx",
                   affiliation_name(r->affiliation()), idx, (unsigned long long) old_tams, (unsigned long long) new_tams);
 
     if ((old_tams == r->bottom()) && (new_tams > old_tams)) {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp
index ac12ff3d215..de70a99c1b8 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp
@@ -146,7 +146,7 @@ bool ShenandoahOldGC::collect(GCCause::Cause cause) {
       }
     }
 
-    if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_mark)) {
+    if (heap->cancelled_gc()) {
       return false;
     }
 
@@ -183,29 +183,32 @@ bool ShenandoahOldGC::collect(GCCause::Cause cause) {
     heap->set_concurrent_prep_for_mixed_evacuation_in_progress(true);
   }
 
+
+  assert(!heap->is_concurrent_strong_root_in_progress(), "No evacuations during old gc.");
+
+  // We must execute this vm operation if we completed final mark. We cannot
+  // return from here with weak roots in progress. This is not a valid gc state
+  // for any young collections (or allocation failures) that interrupt the old
+  // collection.
+  vmop_entry_final_roots(false);
+
   // Coalesce and fill objects _after_ weak root processing and class unloading.
   // Weak root and reference processing makes assertions about unmarked referents
   // that will fail if they've been overwritten with filler objects. There is also
   // a case in the LRB that permits access to from-space objects for the purpose
   // of class unloading that is unlikely to function correctly if the object has
   // been filled.
-
   _allow_preemption.set();
 
-  if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_evac)) {
+  if (heap->cancelled_gc()) {
     return false;
   }
 
-  assert(!heap->is_concurrent_strong_root_in_progress(), "No evacuations during old gc.");
-
-  vmop_entry_final_roots(false);
-
   if (heap->is_concurrent_prep_for_mixed_evacuation_in_progress()) {
     if (!entry_coalesce_and_fill()) {
-      // If old-gen degenerates instead of resuming, we'll just start up an out-of-cycle degenerated GC.
-      // This should be a rare event.  Normally, we'll resume the coalesce-and-fill effort after the
-      // preempting young-gen GC finishes.
-      check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_outside_cycle);
+      // If an allocation failure occurs during coalescing, we will run a degenerated
+      // cycle for the young generation. This should be a rare event.  Normally, we'll
+      // resume the coalesce-and-fill effort after the preempting young-gen GC finishes.
       return false;
     }
   }
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp
index 1640b2ae6d8..f9f6800b66e 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp
@@ -81,12 +81,10 @@ class ShenandoahProcessOldSATB : public SATBBufferClosure {
     for (size_t i = 0; i < size; ++i) {
       oop *p = (oop *) &buffer[i];
       ShenandoahHeapRegion* region = _heap->heap_region_containing(*p);
-      if (region->is_old()) {
-        if (!region->is_trash()) {
+      if (region->is_old() && region->is_active()) {
           ShenandoahMark::mark_through_ref<oop, OLD>(p, _queue, NULL, _mark_context, false);
-        } else {
-          ++_trashed_oops;
-        }
+      } else {
+        ++_trashed_oops;
       }
     }
   }
@@ -158,20 +156,24 @@ bool ShenandoahOldGeneration::is_concurrent_mark_in_progress() {
   return ShenandoahHeap::heap()->is_concurrent_old_mark_in_progress();
 }
 
-void ShenandoahOldGeneration::purge_satb_buffers(bool abandon) {
+void ShenandoahOldGeneration::cancel_marking() {
+  if (is_concurrent_mark_in_progress()) {
+    ShenandoahBarrierSet::satb_mark_queue_set().abandon_partial_marking();
+  }
+
+  ShenandoahGeneration::cancel_marking();
+}
+
+void ShenandoahOldGeneration::transfer_pointers_from_satb() {
   ShenandoahHeap *heap = ShenandoahHeap::heap();
   shenandoah_assert_safepoint();
   assert(heap->is_concurrent_old_mark_in_progress(), "Only necessary during old marking.");
 
-  if (abandon) {
-    ShenandoahBarrierSet::satb_mark_queue_set().abandon_partial_marking();
-  } else {
-    uint nworkers = heap->workers()->active_workers();
-    StrongRootsScope scope(nworkers);
+  uint nworkers = heap->workers()->active_workers();
+  StrongRootsScope scope(nworkers);
 
-    ShenandoahPurgeSATBTask purge_satb_task(task_queues());
-    heap->workers()->run_task(&purge_satb_task);
-  }
+  ShenandoahPurgeSATBTask purge_satb_task(task_queues());
+  heap->workers()->run_task(&purge_satb_task);
 }
 
 bool ShenandoahOldGeneration::contains(oop obj) const {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp
index 1e61d14641d..49dae3e75c1 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp
@@ -46,6 +46,8 @@ class ShenandoahOldGeneration : public ShenandoahGeneration {
 
   void set_concurrent_mark_in_progress(bool in_progress) override;
 
+  virtual void cancel_marking() override;
+
   bool prepare_regions_and_collection_set(bool concurrent) override;
 
   virtual ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode) override;
@@ -68,7 +70,7 @@ class ShenandoahOldGeneration : public ShenandoahGeneration {
   // Alternatively, we could inspect the state of the heap and the age of the
   // object at the barrier, but we reject this approach because it is likely
   // the performance impact would be too severe.
-  void purge_satb_buffers(bool abandon);
+  void transfer_pointers_from_satb();
 
   bool is_concurrent_mark_in_progress() override;
 };