diff --git a/src/share/vm/code/codeCache.cpp b/src/share/vm/code/codeCache.cpp index 9e5b7e98c73458e9e8b3ddef3b37918dbcdd7924..5f9792d8fbbf91603f450c69218c8eaca143a162 100644 --- a/src/share/vm/code/codeCache.cpp +++ b/src/share/vm/code/codeCache.cpp @@ -336,16 +336,19 @@ void CodeCache::blobs_do(CodeBlobClosure* f) { } // Walk the list of methods which might contain non-perm oops. -void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) { +void CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure* f) { assert_locked_or_safepoint(CodeCache_lock); if (UseG1GC) { return; } + const bool fix_relocations = f->fix_relocations(); debug_only(mark_scavenge_root_nmethods()); - for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) { + nmethod* prev = NULL; + nmethod* cur = scavenge_root_nmethods(); + while (cur != NULL) { debug_only(cur->clear_scavenge_root_marked()); assert(cur->scavenge_root_not_marked(), ""); assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); @@ -360,6 +363,18 @@ void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) { // Perform cur->oops_do(f), maybe just once per nmethod. f->do_code_blob(cur); } + nmethod* const next = cur->scavenge_root_link(); + // The scavengable nmethod list must contain all methods with scavengable + // oops. It is safe to include more nmethod on the list, but we do not + // expect any live non-scavengable nmethods on the list. + if (fix_relocations) { + if (!is_live || !cur->detect_scavenge_root_oops()) { + unlink_scavenge_root_nmethod(cur, prev); + } else { + prev = cur; + } + } + cur = next; } // Check for stray marks. @@ -379,6 +394,24 @@ void CodeCache::add_scavenge_root_nmethod(nmethod* nm) { print_trace("add_scavenge_root", nm); } +void CodeCache::unlink_scavenge_root_nmethod(nmethod* nm, nmethod* prev) { + assert_locked_or_safepoint(CodeCache_lock); + + assert((prev == NULL && scavenge_root_nmethods() == nm) || + (prev != NULL && prev->scavenge_root_link() == nm), "precondition"); + + assert(!UseG1GC, "G1 does not use the scavenge_root_nmethods list"); + + print_trace("unlink_scavenge_root", nm); + if (prev == NULL) { + set_scavenge_root_nmethods(nm->scavenge_root_link()); + } else { + prev->set_scavenge_root_link(nm->scavenge_root_link()); + } + nm->set_scavenge_root_link(NULL); + nm->clear_on_scavenge_root_list(); +} + void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) { assert_locked_or_safepoint(CodeCache_lock); @@ -387,20 +420,13 @@ void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) { } print_trace("drop_scavenge_root", nm); - nmethod* last = NULL; - nmethod* cur = scavenge_root_nmethods(); - while (cur != NULL) { - nmethod* next = cur->scavenge_root_link(); + nmethod* prev = NULL; + for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) { if (cur == nm) { - if (last != NULL) - last->set_scavenge_root_link(next); - else set_scavenge_root_nmethods(next); - nm->set_scavenge_root_link(NULL); - nm->clear_on_scavenge_root_list(); + unlink_scavenge_root_nmethod(cur, prev); return; } - last = cur; - cur = next; + prev = cur; } assert(false, "should have been on list"); } @@ -429,11 +455,7 @@ void CodeCache::prune_scavenge_root_nmethods() { } else { // Prune it from the list, so we don't have to look at it any more. print_trace("prune_scavenge_root", cur); - cur->set_scavenge_root_link(NULL); - cur->clear_on_scavenge_root_list(); - if (last != NULL) - last->set_scavenge_root_link(next); - else set_scavenge_root_nmethods(next); + unlink_scavenge_root_nmethod(cur, last); } cur = next; } diff --git a/src/share/vm/code/codeCache.hpp b/src/share/vm/code/codeCache.hpp index f098284a30a472cccc948eb5011159923f44e98b..415f67750351a30b5055562ec6cc14aaaf383a41 100644 --- a/src/share/vm/code/codeCache.hpp +++ b/src/share/vm/code/codeCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,6 +65,10 @@ class CodeCache : AllStatic { static int _codemem_full_count; + static void set_scavenge_root_nmethods(nmethod* nm) { _scavenge_root_nmethods = nm; } + static void prune_scavenge_root_nmethods(); + static void unlink_scavenge_root_nmethod(nmethod* nm, nmethod* prev); + public: // Initialization @@ -135,13 +139,17 @@ class CodeCache : AllStatic { // to "true" iff some code got unloaded. static void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred); static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* f = NULL) PRODUCT_RETURN; - static void scavenge_root_nmethods_do(CodeBlobClosure* f); + + // Apply f to every live code blob in scavengable nmethods. Prune nmethods + // from the list of scavengable nmethods if f->fix_relocations() and a nmethod + // no longer has scavengable oops. If f->fix_relocations(), then f must copy + // objects to their new location immediately to avoid fixing nmethods on the + // basis of the old object locations. + static void scavenge_root_nmethods_do(CodeBlobToOopClosure* f); static nmethod* scavenge_root_nmethods() { return _scavenge_root_nmethods; } - static void set_scavenge_root_nmethods(nmethod* nm) { _scavenge_root_nmethods = nm; } static void add_scavenge_root_nmethod(nmethod* nm); static void drop_scavenge_root_nmethod(nmethod* nm); - static void prune_scavenge_root_nmethods(); // Printing/debugging static void print(); // prints summary diff --git a/src/share/vm/code/nmethod.cpp b/src/share/vm/code/nmethod.cpp index 759ae74e9edaa8bd0411567da3c3be9852a8c983..9e4edf3428649b8ddb66f90d022e273ea43ad829 100644 --- a/src/share/vm/code/nmethod.cpp +++ b/src/share/vm/code/nmethod.cpp @@ -1392,7 +1392,6 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) { assert(_method == NULL, "Tautology"); set_osr_link(NULL); - //set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods NMethodSweeper::report_state_change(this); } diff --git a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp index 6d728ccf597e5f4c7c52b4d39b2c0385b3260239..5d7e99bd2c15ffe60ee4f7541180de53cf5a5993 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -636,12 +636,6 @@ bool PSScavenge::invoke_no_policy() { NOT_PRODUCT(reference_processor()->verify_no_references_recorded()); - { - GCTraceTime tm("Prune Scavenge Root Methods", false, false, &_gc_timer, _gc_tracer.gc_id()); - - CodeCache::prune_scavenge_root_nmethods(); - } - // Re-verify object start arrays if (VerifyObjectStartArray && VerifyAfterGC) { diff --git a/src/share/vm/memory/genCollectedHeap.cpp b/src/share/vm/memory/genCollectedHeap.cpp index f7c9591d9044fe2b3c324baa42fed94c68539888..34fbe88f8c91ba3abf4b7819c3dccea5d407f7df 100644 --- a/src/share/vm/memory/genCollectedHeap.cpp +++ b/src/share/vm/memory/genCollectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -619,7 +619,7 @@ void GenCollectedHeap::process_roots(bool activate_scope, OopClosure* weak_roots, CLDClosure* strong_cld_closure, CLDClosure* weak_cld_closure, - CodeBlobClosure* code_roots) { + CodeBlobToOopClosure* code_roots) { StrongRootsScope srs(this, activate_scope); // General roots. @@ -638,7 +638,7 @@ void GenCollectedHeap::process_roots(bool activate_scope, // Don't process them if they will be processed during the ClassLoaderDataGraph phase. CLDClosure* roots_from_clds_p = (strong_cld_closure != weak_cld_closure) ? strong_cld_closure : NULL; // Only process code roots from thread stacks if we aren't visiting the entire CodeCache anyway - CodeBlobClosure* roots_from_code_p = (so & SO_AllCodeCache) ? NULL : code_roots; + CodeBlobToOopClosure* roots_from_code_p = (so & SO_AllCodeCache) ? NULL : code_roots; Threads::possibly_parallel_oops_do(strong_roots, roots_from_clds_p, roots_from_code_p); diff --git a/src/share/vm/memory/genCollectedHeap.hpp b/src/share/vm/memory/genCollectedHeap.hpp index 58786eded2f0eec4c94ac7762246a3e73feee9f0..1a2fcaa0615d77a01f317bb170e95308bce86006 100644 --- a/src/share/vm/memory/genCollectedHeap.hpp +++ b/src/share/vm/memory/genCollectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -416,7 +416,7 @@ public: OopClosure* weak_roots, CLDClosure* strong_cld_closure, CLDClosure* weak_cld_closure, - CodeBlobClosure* code_roots); + CodeBlobToOopClosure* code_roots); void gen_process_roots(int level, bool younger_gens_as_roots, diff --git a/src/share/vm/memory/iterator.hpp b/src/share/vm/memory/iterator.hpp index 6622e13107025428da5d1b011ab978743fc20488..6cf78dc997445f1fa0b049a0f496fa8bd15b8607 100644 --- a/src/share/vm/memory/iterator.hpp +++ b/src/share/vm/memory/iterator.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -291,9 +291,12 @@ class CodeBlobToOopClosure : public CodeBlobClosure { protected: void do_nmethod(nmethod* nm); public: + // If fix_relocations(), then cl must copy objects to their new location immediately to avoid + // patching nmethods with the old locations. CodeBlobToOopClosure(OopClosure* cl, bool fix_relocations) : _cl(cl), _fix_relocations(fix_relocations) {} virtual void do_code_blob(CodeBlob* cb); + bool fix_relocations() const { return _fix_relocations; } const static bool FixRelocations = true; };