< prev index next >

src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp

Print this page
rev 57223 : 8235337: Shenandoah: Fix evac OOM scoping for concurrent class unloading


   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #include "precompiled.hpp"
  25 #include "code/codeCache.hpp"
  26 #include "code/icBuffer.hpp"
  27 #include "code/nmethod.hpp"
  28 #include "gc/shenandoah/shenandoahCodeRoots.hpp"

  29 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  30 #include "gc/shenandoah/shenandoahNMethod.inline.hpp"
  31 #include "gc/shenandoah/shenandoahUtils.hpp"
  32 #include "memory/resourceArea.hpp"
  33 #include "memory/universe.hpp"
  34 #include "runtime/atomic.hpp"
  35 
  36 ShenandoahParallelCodeCacheIterator::ShenandoahParallelCodeCacheIterator(const GrowableArray<CodeHeap*>* heaps) {
  37   _length = heaps->length();
  38   _iters = NEW_C_HEAP_ARRAY(ShenandoahParallelCodeHeapIterator, _length, mtGC);
  39   for (int h = 0; h < _length; h++) {
  40     _iters[h] = ShenandoahParallelCodeHeapIterator(heaps->at(h));
  41   }
  42 }
  43 
  44 ShenandoahParallelCodeCacheIterator::~ShenandoahParallelCodeCacheIterator() {
  45   FREE_C_HEAP_ARRAY(ParallelCodeHeapIterator, _iters);
  46 }
  47 
  48 void ShenandoahParallelCodeCacheIterator::parallel_blobs_do(CodeBlobClosure* f) {


 204     if (failed()) {
 205       return;
 206     }
 207 
 208     ShenandoahNMethod* nm_data = ShenandoahNMethod::gc_data(nm);
 209     assert(!nm_data->is_unregistered(), "Should not see unregistered entry");
 210 
 211     if (!nm->is_alive()) {
 212       return;
 213     }
 214 
 215     if (nm->is_unloading()) {
 216       ShenandoahReentrantLocker locker(nm_data->lock());
 217       unlink(nm);
 218       return;
 219     }
 220 
 221     ShenandoahReentrantLocker locker(nm_data->lock());
 222 
 223     // Heal oops and disarm
 224     ShenandoahEvacOOMScope scope;
 225     ShenandoahNMethod::heal_nmethod(nm);
 226     ShenandoahNMethod::disarm_nmethod(nm);
 227 
 228     // Clear compiled ICs and exception caches
 229     if (!nm->unload_nmethod_caches(_unloading_occurred)) {
 230       set_failed();
 231     }
 232   }
 233 
 234   bool failed() const {
 235     return Atomic::load(&_failed);
 236   }
 237 };
 238 
 239 class ShenandoahUnlinkTask : public AbstractGangTask {
 240 private:
 241   ShenandoahNMethodUnlinkClosure      _cl;
 242   ICRefillVerifier*                   _verifier;
 243   ShenandoahConcurrentNMethodIterator _iterator;
 244 
 245 public:
 246   ShenandoahUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
 247     AbstractGangTask("ShenandoahNMethodUnlinkTask"),
 248     _cl(unloading_occurred),
 249     _verifier(verifier),
 250     _iterator(ShenandoahCodeRoots::table()) {
 251     MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 252     _iterator.nmethods_do_begin();
 253   }
 254 
 255   ~ShenandoahUnlinkTask() {
 256     MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 257     _iterator.nmethods_do_end();
 258   }
 259 
 260   virtual void work(uint worker_id) {

 261     ICRefillVerifierMark mark(_verifier);
 262     _iterator.nmethods_do(&_cl);
 263   }
 264 
 265   bool success() const {
 266     return !_cl.failed();
 267   }
 268 };
 269 
 270 void ShenandoahCodeRoots::unlink(WorkGang* workers, bool unloading_occurred) {
 271   assert(ShenandoahConcurrentRoots::should_do_concurrent_class_unloading(),
 272          "Only when running concurrent class unloading");
 273 
 274   for (;;) {
 275     ICRefillVerifier verifier;
 276 
 277     {
 278       ShenandoahUnlinkTask task(unloading_occurred, &verifier);
 279       workers->run_task(&task);
 280       if (task.success()) {




   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #include "precompiled.hpp"
  25 #include "code/codeCache.hpp"
  26 #include "code/icBuffer.hpp"
  27 #include "code/nmethod.hpp"
  28 #include "gc/shenandoah/shenandoahCodeRoots.hpp"
  29 #include "gc/shenandoah/shenandoahEvacOOMHandler.hpp"
  30 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  31 #include "gc/shenandoah/shenandoahNMethod.inline.hpp"
  32 #include "gc/shenandoah/shenandoahUtils.hpp"
  33 #include "memory/resourceArea.hpp"
  34 #include "memory/universe.hpp"
  35 #include "runtime/atomic.hpp"
  36 
  37 ShenandoahParallelCodeCacheIterator::ShenandoahParallelCodeCacheIterator(const GrowableArray<CodeHeap*>* heaps) {
  38   _length = heaps->length();
  39   _iters = NEW_C_HEAP_ARRAY(ShenandoahParallelCodeHeapIterator, _length, mtGC);
  40   for (int h = 0; h < _length; h++) {
  41     _iters[h] = ShenandoahParallelCodeHeapIterator(heaps->at(h));
  42   }
  43 }
  44 
  45 ShenandoahParallelCodeCacheIterator::~ShenandoahParallelCodeCacheIterator() {
  46   FREE_C_HEAP_ARRAY(ParallelCodeHeapIterator, _iters);
  47 }
  48 
  49 void ShenandoahParallelCodeCacheIterator::parallel_blobs_do(CodeBlobClosure* f) {


 205     if (failed()) {
 206       return;
 207     }
 208 
 209     ShenandoahNMethod* nm_data = ShenandoahNMethod::gc_data(nm);
 210     assert(!nm_data->is_unregistered(), "Should not see unregistered entry");
 211 
 212     if (!nm->is_alive()) {
 213       return;
 214     }
 215 
 216     if (nm->is_unloading()) {
 217       ShenandoahReentrantLocker locker(nm_data->lock());
 218       unlink(nm);
 219       return;
 220     }
 221 
 222     ShenandoahReentrantLocker locker(nm_data->lock());
 223 
 224     // Heal oops and disarm

 225     ShenandoahNMethod::heal_nmethod(nm);
 226     ShenandoahNMethod::disarm_nmethod(nm);
 227 
 228     // Clear compiled ICs and exception caches
 229     if (!nm->unload_nmethod_caches(_unloading_occurred)) {
 230       set_failed();
 231     }
 232   }
 233 
 234   bool failed() const {
 235     return Atomic::load(&_failed);
 236   }
 237 };
 238 
 239 class ShenandoahUnlinkTask : public AbstractGangTask {
 240 private:
 241   ShenandoahNMethodUnlinkClosure      _cl;
 242   ICRefillVerifier*                   _verifier;
 243   ShenandoahConcurrentNMethodIterator _iterator;
 244 
 245 public:
 246   ShenandoahUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
 247     AbstractGangTask("ShenandoahNMethodUnlinkTask"),
 248     _cl(unloading_occurred),
 249     _verifier(verifier),
 250     _iterator(ShenandoahCodeRoots::table()) {
 251     MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 252     _iterator.nmethods_do_begin();
 253   }
 254 
 255   ~ShenandoahUnlinkTask() {
 256     MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 257     _iterator.nmethods_do_end();
 258   }
 259 
 260   virtual void work(uint worker_id) {
 261     ShenandoahEvacOOMScope evac_scope;
 262     ICRefillVerifierMark mark(_verifier);
 263     _iterator.nmethods_do(&_cl);
 264   }
 265 
 266   bool success() const {
 267     return !_cl.failed();
 268   }
 269 };
 270 
 271 void ShenandoahCodeRoots::unlink(WorkGang* workers, bool unloading_occurred) {
 272   assert(ShenandoahConcurrentRoots::should_do_concurrent_class_unloading(),
 273          "Only when running concurrent class unloading");
 274 
 275   for (;;) {
 276     ICRefillVerifier verifier;
 277 
 278     {
 279       ShenandoahUnlinkTask task(unloading_occurred, &verifier);
 280       workers->run_task(&task);
 281       if (task.success()) {


< prev index next >