< prev index next >

src/hotspot/share/gc/z/zNMethodTable.cpp


33 #include "oops/oop.inline.hpp"                                                                                                       
34 #include "runtime/atomic.hpp"                                                                                                        
35 #include "utilities/debug.hpp"                                                                                                       
36 
37 class ZNMethodWithImmediateOops {                                                                                                    
38 private:                                                                                                                             
39   nmethod* const _nm;                                                                                                                
40   const size_t   _nimmediate_oops;                                                                                                   
41 
42   static size_t header_size();                                                                                                       
43 
44   ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops);                                                 
45 
46 public:                                                                                                                              
47   static ZNMethodWithImmediateOops* create(nmethod* nm, const GrowableArray<oop*>& immediate_oops);                                  
48   static void destroy(ZNMethodWithImmediateOops* nmi);                                                                               
49 
50   nmethod* method() const;                                                                                                           
51   size_t immediate_oops_count() const;                                                                                               
52   oop** immediate_oops_begin() const;                                                                                                
53   oop** immediate_oops_begin_safe() const;                                                                                           
54   oop** immediate_oops_end() const;                                                                                                  
55 };                                                                                                                                   
56 
57 size_t ZNMethodWithImmediateOops::header_size() {                                                                                    
58   const size_t size = sizeof(ZNMethodWithImmediateOops);                                                                             
59   assert(is_aligned(size, sizeof(oop*)), "Header misaligned");                                                                       
60   return size;                                                                                                                       
61 }                                                                                                                                    
62 
63 ZNMethodWithImmediateOops::ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops) :                       
64     _nm(nm),                                                                                                                         
65     _nimmediate_oops(immediate_oops.length()) {                                                                                      
66   // Save all immediate oops                                                                                                         
67   for (size_t i = 0; i < _nimmediate_oops; i++) {                                                                                    
68     immediate_oops_begin()[i] = immediate_oops.at(i);                                                                                
69   }                                                                                                                                  
70 }                                                                                                                                    
71 
72 ZNMethodWithImmediateOops* ZNMethodWithImmediateOops::create(nmethod* nm, const GrowableArray<oop*>& immediate_oops) {               

33 #include "oops/oop.inline.hpp"
34 #include "runtime/atomic.hpp"
35 #include "utilities/debug.hpp"
36 
37 class ZNMethodWithImmediateOops {
38 private:
39   nmethod* const _nm;
40   const size_t   _nimmediate_oops;
41 
42   static size_t header_size();
43 
44   ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops);
45 
46 public:
47   static ZNMethodWithImmediateOops* create(nmethod* nm, const GrowableArray<oop*>& immediate_oops);
48   static void destroy(ZNMethodWithImmediateOops* nmi);
49 
50   nmethod* method() const;
51   size_t immediate_oops_count() const;
52   oop** immediate_oops_begin() const;

53   oop** immediate_oops_end() const;
54 };
55 
56 size_t ZNMethodWithImmediateOops::header_size() {
57   const size_t size = sizeof(ZNMethodWithImmediateOops);
58   assert(is_aligned(size, sizeof(oop*)), "Header misaligned");
59   return size;
60 }
61 
62 ZNMethodWithImmediateOops::ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops) :
63     _nm(nm),
64     _nimmediate_oops(immediate_oops.length()) {
65   // Save all immediate oops
66   for (size_t i = 0; i < _nimmediate_oops; i++) {
67     immediate_oops_begin()[i] = immediate_oops.at(i);
68   }
69 }
70 
71 ZNMethodWithImmediateOops* ZNMethodWithImmediateOops::create(nmethod* nm, const GrowableArray<oop*>& immediate_oops) {

77   return ::new (method_with_immediate_oops) ZNMethodWithImmediateOops(nm, immediate_oops);                                           
78 }                                                                                                                                    
79 
80 void ZNMethodWithImmediateOops::destroy(ZNMethodWithImmediateOops* nmi) {                                                            
81   FREE_C_HEAP_ARRAY(uint8_t, nmi);                                                                                                   
82 }                                                                                                                                    
83 
84 nmethod* ZNMethodWithImmediateOops::method() const {                                                                                 
85   return _nm;                                                                                                                        
86 }                                                                                                                                    
87 
88 size_t ZNMethodWithImmediateOops::immediate_oops_count() const {                                                                     
89   return _nimmediate_oops;                                                                                                           
90 }                                                                                                                                    
91 
92 oop** ZNMethodWithImmediateOops::immediate_oops_begin() const {                                                                      
93   // The immediate oop* array starts immediately after this object                                                                   
94   return (oop**)((uintptr_t)this + header_size());                                                                                   
95 }                                                                                                                                    
96 
97 oop** ZNMethodWithImmediateOops::immediate_oops_begin_safe() const {                                                                 
98   // Non-entrant nmethods have a jump instruction patched into the beginning                                                         
99   // of the verified entry point, which could have overwritten an immediate                                                          
100   // oop. If so, make sure we skip over that oop.                                                                                    
101   if (_nm->is_not_entrant()) {                                                                                                       
102     oop* const first_immediate_oop = *immediate_oops_begin();                                                                        
103     oop* const safe_begin = (oop*)(_nm->verified_entry_point() + NativeJump::instruction_size);                                      
104     if (first_immediate_oop < safe_begin) {                                                                                          
105       // First immediate oop overwritten, skip it                                                                                    
106       return immediate_oops_begin() + 1;                                                                                             
107     }                                                                                                                                
108   }                                                                                                                                  
109                                                                                                                                      
110   // First immediate oop not overwritten                                                                                             
111   return immediate_oops_begin();                                                                                                     
112 }                                                                                                                                    
113                                                                                                                                      
114                                                                                                                                      
115 oop** ZNMethodWithImmediateOops::immediate_oops_end() const {                                                                        
116   return immediate_oops_begin() + immediate_oops_count();                                                                            
117 }                                                                                                                                    
118 
119 ZNMethodTableEntry* ZNMethodTable::_table = NULL;                                                                                    
120 size_t ZNMethodTable::_size = 0;                                                                                                     
121 size_t ZNMethodTable::_nregistered = 0;                                                                                              
122 size_t ZNMethodTable::_nunregistered = 0;                                                                                            
123 volatile size_t ZNMethodTable::_claimed = 0;                                                                                         
124 
125 ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) {                                                                        
126   GrowableArray<oop*> immediate_oops;                                                                                                
127   bool non_immediate_oops = false;                                                                                                   
128 
129   // Find all oops relocations                                                                                                       
130   RelocIterator iter(nm);                                                                                                            
131   while (iter.next()) {                                                                                                              
132     if (iter.type() != relocInfo::oop_type) {                                                                                        
133       // Not an oop                                                                                                                  

76   return ::new (method_with_immediate_oops) ZNMethodWithImmediateOops(nm, immediate_oops);
77 }
78 
79 void ZNMethodWithImmediateOops::destroy(ZNMethodWithImmediateOops* nmi) {
80   FREE_C_HEAP_ARRAY(uint8_t, nmi);
81 }
82 
83 nmethod* ZNMethodWithImmediateOops::method() const {
84   return _nm;
85 }
86 
87 size_t ZNMethodWithImmediateOops::immediate_oops_count() const {
88   return _nimmediate_oops;
89 }
90 
91 oop** ZNMethodWithImmediateOops::immediate_oops_begin() const {
92   // The immediate oop* array starts immediately after this object
93   return (oop**)((uintptr_t)this + header_size());
94 }
95 


















96 oop** ZNMethodWithImmediateOops::immediate_oops_end() const {
97   return immediate_oops_begin() + immediate_oops_count();
98 }
99 
100 ZNMethodTableEntry* ZNMethodTable::_table = NULL;
101 size_t ZNMethodTable::_size = 0;
102 size_t ZNMethodTable::_nregistered = 0;
103 size_t ZNMethodTable::_nunregistered = 0;
104 volatile size_t ZNMethodTable::_claimed = 0;
105 
106 ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) {
107   GrowableArray<oop*> immediate_oops;
108   bool non_immediate_oops = false;
109 
110   // Find all oops relocations
111   RelocIterator iter(nm);
112   while (iter.next()) {
113     if (iter.type() != relocInfo::oop_type) {
114       // Not an oop

411 
412 void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) {                                                        
413   nmethod* const nm = method(entry);                                                                                                 
414   if (!nm->is_alive()) {                                                                                                             
415     // No need to visit oops                                                                                                         
416     return;                                                                                                                          
417   }                                                                                                                                  
418 
419   // Process oops table                                                                                                              
420   oop* const begin = nm->oops_begin();                                                                                               
421   oop* const end = nm->oops_end();                                                                                                   
422   for (oop* p = begin; p < end; p++) {                                                                                               
423     if (*p != Universe::non_oop_word()) {                                                                                            
424       cl->do_oop(p);                                                                                                                 
425     }                                                                                                                                
426   }                                                                                                                                  
427 
428   if (entry.immediate_oops()) {                                                                                                      
429     // Process immediate oops                                                                                                        
430     const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops();                                                 
431     oop** const begin = nmi->immediate_oops_begin_safe();                                                                            
432     oop** const end = nmi->immediate_oops_end();                                                                                     
433     for (oop** p = begin; p < end; p++) {                                                                                            
434       cl->do_oop(*p);                                                                                                                
435     }                                                                                                                                
436   }                                                                                                                                  
437 
438   if (entry.non_immediate_oops()) {                                                                                                  
439     // Process non-immediate oops                                                                                                    
440     nm->fix_oop_relocations();                                                                                                       
441   }                                                                                                                                  
442 }                                                                                                                                    
443 
444 void ZNMethodTable::oops_do(OopClosure* cl) {                                                                                        
445   for (;;) {                                                                                                                         
446     // Claim table partition. Each partition is currently sized to span                                                              
447     // two cache lines. This number is just a guess, but seems to work well.                                                         
448     const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);                                                 
449     const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size);                             
450     const size_t partition_end = MIN2(partition_start + partition_size, _size);                                                      

392 
393 void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) {
394   nmethod* const nm = method(entry);
395   if (!nm->is_alive()) {
396     // No need to visit oops
397     return;
398   }
399 
400   // Process oops table
401   oop* const begin = nm->oops_begin();
402   oop* const end = nm->oops_end();
403   for (oop* p = begin; p < end; p++) {
404     if (*p != Universe::non_oop_word()) {
405       cl->do_oop(p);
406     }
407   }
408 
409   if (entry.immediate_oops()) {
410     // Process immediate oops
411     const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops();
412     oop** const begin = nmi->immediate_oops_begin();
413     oop** const end = nmi->immediate_oops_end();
414     for (oop** p = begin; p < end; p++) {
415       cl->do_oop(*p);
416     }
417   }
418 
419   if (entry.non_immediate_oops()) {
420     // Process non-immediate oops
421     nm->fix_oop_relocations();
422   }
423 }
424 
425 void ZNMethodTable::oops_do(OopClosure* cl) {
426   for (;;) {
427     // Claim table partition. Each partition is currently sized to span
428     // two cache lines. This number is just a guess, but seems to work well.
429     const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
430     const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size);
431     const size_t partition_end = MIN2(partition_start + partition_size, _size);
< prev index next >