annotate src/hotspot/share/gc/z/zUnload.cpp @ 54567:224515275cf9

8219718: ZGC: Make nmethod entry barriers and nmethod::is_unloading use ZNMethodDataOops Reviewed-by: pliden, stefank
author eosterlund
date Wed, 17 Apr 2019 12:41:33 +0200
parents a590b6107ab3
children 1126f0607c70
rev   line source
eosterlund@52939 1 /*
eosterlund@52939 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
eosterlund@52939 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
eosterlund@52939 4 *
eosterlund@52939 5 * This code is free software; you can redistribute it and/or modify it
eosterlund@52939 6 * under the terms of the GNU General Public License version 2 only, as
eosterlund@52939 7 * published by the Free Software Foundation.
eosterlund@52939 8 *
eosterlund@52939 9 * This code is distributed in the hope that it will be useful, but WITHOUT
eosterlund@52939 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
eosterlund@52939 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
eosterlund@52939 12 * version 2 for more details (a copy is included in the LICENSE file that
eosterlund@52939 13 * accompanied this code).
eosterlund@52939 14 *
eosterlund@52939 15 * You should have received a copy of the GNU General Public License version
eosterlund@52939 16 * 2 along with this work; if not, write to the Free Software Foundation,
eosterlund@52939 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
eosterlund@52939 18 *
eosterlund@52939 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
eosterlund@52939 20 * or visit www.oracle.com if you need additional information or have any
eosterlund@52939 21 * questions.
eosterlund@52939 22 */
eosterlund@52939 23
eosterlund@52939 24 #include "precompiled.hpp"
eosterlund@52939 25 #include "classfile/classLoaderDataGraph.hpp"
eosterlund@52939 26 #include "classfile/systemDictionary.hpp"
eosterlund@52939 27 #include "code/codeBehaviours.hpp"
eosterlund@52939 28 #include "code/codeCache.hpp"
eosterlund@52939 29 #include "code/dependencyContext.hpp"
eosterlund@52939 30 #include "gc/shared/gcBehaviours.hpp"
eosterlund@52939 31 #include "gc/shared/suspendibleThreadSet.hpp"
eosterlund@52939 32 #include "gc/z/zLock.inline.hpp"
stefank@53894 33 #include "gc/z/zNMethod.hpp"
eosterlund@52939 34 #include "gc/z/zOopClosures.hpp"
eosterlund@52939 35 #include "gc/z/zStat.hpp"
eosterlund@52939 36 #include "gc/z/zUnload.hpp"
eosterlund@52939 37 #include "oops/access.inline.hpp"
eosterlund@52939 38
eosterlund@52939 39 static const ZStatSubPhase ZSubPhaseConcurrentClassesUnload("Concurrent Classes Unload");
eosterlund@52939 40
eosterlund@52939 41 class ZIsUnloadingOopClosure : public OopClosure {
eosterlund@52939 42 private:
eosterlund@52939 43 ZPhantomIsAliveObjectClosure _is_alive;
eosterlund@52939 44 bool _is_unloading;
eosterlund@52939 45
eosterlund@52939 46 public:
eosterlund@52939 47 ZIsUnloadingOopClosure() :
eosterlund@52939 48 _is_alive(),
eosterlund@52939 49 _is_unloading(false) {}
eosterlund@52939 50
eosterlund@52939 51 virtual void do_oop(oop* p) {
eosterlund@52939 52 const oop o = RawAccess<>::oop_load(p);
eosterlund@52939 53 if (o != NULL && !_is_alive.do_object_b(o)) {
eosterlund@52939 54 _is_unloading = true;
eosterlund@52939 55 }
eosterlund@52939 56 }
eosterlund@52939 57
eosterlund@52939 58 virtual void do_oop(narrowOop* p) {
eosterlund@52939 59 ShouldNotReachHere();
eosterlund@52939 60 }
eosterlund@52939 61
eosterlund@52939 62 bool is_unloading() const {
eosterlund@52939 63 return _is_unloading;
eosterlund@52939 64 }
eosterlund@52939 65 };
eosterlund@52939 66
eosterlund@52939 67 class ZIsUnloadingBehaviour : public IsUnloadingBehaviour {
eosterlund@52939 68 public:
eosterlund@52939 69 virtual bool is_unloading(CompiledMethod* method) const {
eosterlund@52939 70 nmethod* const nm = method->as_nmethod();
stefank@53894 71 ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
eosterlund@53921 72 ZLocker<ZReentrantLock> locker(lock);
eosterlund@53921 73 ZIsUnloadingOopClosure cl;
eosterlund@54567 74 ZNMethod::nmethod_oops_do(nm, &cl);
eosterlund@53921 75 return cl.is_unloading();
eosterlund@52939 76 }
eosterlund@52939 77 };
eosterlund@52939 78
eosterlund@52939 79 class ZCompiledICProtectionBehaviour : public CompiledICProtectionBehaviour {
eosterlund@52939 80 public:
eosterlund@52939 81 virtual bool lock(CompiledMethod* method) {
eosterlund@52939 82 nmethod* const nm = method->as_nmethod();
stefank@53894 83 ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
eosterlund@53921 84 lock->lock();
eosterlund@52939 85 return true;
eosterlund@52939 86 }
eosterlund@52939 87
eosterlund@52939 88 virtual void unlock(CompiledMethod* method) {
eosterlund@52939 89 nmethod* const nm = method->as_nmethod();
stefank@53894 90 ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
eosterlund@53921 91 lock->unlock();
eosterlund@52939 92 }
eosterlund@52939 93
eosterlund@52939 94 virtual bool is_safe(CompiledMethod* method) {
eosterlund@52939 95 if (SafepointSynchronize::is_at_safepoint()) {
eosterlund@52939 96 return true;
eosterlund@52939 97 }
eosterlund@52939 98
eosterlund@52939 99 nmethod* const nm = method->as_nmethod();
stefank@53894 100 ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
eosterlund@53921 101 return lock->is_owned();
eosterlund@52939 102 }
eosterlund@52939 103 };
eosterlund@52939 104
eosterlund@52939 105 ZUnload::ZUnload(ZWorkers* workers) :
eosterlund@52939 106 _workers(workers) {
eosterlund@52939 107
eosterlund@52939 108 if (!ClassUnloading) {
eosterlund@52939 109 return;
eosterlund@52939 110 }
eosterlund@52939 111
eosterlund@52939 112 static ZIsUnloadingBehaviour is_unloading_behaviour;
eosterlund@52939 113 IsUnloadingBehaviour::set_current(&is_unloading_behaviour);
eosterlund@52939 114
eosterlund@52939 115 static ZCompiledICProtectionBehaviour ic_protection_behaviour;
eosterlund@52939 116 CompiledICProtectionBehaviour::set_current(&ic_protection_behaviour);
eosterlund@52939 117 }
eosterlund@52939 118
eosterlund@52939 119 void ZUnload::prepare() {
eosterlund@52939 120 if (!ClassUnloading) {
eosterlund@52939 121 return;
eosterlund@52939 122 }
eosterlund@52939 123
eosterlund@52939 124 CodeCache::increment_unloading_cycle();
eosterlund@52939 125 DependencyContext::cleaning_start();
eosterlund@52939 126 }
eosterlund@52939 127
eosterlund@52939 128 void ZUnload::unlink() {
eosterlund@52939 129 SuspendibleThreadSetJoiner sts;
eosterlund@52939 130 bool unloading_occurred;
eosterlund@52939 131
eosterlund@52939 132 {
eosterlund@52939 133 MutexLockerEx ml(ClassLoaderDataGraph_lock);
eosterlund@52939 134 unloading_occurred = SystemDictionary::do_unloading(ZStatPhase::timer());
eosterlund@52939 135 }
eosterlund@52939 136
eosterlund@52939 137 Klass::clean_weak_klass_links(unloading_occurred);
eosterlund@52939 138
stefank@53894 139 ZNMethod::unlink(_workers, unloading_occurred);
eosterlund@52939 140
eosterlund@52939 141 DependencyContext::cleaning_end();
eosterlund@52939 142 }
eosterlund@52939 143
eosterlund@52939 144 void ZUnload::purge() {
eosterlund@52939 145 {
eosterlund@52939 146 SuspendibleThreadSetJoiner sts;
stefank@53894 147 ZNMethod::purge(_workers);
eosterlund@52939 148 }
eosterlund@52939 149
eosterlund@52939 150 ClassLoaderDataGraph::purge();
eosterlund@52939 151 CodeCache::purge_exception_caches();
eosterlund@52939 152 }
eosterlund@52939 153
eosterlund@52939 154 class ZUnloadRendezvousClosure : public ThreadClosure {
eosterlund@52939 155 public:
eosterlund@52939 156 void do_thread(Thread* thread) {}
eosterlund@52939 157 };
eosterlund@52939 158
eosterlund@52939 159 void ZUnload::unload() {
eosterlund@52939 160 if (!ClassUnloading) {
eosterlund@52939 161 return;
eosterlund@52939 162 }
eosterlund@52939 163
eosterlund@52939 164 ZStatTimer timer(ZSubPhaseConcurrentClassesUnload);
eosterlund@52939 165
eosterlund@52939 166 // Unlink stale metadata and nmethods
eosterlund@52939 167 unlink();
eosterlund@52939 168
eosterlund@52939 169 // Make sure stale metadata and nmethods are no longer observable
eosterlund@52939 170 ZUnloadRendezvousClosure cl;
eosterlund@52939 171 Handshake::execute(&cl);
eosterlund@52939 172
eosterlund@52939 173 // Purge stale metadata and nmethods that were unlinked
eosterlund@52939 174 purge();
eosterlund@52939 175 }
eosterlund@52939 176
eosterlund@52939 177 void ZUnload::finish() {
eosterlund@52939 178 // Resize and verify metaspace
eosterlund@52939 179 MetaspaceGC::compute_new_size();
eosterlund@52939 180 MetaspaceUtils::verify_metrics();
eosterlund@52939 181 }