< prev index next >

src/hotspot/share/memory/metaspace/virtualSpaceList.cpp

Concurrent class unloading

54   assert_lock_strong(MetaspaceExpand_lock);                                                                                          
55   _committed_words = _committed_words - v;                                                                                           
56 
57   assert_committed_below_limit();                                                                                                    
58 }                                                                                                                                    
59 
60 void VirtualSpaceList::inc_virtual_space_count() {                                                                                   
61   assert_lock_strong(MetaspaceExpand_lock);                                                                                          
62   _virtual_space_count++;                                                                                                            
63 }                                                                                                                                    
64 
65 void VirtualSpaceList::dec_virtual_space_count() {                                                                                   
66   assert_lock_strong(MetaspaceExpand_lock);                                                                                          
67   _virtual_space_count--;                                                                                                            
68 }                                                                                                                                    
69 
70 // Walk the list of VirtualSpaceNodes and delete                                                                                     
71 // nodes with a 0 container_count.  Remove Metachunks in                                                                             
72 // the node from their respective freelists.                                                                                         
73 void VirtualSpaceList::purge(ChunkManager* chunk_manager) {                                                                          
74   assert(SafepointSynchronize::is_at_safepoint(), "must be called at safepoint for contains to work");                               
75   assert_lock_strong(MetaspaceExpand_lock);                                                                                          
76   // Don't use a VirtualSpaceListIterator because this                                                                               
77   // list is being changed and a straightforward use of an iterator is not safe.                                                     
78   VirtualSpaceNode* purged_vsl = NULL;                                                                                               
79   VirtualSpaceNode* prev_vsl = virtual_space_list();                                                                                 
80   VirtualSpaceNode* next_vsl = prev_vsl;                                                                                             
81   while (next_vsl != NULL) {                                                                                                         
82     VirtualSpaceNode* vsl = next_vsl;                                                                                                
83     DEBUG_ONLY(vsl->verify_container_count();)                                                                                       
84     next_vsl = vsl->next();                                                                                                          
85     // Don't free the current virtual space since it will likely                                                                     
86     // be needed soon.                                                                                                               
87     if (vsl->container_count() == 0 && vsl != current_virtual_space()) {                                                             
88       log_trace(gc, metaspace, freelist)("Purging VirtualSpaceNode " PTR_FORMAT " (capacity: " SIZE_FORMAT                           
89                                          ", used: " SIZE_FORMAT ").", p2i(vsl), vsl->capacity_words_in_vs(), vsl->used_words_in_vs())
90       DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_vsnodes_purged));                                                            
91       // Unlink it from the list                                                                                                     
92       if (prev_vsl == vsl) {                                                                                                         
93         // This is the case of the current node being the first node.                                                                

54   assert_lock_strong(MetaspaceExpand_lock);
55   _committed_words = _committed_words - v;
56 
57   assert_committed_below_limit();
58 }
59 
60 void VirtualSpaceList::inc_virtual_space_count() {
61   assert_lock_strong(MetaspaceExpand_lock);
62   _virtual_space_count++;
63 }
64 
65 void VirtualSpaceList::dec_virtual_space_count() {
66   assert_lock_strong(MetaspaceExpand_lock);
67   _virtual_space_count--;
68 }
69 
70 // Walk the list of VirtualSpaceNodes and delete
71 // nodes with a 0 container_count.  Remove Metachunks in
72 // the node from their respective freelists.
73 void VirtualSpaceList::purge(ChunkManager* chunk_manager) {
74   assert(UseZGC || SafepointSynchronize::is_at_safepoint(), "must be called at safepoint for contains to work");
75   assert_lock_strong(MetaspaceExpand_lock);
76   // Don't use a VirtualSpaceListIterator because this
77   // list is being changed and a straightforward use of an iterator is not safe.
78   VirtualSpaceNode* purged_vsl = NULL;
79   VirtualSpaceNode* prev_vsl = virtual_space_list();
80   VirtualSpaceNode* next_vsl = prev_vsl;
81   while (next_vsl != NULL) {
82     VirtualSpaceNode* vsl = next_vsl;
83     DEBUG_ONLY(vsl->verify_container_count();)
84     next_vsl = vsl->next();
85     // Don't free the current virtual space since it will likely
86     // be needed soon.
87     if (vsl->container_count() == 0 && vsl != current_virtual_space()) {
88       log_trace(gc, metaspace, freelist)("Purging VirtualSpaceNode " PTR_FORMAT " (capacity: " SIZE_FORMAT
89                                          ", used: " SIZE_FORMAT ").", p2i(vsl), vsl->capacity_words_in_vs(), vsl->used_words_in_vs())
90       DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_vsnodes_purged));
91       // Unlink it from the list
92       if (prev_vsl == vsl) {
93         // This is the case of the current node being the first node.

107       prev_vsl = vsl;                                                                                                                
108     }                                                                                                                                
109   }                                                                                                                                  
110 #ifdef ASSERT                                                                                                                        
111   if (purged_vsl != NULL) {                                                                                                          
112     // List should be stable enough to use an iterator here.                                                                         
113     VirtualSpaceListIterator iter(virtual_space_list());                                                                             
114     while (iter.repeat()) {                                                                                                          
115       VirtualSpaceNode* vsl = iter.get_next();                                                                                       
116       assert(vsl != purged_vsl, "Purge of vsl failed");                                                                              
117     }                                                                                                                                
118   }                                                                                                                                  
119 #endif                                                                                                                               
120 }                                                                                                                                    
121 
122 
123 // This function looks at the mmap regions in the metaspace without locking.                                                         
124 // The chunks are added with store ordering and not deleted except for at                                                            
125 // unloading time during a safepoint.                                                                                                
126 bool VirtualSpaceList::contains(const void* ptr) {                                                                                   
                                                                                                                                     
                                                                                                                                     
127   // List should be stable enough to use an iterator here because removing virtual                                                   
128   // space nodes is only allowed at a safepoint.                                                                                     
129   VirtualSpaceListIterator iter(virtual_space_list());                                                                               
130   while (iter.repeat()) {                                                                                                            
131     VirtualSpaceNode* vsn = iter.get_next();                                                                                         
132     if (vsn->contains(ptr)) {                                                                                                        
133       return true;                                                                                                                   
134     }                                                                                                                                
135   }                                                                                                                                  
136   return false;                                                                                                                      
137 }                                                                                                                                    
138 
139 void VirtualSpaceList::retire_current_virtual_space() {                                                                              
140   assert_lock_strong(MetaspaceExpand_lock);                                                                                          
141 
142   VirtualSpaceNode* vsn = current_virtual_space();                                                                                   
143 
144   ChunkManager* cm = is_class() ? Metaspace::chunk_manager_class() :                                                                 
145                                   Metaspace::chunk_manager_metadata();                                                               

107       prev_vsl = vsl;
108     }
109   }
110 #ifdef ASSERT
111   if (purged_vsl != NULL) {
112     // List should be stable enough to use an iterator here.
113     VirtualSpaceListIterator iter(virtual_space_list());
114     while (iter.repeat()) {
115       VirtualSpaceNode* vsl = iter.get_next();
116       assert(vsl != purged_vsl, "Purge of vsl failed");
117     }
118   }
119 #endif
120 }
121 
122 
123 // This function looks at the mmap regions in the metaspace without locking.
124 // The chunks are added with store ordering and not deleted except for at
125 // unloading time during a safepoint.
126 bool VirtualSpaceList::contains(const void* ptr) {
127   MutexLockerEx cl(MetaspaceExpand_lock,
128                    Mutex::_no_safepoint_check_flag);
129   // List should be stable enough to use an iterator here because removing virtual
130   // space nodes is only allowed at a safepoint.
131   VirtualSpaceListIterator iter(virtual_space_list());
132   while (iter.repeat()) {
133     VirtualSpaceNode* vsn = iter.get_next();
134     if (vsn->contains(ptr)) {
135       return true;
136     }
137   }
138   return false;
139 }
140 
141 void VirtualSpaceList::retire_current_virtual_space() {
142   assert_lock_strong(MetaspaceExpand_lock);
143 
144   VirtualSpaceNode* vsn = current_virtual_space();
145 
146   ChunkManager* cm = is_class() ? Metaspace::chunk_manager_class() :
147                                   Metaspace::chunk_manager_metadata();

366   while (iter.repeat()) {                                                                                                            
367     st->cr();                                                                                                                        
368     VirtualSpaceNode* node = iter.get_next();                                                                                        
369     node->print_on(st, scale);                                                                                                       
370   }                                                                                                                                  
371 }                                                                                                                                    
372 
373 void VirtualSpaceList::print_map(outputStream* st) const {                                                                           
374   VirtualSpaceNode* list = virtual_space_list();                                                                                     
375   VirtualSpaceListIterator iter(list);                                                                                               
376   unsigned i = 0;                                                                                                                    
377   while (iter.repeat()) {                                                                                                            
378     st->print_cr("Node %u:", i);                                                                                                     
379     VirtualSpaceNode* node = iter.get_next();                                                                                        
380     node->print_map(st, this->is_class());                                                                                           
381     i ++;                                                                                                                            
382   }                                                                                                                                  
383 }                                                                                                                                    
384 
385 } // namespace metaspace                                                                                                             
386                                                                                                                                      

368   while (iter.repeat()) {
369     st->cr();
370     VirtualSpaceNode* node = iter.get_next();
371     node->print_on(st, scale);
372   }
373 }
374 
375 void VirtualSpaceList::print_map(outputStream* st) const {
376   VirtualSpaceNode* list = virtual_space_list();
377   VirtualSpaceListIterator iter(list);
378   unsigned i = 0;
379   while (iter.repeat()) {
380     st->print_cr("Node %u:", i);
381     VirtualSpaceNode* node = iter.get_next();
382     node->print_map(st, this->is_class());
383     i ++;
384   }
385 }
386 
387 } // namespace metaspace

< prev index next >