0 /*                                                                                                                                   
1  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.                                                            
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.                                                                     
3  *                                                                                                                                   
4  * This code is free software; you can redistribute it and/or modify it                                                              
5  * under the terms of the GNU General Public License version 2 only, as                                                              
6  * published by the Free Software Foundation.                                                                                        
7  *                                                                                                                                   
8  * This code is distributed in the hope that it will be useful, but WITHOUT                                                          
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 #include "precompiled.hpp"                                                                                                           
24 #include "classfile/classLoaderDataGraph.hpp"                                                                                        
25 #include "classfile/systemDictionary.hpp"                                                                                            
26 #include "code/codeBehaviours.hpp"                                                                                                   
27 #include "code/codeCache.hpp"                                                                                                        
28 #include "code/dependencyContext.hpp"                                                                                                
29 #include "gc/shared/gcBehaviours.hpp"                                                                                                
30 #include "gc/shared/suspendibleThreadSet.hpp"                                                                                        
31 #include "gc/z/zLock.inline.hpp"                                                                                                     
32 #include "gc/z/zNMethod.hpp"                                                                                                         
33 #include "gc/z/zOopClosures.hpp"                                                                                                     
34 #include "gc/z/zStat.hpp"                                                                                                            
35 #include "gc/z/zUnload.hpp"                                                                                                          
36 #include "oops/access.inline.hpp"                                                                                                    
37 
38 static const ZStatSubPhase ZSubPhaseConcurrentClassesUnload("Concurrent Classes Unload");                                            
39 
40 class ZIsUnloadingOopClosure : public OopClosure {                                                                                   
41 private:                                                                                                                             
42   ZPhantomIsAliveObjectClosure _is_alive;                                                                                            
43   bool                         _is_unloading;                                                                                        
44 
45 public:                                                                                                                              
46   ZIsUnloadingOopClosure() :                                                                                                         
47       _is_alive(),                                                                                                                   
48       _is_unloading(false) {}                                                                                                        
49 
50   virtual void do_oop(oop* p) {                                                                                                      
51     const oop o = RawAccess<>::oop_load(p);                                                                                          
52     if (o != NULL && !_is_alive.do_object_b(o)) {                                                                                    
53       _is_unloading = true;                                                                                                          
54     }                                                                                                                                
55   }                                                                                                                                  
56 
57   virtual void do_oop(narrowOop* p) {                                                                                                
58     ShouldNotReachHere();                                                                                                            
59   }                                                                                                                                  
60 
61   bool is_unloading() const {                                                                                                        
62     return _is_unloading;                                                                                                            
63   }                                                                                                                                  
64 };                                                                                                                                   
65 
66 class ZIsUnloadingBehaviour : public IsUnloadingBehaviour {                                                                          
67 private:                                                                                                                             
68   bool is_unloading(nmethod* nm) const {                                                                                             
69     ZIsUnloadingOopClosure cl;                                                                                                       
70     nm->oops_do(&cl, true /* allow_zombie */);                                                                                       
71     return cl.is_unloading();                                                                                                        
72   }                                                                                                                                  
73                                                                                                                                      
74 public:                                                                                                                              
75   virtual bool is_unloading(CompiledMethod* method) const {                                                                          
76     nmethod* const nm = method->as_nmethod();                                                                                        
77     ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);                                                                     
78     if (lock == NULL) {                                                                                                              
79       return is_unloading(nm);                                                                                                       
80     } else {                                                                                                                         
81       ZLocker<ZReentrantLock> locker(lock);                                                                                          
82       return is_unloading(nm);                                                                                                       
83     }                                                                                                                                
84   }                                                                                                                                  
85 };                                                                                                                                   
86 
87 class ZCompiledICProtectionBehaviour : public CompiledICProtectionBehaviour {                                                        
88 public:                                                                                                                              
89   virtual bool lock(CompiledMethod* method) {                                                                                        
90     nmethod* const nm = method->as_nmethod();                                                                                        
91     ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);                                                                     
92     if (lock != NULL) {                                                                                                              
93       lock->lock();                                                                                                                  
94     }                                                                                                                                
95     return true;                                                                                                                     
96   }                                                                                                                                  
97 
98   virtual void unlock(CompiledMethod* method) {                                                                                      
99     nmethod* const nm = method->as_nmethod();                                                                                        
100     ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);                                                                     
101     if (lock != NULL) {                                                                                                              
102       lock->unlock();                                                                                                                
103     }                                                                                                                                
104   }                                                                                                                                  
105 
106   virtual bool is_safe(CompiledMethod* method) {                                                                                     
107     if (SafepointSynchronize::is_at_safepoint()) {                                                                                   
108       return true;                                                                                                                   
109     }                                                                                                                                
110 
111     nmethod* const nm = method->as_nmethod();                                                                                        
112     ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);                                                                     
113     return lock == NULL || lock->is_owned();                                                                                         
114   }                                                                                                                                  
115 };                                                                                                                                   
116 
117 ZUnload::ZUnload(ZWorkers* workers) :                                                                                                
118     _workers(workers) {                                                                                                              
119 
120   if (!ClassUnloading) {                                                                                                             
121     return;                                                                                                                          
122   }                                                                                                                                  
123 
124   static ZIsUnloadingBehaviour is_unloading_behaviour;                                                                               
125   IsUnloadingBehaviour::set_current(&is_unloading_behaviour);                                                                        
126 
127   static ZCompiledICProtectionBehaviour ic_protection_behaviour;                                                                     
128   CompiledICProtectionBehaviour::set_current(&ic_protection_behaviour);                                                              
129 }                                                                                                                                    
130 
131 void ZUnload::prepare() {                                                                                                            
132   if (!ClassUnloading) {                                                                                                             
133     return;                                                                                                                          
134   }                                                                                                                                  
135 
136   CodeCache::increment_unloading_cycle();                                                                                            
137   DependencyContext::cleaning_start();                                                                                               
138 }                                                                                                                                    
139 
140 void ZUnload::unlink() {                                                                                                             
141   SuspendibleThreadSetJoiner sts;                                                                                                    
142   bool unloading_occurred;                                                                                                           
143 
144   {                                                                                                                                  
145     MutexLockerEx ml(ClassLoaderDataGraph_lock);                                                                                     
146     unloading_occurred = SystemDictionary::do_unloading(ZStatPhase::timer());                                                        
147   }                                                                                                                                  
148 
149   Klass::clean_weak_klass_links(unloading_occurred);                                                                                 
150 
151   ZNMethod::unlink(_workers, unloading_occurred);                                                                                    
152 
153   DependencyContext::cleaning_end();                                                                                                 
154 }                                                                                                                                    
155 
156 void ZUnload::purge() {                                                                                                              
157   {                                                                                                                                  
158     SuspendibleThreadSetJoiner sts;                                                                                                  
159     ZNMethod::purge(_workers);                                                                                                       
160   }                                                                                                                                  
161 
162   ClassLoaderDataGraph::purge();                                                                                                     
163   CodeCache::purge_exception_caches();                                                                                               
164 }                                                                                                                                    
165 
166 class ZUnloadRendezvousClosure : public ThreadClosure {                                                                              
167 public:                                                                                                                              
168   void do_thread(Thread* thread) {}                                                                                                  
169 };                                                                                                                                   
170 
171 void ZUnload::unload() {                                                                                                             
172   if (!ClassUnloading) {                                                                                                             
173     return;                                                                                                                          
174   }                                                                                                                                  
175 
176   ZStatTimer timer(ZSubPhaseConcurrentClassesUnload);                                                                                
177 
178   // Unlink stale metadata and nmethods                                                                                              
179   unlink();                                                                                                                          
180 
181   // Make sure stale metadata and nmethods are no longer observable                                                                  
182   ZUnloadRendezvousClosure cl;                                                                                                       
183   Handshake::execute(&cl);                                                                                                           
184 
185   // Purge stale metadata and nmethods that were unlinked                                                                            
186   purge();                                                                                                                           
187 }                                                                                                                                    
188 
189 void ZUnload::finish() {                                                                                                             
190   // Resize and verify metaspace                                                                                                     
191   MetaspaceGC::compute_new_size();                                                                                                   
192   MetaspaceUtils::verify_metrics();                                                                                                  
193 }                                                                                                                                    
--- EOF ---