1478 // get unmarked objects in the roots. |
1478 // get unmarked objects in the roots. |
1479 |
1479 |
1480 if (!cancelled_gc()) { |
1480 if (!cancelled_gc()) { |
1481 concurrent_mark()->finish_mark_from_roots(/* full_gc = */ false); |
1481 concurrent_mark()->finish_mark_from_roots(/* full_gc = */ false); |
1482 |
1482 |
|
1483 // Marking is completed, deactivate SATB barrier |
|
1484 set_concurrent_mark_in_progress(false); |
|
1485 mark_complete_marking_context(); |
|
1486 |
|
1487 parallel_cleaning(false /* full gc*/); |
|
1488 |
1483 if (has_forwarded_objects()) { |
1489 if (has_forwarded_objects()) { |
1484 // Degen may be caused by failed evacuation of roots |
1490 // Degen may be caused by failed evacuation of roots |
1485 if (is_degenerated_gc_in_progress()) { |
1491 if (is_degenerated_gc_in_progress()) { |
1486 concurrent_mark()->update_roots(ShenandoahPhaseTimings::degen_gc_update_roots); |
1492 concurrent_mark()->update_roots(ShenandoahPhaseTimings::degen_gc_update_roots); |
1487 } else { |
1493 } else { |
1488 concurrent_mark()->update_thread_roots(ShenandoahPhaseTimings::update_roots); |
1494 concurrent_mark()->update_thread_roots(ShenandoahPhaseTimings::update_roots); |
1489 } |
1495 } |
|
1496 set_has_forwarded_objects(false); |
1490 } |
1497 } |
1491 |
1498 |
1492 if (ShenandoahVerify) { |
1499 if (ShenandoahVerify) { |
1493 verifier()->verify_roots_no_forwarded(); |
1500 verifier()->verify_roots_no_forwarded(); |
1494 } |
1501 } |
1495 |
1502 // All allocations past TAMS are implicitly live, adjust the region data. |
1496 stop_concurrent_marking(); |
1503 // Bitmaps/TAMS are swapped at this point, so we need to poll complete bitmap. |
1497 |
|
1498 { |
1504 { |
1499 ShenandoahGCPhase phase(ShenandoahPhaseTimings::complete_liveness); |
1505 ShenandoahGCPhase phase(ShenandoahPhaseTimings::complete_liveness); |
1500 |
|
1501 // All allocations past TAMS are implicitly live, adjust the region data. |
|
1502 // Bitmaps/TAMS are swapped at this point, so we need to poll complete bitmap. |
|
1503 ShenandoahCompleteLivenessClosure cl; |
1506 ShenandoahCompleteLivenessClosure cl; |
1504 parallel_heap_region_iterate(&cl); |
1507 parallel_heap_region_iterate(&cl); |
1505 } |
1508 } |
1506 |
1509 |
|
1510 // Force the threads to reacquire their TLABs outside the collection set. |
1507 { |
1511 { |
1508 ShenandoahGCPhase prepare_evac(ShenandoahPhaseTimings::prepare_evac); |
1512 ShenandoahGCPhase phase(ShenandoahPhaseTimings::retire_tlabs); |
1509 |
|
1510 make_parsable(true); |
1513 make_parsable(true); |
1511 |
1514 } |
|
1515 |
|
1516 // We are about to select the collection set, make sure it knows about |
|
1517 // current pinning status. Also, this allows trashing more regions that |
|
1518 // now have their pinning status dropped. |
|
1519 { |
|
1520 ShenandoahGCPhase phase(ShenandoahPhaseTimings::sync_pinned); |
|
1521 sync_pinned_region_status(); |
|
1522 } |
|
1523 |
|
1524 // Trash the collection set left over from previous cycle, if any. |
|
1525 { |
|
1526 ShenandoahGCPhase phase(ShenandoahPhaseTimings::trash_cset); |
1512 trash_cset_regions(); |
1527 trash_cset_regions(); |
1513 |
1528 } |
1514 { |
1529 |
1515 ShenandoahHeapLocker locker(lock()); |
1530 { |
1516 _collection_set->clear(); |
1531 ShenandoahGCPhase phase(ShenandoahPhaseTimings::prepare_evac); |
1517 _free_set->clear(); |
1532 |
1518 |
1533 ShenandoahHeapLocker locker(lock()); |
1519 heuristics()->choose_collection_set(_collection_set); |
1534 _collection_set->clear(); |
1520 |
1535 _free_set->clear(); |
1521 _free_set->rebuild(); |
1536 |
1522 } |
1537 heuristics()->choose_collection_set(_collection_set); |
|
1538 |
|
1539 _free_set->rebuild(); |
1523 } |
1540 } |
1524 |
1541 |
1525 // If collection set has candidates, start evacuation. |
1542 // If collection set has candidates, start evacuation. |
1526 // Otherwise, bypass the rest of the cycle. |
1543 // Otherwise, bypass the rest of the cycle. |
1527 if (!collection_set()->is_empty()) { |
1544 if (!collection_set()->is_empty()) { |
1562 Universe::verify(); |
1579 Universe::verify(); |
1563 } |
1580 } |
1564 } |
1581 } |
1565 |
1582 |
1566 } else { |
1583 } else { |
|
1584 // If this cycle was updating references, we need to keep the has_forwarded_objects |
|
1585 // flag on, for subsequent phases to deal with it. |
1567 concurrent_mark()->cancel(); |
1586 concurrent_mark()->cancel(); |
1568 stop_concurrent_marking(); |
1587 set_concurrent_mark_in_progress(false); |
1569 |
1588 |
1570 if (process_references()) { |
1589 if (process_references()) { |
1571 // Abandon reference processing right away: pre-cleaning must have failed. |
1590 // Abandon reference processing right away: pre-cleaning must have failed. |
1572 ReferenceProcessor *rp = ref_processor(); |
1591 ReferenceProcessor *rp = ref_processor(); |
1573 rp->disable_discovery(); |
1592 rp->disable_discovery(); |
1776 // the collection set, and then the pin reached the cset region. If we continue |
1798 // the collection set, and then the pin reached the cset region. If we continue |
1777 // the cycle here, we would trash the cset and alive objects in it. To avoid |
1799 // the cycle here, we would trash the cset and alive objects in it. To avoid |
1778 // it, we fail degeneration right away and slide into Full GC to recover. |
1800 // it, we fail degeneration right away and slide into Full GC to recover. |
1779 |
1801 |
1780 { |
1802 { |
|
1803 sync_pinned_region_status(); |
1781 collection_set()->clear_current_index(); |
1804 collection_set()->clear_current_index(); |
1782 |
1805 |
1783 ShenandoahHeapRegion* r; |
1806 ShenandoahHeapRegion* r; |
1784 while ((r = collection_set()->next()) != NULL) { |
1807 while ((r = collection_set()->next()) != NULL) { |
1785 if (r->is_pinned()) { |
1808 if (r->is_pinned()) { |
1855 void ShenandoahHeap::op_degenerated_futile() { |
1878 void ShenandoahHeap::op_degenerated_futile() { |
1856 shenandoah_policy()->record_degenerated_upgrade_to_full(); |
1879 shenandoah_policy()->record_degenerated_upgrade_to_full(); |
1857 op_full(GCCause::_shenandoah_upgrade_to_full_gc); |
1880 op_full(GCCause::_shenandoah_upgrade_to_full_gc); |
1858 } |
1881 } |
1859 |
1882 |
1860 void ShenandoahHeap::stop_concurrent_marking() { |
|
1861 assert(is_concurrent_mark_in_progress(), "How else could we get here?"); |
|
1862 set_concurrent_mark_in_progress(false); |
|
1863 if (!cancelled_gc()) { |
|
1864 // If we needed to update refs, and concurrent marking has been cancelled, |
|
1865 // we need to finish updating references. |
|
1866 set_has_forwarded_objects(false); |
|
1867 mark_complete_marking_context(); |
|
1868 } |
|
1869 } |
|
1870 |
|
1871 void ShenandoahHeap::force_satb_flush_all_threads() { |
1883 void ShenandoahHeap::force_satb_flush_all_threads() { |
1872 if (!is_concurrent_mark_in_progress() && !is_concurrent_traversal_in_progress()) { |
1884 if (!is_concurrent_mark_in_progress() && !is_concurrent_traversal_in_progress()) { |
1873 // No need to flush SATBs |
1885 // No need to flush SATBs |
1874 return; |
1886 return; |
1875 } |
1887 } |
1902 } |
1914 } |
1903 ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); |
1915 ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); |
1904 } |
1916 } |
1905 |
1917 |
1906 void ShenandoahHeap::set_concurrent_traversal_in_progress(bool in_progress) { |
1918 void ShenandoahHeap::set_concurrent_traversal_in_progress(bool in_progress) { |
1907 set_gc_state_mask(TRAVERSAL | HAS_FORWARDED | UPDATEREFS, in_progress); |
1919 set_gc_state_mask(TRAVERSAL, in_progress); |
1908 ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); |
1920 ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); |
1909 } |
1921 } |
1910 |
1922 |
1911 void ShenandoahHeap::set_evacuation_in_progress(bool in_progress) { |
1923 void ShenandoahHeap::set_evacuation_in_progress(bool in_progress) { |
1912 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only call this at safepoint"); |
1924 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only call this at safepoint"); |
2033 ShenandoahPhaseTimings::full_gc_purge_par : |
2045 ShenandoahPhaseTimings::full_gc_purge_par : |
2034 ShenandoahPhaseTimings::purge_par; |
2046 ShenandoahPhaseTimings::purge_par; |
2035 // Cleanup weak roots |
2047 // Cleanup weak roots |
2036 ShenandoahGCPhase phase(timing_phase); |
2048 ShenandoahGCPhase phase(timing_phase); |
2037 if (has_forwarded_objects()) { |
2049 if (has_forwarded_objects()) { |
2038 ShenandoahForwardedIsAliveClosure is_alive; |
2050 if (is_traversal_mode()) { |
2039 ShenandoahUpdateRefsClosure keep_alive; |
2051 ShenandoahForwardedIsAliveClosure is_alive; |
2040 ShenandoahParallelWeakRootsCleaningTask<ShenandoahForwardedIsAliveClosure, ShenandoahUpdateRefsClosure> |
2052 ShenandoahTraversalUpdateRefsClosure keep_alive; |
2041 cleaning_task(&is_alive, &keep_alive, num_workers); |
2053 ShenandoahParallelWeakRootsCleaningTask<ShenandoahForwardedIsAliveClosure, ShenandoahTraversalUpdateRefsClosure> |
2042 _workers->run_task(&cleaning_task); |
2054 cleaning_task(&is_alive, &keep_alive, num_workers); |
|
2055 _workers->run_task(&cleaning_task); |
|
2056 } else { |
|
2057 ShenandoahForwardedIsAliveClosure is_alive; |
|
2058 ShenandoahUpdateRefsClosure keep_alive; |
|
2059 ShenandoahParallelWeakRootsCleaningTask<ShenandoahForwardedIsAliveClosure, ShenandoahUpdateRefsClosure> |
|
2060 cleaning_task(&is_alive, &keep_alive, num_workers); |
|
2061 _workers->run_task(&cleaning_task); |
|
2062 } |
2043 } else { |
2063 } else { |
2044 ShenandoahIsAliveClosure is_alive; |
2064 ShenandoahIsAliveClosure is_alive; |
2045 #ifdef ASSERT |
2065 #ifdef ASSERT |
2046 ShenandoahAssertNotForwardedClosure verify_cl; |
2066 ShenandoahAssertNotForwardedClosure verify_cl; |
2047 ShenandoahParallelWeakRootsCleaningTask<ShenandoahIsAliveClosure, ShenandoahAssertNotForwardedClosure> |
2067 ShenandoahParallelWeakRootsCleaningTask<ShenandoahIsAliveClosure, ShenandoahAssertNotForwardedClosure> |
2059 stw_process_weak_roots(full_gc); |
2079 stw_process_weak_roots(full_gc); |
2060 stw_unload_classes(full_gc); |
2080 stw_unload_classes(full_gc); |
2061 } |
2081 } |
2062 |
2082 |
2063 void ShenandoahHeap::set_has_forwarded_objects(bool cond) { |
2083 void ShenandoahHeap::set_has_forwarded_objects(bool cond) { |
2064 set_gc_state_mask(HAS_FORWARDED, cond); |
2084 if (is_traversal_mode()) { |
|
2085 set_gc_state_mask(HAS_FORWARDED | UPDATEREFS, cond); |
|
2086 } else { |
|
2087 set_gc_state_mask(HAS_FORWARDED, cond); |
|
2088 } |
|
2089 |
2065 } |
2090 } |
2066 |
2091 |
2067 void ShenandoahHeap::set_process_references(bool pr) { |
2092 void ShenandoahHeap::set_process_references(bool pr) { |
2068 _process_references.set_cond(pr); |
2093 _process_references.set_cond(pr); |
2069 } |
2094 } |
2126 void ShenandoahHeap::unregister_nmethod(nmethod* nm) { |
2151 void ShenandoahHeap::unregister_nmethod(nmethod* nm) { |
2127 ShenandoahCodeRoots::remove_nmethod(nm); |
2152 ShenandoahCodeRoots::remove_nmethod(nm); |
2128 } |
2153 } |
2129 |
2154 |
2130 oop ShenandoahHeap::pin_object(JavaThread* thr, oop o) { |
2155 oop ShenandoahHeap::pin_object(JavaThread* thr, oop o) { |
|
2156 heap_region_containing(o)->record_pin(); |
|
2157 return o; |
|
2158 } |
|
2159 |
|
2160 void ShenandoahHeap::unpin_object(JavaThread* thr, oop o) { |
|
2161 heap_region_containing(o)->record_unpin(); |
|
2162 } |
|
2163 |
|
2164 void ShenandoahHeap::sync_pinned_region_status() { |
2131 ShenandoahHeapLocker locker(lock()); |
2165 ShenandoahHeapLocker locker(lock()); |
2132 heap_region_containing(o)->make_pinned(); |
2166 |
2133 return o; |
2167 for (size_t i = 0; i < num_regions(); i++) { |
2134 } |
2168 ShenandoahHeapRegion *r = get_region(i); |
2135 |
2169 if (r->is_active()) { |
2136 void ShenandoahHeap::unpin_object(JavaThread* thr, oop o) { |
2170 if (r->is_pinned()) { |
2137 ShenandoahHeapLocker locker(lock()); |
2171 if (r->pin_count() == 0) { |
2138 heap_region_containing(o)->make_unpinned(); |
2172 r->make_unpinned(); |
2139 } |
2173 } |
|
2174 } else { |
|
2175 if (r->pin_count() > 0) { |
|
2176 r->make_pinned(); |
|
2177 } |
|
2178 } |
|
2179 } |
|
2180 } |
|
2181 |
|
2182 assert_pinned_region_status(); |
|
2183 } |
|
2184 |
|
2185 #ifdef ASSERT |
|
2186 void ShenandoahHeap::assert_pinned_region_status() { |
|
2187 for (size_t i = 0; i < num_regions(); i++) { |
|
2188 ShenandoahHeapRegion* r = get_region(i); |
|
2189 assert((r->is_pinned() && r->pin_count() > 0) || (!r->is_pinned() && r->pin_count() == 0), |
|
2190 "Region " SIZE_FORMAT " pinning status is inconsistent", i); |
|
2191 } |
|
2192 } |
|
2193 #endif |
2140 |
2194 |
2141 GCTimer* ShenandoahHeap::gc_timer() const { |
2195 GCTimer* ShenandoahHeap::gc_timer() const { |
2142 return _gc_timer; |
2196 return _gc_timer; |
2143 } |
2197 } |
2144 |
2198 |
2228 void ShenandoahHeap::op_init_updaterefs() { |
2282 void ShenandoahHeap::op_init_updaterefs() { |
2229 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at safepoint"); |
2283 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at safepoint"); |
2230 |
2284 |
2231 set_evacuation_in_progress(false); |
2285 set_evacuation_in_progress(false); |
2232 |
2286 |
2233 retire_and_reset_gclabs(); |
2287 { |
|
2288 ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_refs_retire_gclabs); |
|
2289 retire_and_reset_gclabs(); |
|
2290 } |
2234 |
2291 |
2235 if (ShenandoahVerify) { |
2292 if (ShenandoahVerify) { |
2236 if (!is_degenerated_gc_in_progress()) { |
2293 if (!is_degenerated_gc_in_progress()) { |
2237 verifier()->verify_roots_no_forwarded_except(ShenandoahRootVerifier::ThreadRoots); |
2294 verifier()->verify_roots_no_forwarded_except(ShenandoahRootVerifier::ThreadRoots); |
2238 } |
2295 } |
2239 verifier()->verify_before_updaterefs(); |
2296 verifier()->verify_before_updaterefs(); |
2240 } |
2297 } |
2241 |
2298 |
2242 set_update_refs_in_progress(true); |
2299 set_update_refs_in_progress(true); |
2243 make_parsable(true); |
2300 |
2244 for (uint i = 0; i < num_regions(); i++) { |
2301 { |
2245 ShenandoahHeapRegion* r = get_region(i); |
2302 ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_refs_prepare); |
2246 r->set_concurrent_iteration_safe_limit(r->top()); |
2303 |
2247 } |
2304 make_parsable(true); |
2248 |
2305 for (uint i = 0; i < num_regions(); i++) { |
2249 // Reset iterator. |
2306 ShenandoahHeapRegion* r = get_region(i); |
2250 _update_refs_iterator.reset(); |
2307 r->set_concurrent_iteration_safe_limit(r->top()); |
|
2308 } |
|
2309 |
|
2310 // Reset iterator. |
|
2311 _update_refs_iterator.reset(); |
|
2312 } |
2251 |
2313 |
2252 if (ShenandoahPacing) { |
2314 if (ShenandoahPacing) { |
2253 pacer()->setup_for_updaterefs(); |
2315 pacer()->setup_for_updaterefs(); |
2254 } |
2316 } |
2255 } |
2317 } |
2257 void ShenandoahHeap::op_final_updaterefs() { |
2319 void ShenandoahHeap::op_final_updaterefs() { |
2258 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at safepoint"); |
2320 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at safepoint"); |
2259 |
2321 |
2260 // Check if there is left-over work, and finish it |
2322 // Check if there is left-over work, and finish it |
2261 if (_update_refs_iterator.has_next()) { |
2323 if (_update_refs_iterator.has_next()) { |
2262 ShenandoahGCPhase final_work(ShenandoahPhaseTimings::final_update_refs_finish_work); |
2324 ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_finish_work); |
2263 |
2325 |
2264 // Finish updating references where we left off. |
2326 // Finish updating references where we left off. |
2265 clear_cancelled_gc(); |
2327 clear_cancelled_gc(); |
2266 update_heap_references(false); |
2328 update_heap_references(false); |
2267 } |
2329 } |
2286 // Has to be done before cset is clear |
2348 // Has to be done before cset is clear |
2287 if (ShenandoahVerify) { |
2349 if (ShenandoahVerify) { |
2288 verifier()->verify_roots_in_to_space(); |
2350 verifier()->verify_roots_in_to_space(); |
2289 } |
2351 } |
2290 |
2352 |
2291 ShenandoahGCPhase final_update_refs(ShenandoahPhaseTimings::final_update_refs_recycle); |
2353 // Drop unnecessary "pinned" state from regions that does not have CP marks |
2292 |
2354 // anymore, as this would allow trashing them below. |
2293 trash_cset_regions(); |
2355 { |
|
2356 ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_sync_pinned); |
|
2357 sync_pinned_region_status(); |
|
2358 } |
|
2359 |
|
2360 { |
|
2361 ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_trash_cset); |
|
2362 trash_cset_regions(); |
|
2363 } |
|
2364 |
2294 set_has_forwarded_objects(false); |
2365 set_has_forwarded_objects(false); |
2295 set_update_refs_in_progress(false); |
2366 set_update_refs_in_progress(false); |
2296 |
2367 |
2297 if (ShenandoahVerify) { |
2368 if (ShenandoahVerify) { |
2298 verifier()->verify_after_updaterefs(); |
2369 verifier()->verify_after_updaterefs(); |