1074 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only iterate roots while world is stopped"); |
1074 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only iterate roots while world is stopped"); |
1075 { |
1075 { |
1076 // Include concurrent roots if current cycle can not process those roots concurrently |
1076 // Include concurrent roots if current cycle can not process those roots concurrently |
1077 ShenandoahRootEvacuator rp(workers()->active_workers(), |
1077 ShenandoahRootEvacuator rp(workers()->active_workers(), |
1078 ShenandoahPhaseTimings::init_evac, |
1078 ShenandoahPhaseTimings::init_evac, |
1079 !ShenandoahConcurrentRoots::should_do_concurrent_roots()); |
1079 !ShenandoahConcurrentRoots::should_do_concurrent_roots(), |
|
1080 !ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()); |
1080 ShenandoahEvacuateUpdateRootsTask roots_task(&rp); |
1081 ShenandoahEvacuateUpdateRootsTask roots_task(&rp); |
1081 workers()->run_task(&roots_task); |
1082 workers()->run_task(&roots_task); |
1082 } |
1083 } |
1083 |
1084 |
1084 #if COMPILER2_OR_JVMCI |
1085 #if COMPILER2_OR_JVMCI |
1546 set_evacuation_in_progress(true); |
1547 set_evacuation_in_progress(true); |
1547 // From here on, we need to update references. |
1548 // From here on, we need to update references. |
1548 set_has_forwarded_objects(true); |
1549 set_has_forwarded_objects(true); |
1549 |
1550 |
1550 if (!is_degenerated_gc_in_progress()) { |
1551 if (!is_degenerated_gc_in_progress()) { |
|
1552 prepare_concurrent_roots(); |
|
1553 prepare_concurrent_unloading(); |
1551 evacuate_and_update_roots(); |
1554 evacuate_and_update_roots(); |
1552 } |
1555 } |
1553 |
1556 |
1554 if (ShenandoahPacing) { |
1557 if (ShenandoahPacing) { |
1555 pacer()->setup_for_evac(); |
1558 pacer()->setup_for_evac(); |
1556 } |
1559 } |
1557 |
1560 |
1558 if (ShenandoahVerify) { |
1561 if (ShenandoahVerify) { |
|
1562 ShenandoahRootVerifier::RootTypes types = ShenandoahRootVerifier::None; |
1559 if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) { |
1563 if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) { |
1560 ShenandoahRootVerifier::RootTypes types = ShenandoahRootVerifier::combine(ShenandoahRootVerifier::JNIHandleRoots, ShenandoahRootVerifier::WeakRoots); |
1564 types = ShenandoahRootVerifier::combine(ShenandoahRootVerifier::JNIHandleRoots, ShenandoahRootVerifier::WeakRoots); |
1561 types = ShenandoahRootVerifier::combine(types, ShenandoahRootVerifier::CLDGRoots); |
1565 types = ShenandoahRootVerifier::combine(types, ShenandoahRootVerifier::CLDGRoots); |
1562 verifier()->verify_roots_no_forwarded_except(types); |
|
1563 } else { |
|
1564 verifier()->verify_roots_no_forwarded(); |
|
1565 } |
1566 } |
|
1567 |
|
1568 if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) { |
|
1569 types = ShenandoahRootVerifier::combine(types, ShenandoahRootVerifier::CodeRoots); |
|
1570 } |
|
1571 verifier()->verify_roots_no_forwarded_except(types); |
1566 verifier()->verify_during_evacuation(); |
1572 verifier()->verify_during_evacuation(); |
1567 } |
1573 } |
1568 } else { |
1574 } else { |
1569 if (ShenandoahVerify) { |
1575 if (ShenandoahVerify) { |
1570 verifier()->verify_after_concmark(); |
1576 verifier()->verify_after_concmark(); |
1656 } |
1662 } |
1657 } |
1663 } |
1658 }; |
1664 }; |
1659 |
1665 |
1660 void ShenandoahHeap::op_roots() { |
1666 void ShenandoahHeap::op_roots() { |
1661 if (is_evacuation_in_progress() && |
1667 if (is_evacuation_in_progress()) { |
1662 ShenandoahConcurrentRoots::should_do_concurrent_roots()) { |
1668 if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) { |
1663 ShenandoahConcurrentRootsEvacUpdateTask task; |
1669 _unloader.unload(); |
1664 workers()->run_task(&task); |
1670 } |
1665 } |
1671 |
|
1672 if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) { |
|
1673 ShenandoahConcurrentRootsEvacUpdateTask task; |
|
1674 workers()->run_task(&task); |
|
1675 } |
|
1676 } |
|
1677 |
|
1678 set_concurrent_root_in_progress(false); |
1666 } |
1679 } |
1667 |
1680 |
1668 void ShenandoahHeap::op_reset() { |
1681 void ShenandoahHeap::op_reset() { |
1669 reset_mark_bitmap(); |
1682 reset_mark_bitmap(); |
1670 } |
1683 } |
1918 void ShenandoahHeap::set_evacuation_in_progress(bool in_progress) { |
1931 void ShenandoahHeap::set_evacuation_in_progress(bool in_progress) { |
1919 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only call this at safepoint"); |
1932 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only call this at safepoint"); |
1920 set_gc_state_mask(EVACUATION, in_progress); |
1933 set_gc_state_mask(EVACUATION, in_progress); |
1921 } |
1934 } |
1922 |
1935 |
|
1936 void ShenandoahHeap::set_concurrent_root_in_progress(bool in_progress) { |
|
1937 assert(ShenandoahConcurrentRoots::can_do_concurrent_roots(), "Why set the flag?"); |
|
1938 if (in_progress) { |
|
1939 _concurrent_root_in_progress.set(); |
|
1940 } else { |
|
1941 _concurrent_root_in_progress.unset(); |
|
1942 } |
|
1943 } |
|
1944 |
1923 void ShenandoahHeap::ref_processing_init() { |
1945 void ShenandoahHeap::ref_processing_init() { |
1924 assert(_max_workers > 0, "Sanity"); |
1946 assert(_max_workers > 0, "Sanity"); |
1925 |
1947 |
1926 _ref_processor = |
1948 _ref_processor = |
1927 new ReferenceProcessor(&_subject_to_discovery, // is_subject_to_discovery |
1949 new ReferenceProcessor(&_subject_to_discovery, // is_subject_to_discovery |
2026 // Resize and verify metaspace |
2048 // Resize and verify metaspace |
2027 MetaspaceGC::compute_new_size(); |
2049 MetaspaceGC::compute_new_size(); |
2028 MetaspaceUtils::verify_metrics(); |
2050 MetaspaceUtils::verify_metrics(); |
2029 } |
2051 } |
2030 |
2052 |
2031 // Process leftover weak oops: update them, if needed or assert they do not |
2053 // Weak roots are either pre-evacuated (final mark) or updated (final updaterefs), |
2032 // need updating otherwise. |
2054 // so they should not have forwarded oops. |
2033 // Weak processor API requires us to visit the oops, even if we are not doing |
2055 // However, we do need to "null" dead oops in the roots, if can not be done |
2034 // anything to them. |
2056 // in concurrent cycles. |
2035 void ShenandoahHeap::stw_process_weak_roots(bool full_gc) { |
2057 void ShenandoahHeap::stw_process_weak_roots(bool full_gc) { |
2036 ShenandoahGCPhase root_phase(full_gc ? |
2058 ShenandoahGCPhase root_phase(full_gc ? |
2037 ShenandoahPhaseTimings::full_gc_purge : |
2059 ShenandoahPhaseTimings::full_gc_purge : |
2038 ShenandoahPhaseTimings::purge); |
2060 ShenandoahPhaseTimings::purge); |
2039 uint num_workers = _workers->active_workers(); |
2061 uint num_workers = _workers->active_workers(); |
2071 } |
2093 } |
2072 |
2094 |
2073 void ShenandoahHeap::parallel_cleaning(bool full_gc) { |
2095 void ShenandoahHeap::parallel_cleaning(bool full_gc) { |
2074 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); |
2096 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); |
2075 stw_process_weak_roots(full_gc); |
2097 stw_process_weak_roots(full_gc); |
2076 stw_unload_classes(full_gc); |
2098 if (!ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) { |
|
2099 stw_unload_classes(full_gc); |
|
2100 } |
2077 } |
2101 } |
2078 |
2102 |
2079 void ShenandoahHeap::set_has_forwarded_objects(bool cond) { |
2103 void ShenandoahHeap::set_has_forwarded_objects(bool cond) { |
2080 if (is_traversal_mode()) { |
2104 if (is_traversal_mode()) { |
2081 set_gc_state_mask(HAS_FORWARDED | UPDATEREFS, cond); |
2105 set_gc_state_mask(HAS_FORWARDED | UPDATEREFS, cond); |
2139 void ShenandoahHeap::set_update_refs_in_progress(bool in_progress) { |
2163 void ShenandoahHeap::set_update_refs_in_progress(bool in_progress) { |
2140 set_gc_state_mask(UPDATEREFS, in_progress); |
2164 set_gc_state_mask(UPDATEREFS, in_progress); |
2141 } |
2165 } |
2142 |
2166 |
2143 void ShenandoahHeap::register_nmethod(nmethod* nm) { |
2167 void ShenandoahHeap::register_nmethod(nmethod* nm) { |
2144 ShenandoahCodeRoots::add_nmethod(nm); |
2168 ShenandoahCodeRoots::register_nmethod(nm); |
2145 } |
2169 } |
2146 |
2170 |
2147 void ShenandoahHeap::unregister_nmethod(nmethod* nm) { |
2171 void ShenandoahHeap::unregister_nmethod(nmethod* nm) { |
2148 ShenandoahCodeRoots::remove_nmethod(nm); |
2172 ShenandoahCodeRoots::unregister_nmethod(nm); |
|
2173 } |
|
2174 |
|
2175 void ShenandoahHeap::flush_nmethod(nmethod* nm) { |
|
2176 ShenandoahCodeRoots::flush_nmethod(nm); |
2149 } |
2177 } |
2150 |
2178 |
2151 oop ShenandoahHeap::pin_object(JavaThread* thr, oop o) { |
2179 oop ShenandoahHeap::pin_object(JavaThread* thr, oop o) { |
2152 heap_region_containing(o)->record_pin(); |
2180 heap_region_containing(o)->record_pin(); |
2153 return o; |
2181 return o; |
2188 } |
2216 } |
2189 #endif |
2217 #endif |
2190 |
2218 |
2191 GCTimer* ShenandoahHeap::gc_timer() const { |
2219 GCTimer* ShenandoahHeap::gc_timer() const { |
2192 return _gc_timer; |
2220 return _gc_timer; |
|
2221 } |
|
2222 |
|
2223 void ShenandoahHeap::prepare_concurrent_roots() { |
|
2224 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); |
|
2225 if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) { |
|
2226 set_concurrent_root_in_progress(true); |
|
2227 } |
|
2228 } |
|
2229 |
|
2230 void ShenandoahHeap::prepare_concurrent_unloading() { |
|
2231 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); |
|
2232 if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) { |
|
2233 ShenandoahCodeRoots::prepare_concurrent_unloading(); |
|
2234 _unloader.prepare(); |
|
2235 } |
|
2236 } |
|
2237 |
|
2238 void ShenandoahHeap::finish_concurrent_unloading() { |
|
2239 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); |
|
2240 if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) { |
|
2241 _unloader.finish(); |
|
2242 } |
2193 } |
2243 } |
2194 |
2244 |
2195 #ifdef ASSERT |
2245 #ifdef ASSERT |
2196 void ShenandoahHeap::assert_gc_workers(uint nworkers) { |
2246 void ShenandoahHeap::assert_gc_workers(uint nworkers) { |
2197 assert(nworkers > 0 && nworkers <= max_workers(), "Sanity"); |
2247 assert(nworkers > 0 && nworkers <= max_workers(), "Sanity"); |
2313 } |
2363 } |
2314 |
2364 |
2315 void ShenandoahHeap::op_final_updaterefs() { |
2365 void ShenandoahHeap::op_final_updaterefs() { |
2316 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at safepoint"); |
2366 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at safepoint"); |
2317 |
2367 |
|
2368 finish_concurrent_unloading(); |
|
2369 |
2318 // Check if there is left-over work, and finish it |
2370 // Check if there is left-over work, and finish it |
2319 if (_update_refs_iterator.has_next()) { |
2371 if (_update_refs_iterator.has_next()) { |
2320 ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_finish_work); |
2372 ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_finish_work); |
2321 |
2373 |
2322 // Finish updating references where we left off. |
2374 // Finish updating references where we left off. |
2330 clear_cancelled_gc(); |
2382 clear_cancelled_gc(); |
2331 } |
2383 } |
2332 assert(!cancelled_gc(), "Should have been done right before"); |
2384 assert(!cancelled_gc(), "Should have been done right before"); |
2333 |
2385 |
2334 if (ShenandoahVerify && !is_degenerated_gc_in_progress()) { |
2386 if (ShenandoahVerify && !is_degenerated_gc_in_progress()) { |
2335 verifier()->verify_roots_no_forwarded_except(ShenandoahRootVerifier::ThreadRoots); |
2387 verifier()->verify_roots_in_to_space_except(ShenandoahRootVerifier::ThreadRoots); |
2336 } |
2388 } |
2337 |
2389 |
2338 if (is_degenerated_gc_in_progress()) { |
2390 if (is_degenerated_gc_in_progress()) { |
2339 concurrent_mark()->update_roots(ShenandoahPhaseTimings::degen_gc_update_roots); |
2391 concurrent_mark()->update_roots(ShenandoahPhaseTimings::degen_gc_update_roots); |
2340 } else { |
2392 } else { |