< prev index next >

src/hotspot/share/code/icBuffer.cpp


24 #include "precompiled.hpp"                                                                                                           
25 #include "code/codeCache.hpp"                                                                                                        
26 #include "code/compiledIC.hpp"                                                                                                       
27 #include "code/icBuffer.hpp"                                                                                                         
28 #include "code/nmethod.hpp"                                                                                                          
29 #include "code/scopeDesc.hpp"                                                                                                        
30 #include "gc/shared/collectedHeap.inline.hpp"                                                                                        
31 #include "interpreter/interpreter.hpp"                                                                                               
32 #include "interpreter/linkResolver.hpp"                                                                                              
33 #include "memory/resourceArea.hpp"                                                                                                   
34 #include "memory/universe.hpp"                                                                                                       
35 #include "oops/method.hpp"                                                                                                           
36 #include "oops/oop.inline.hpp"                                                                                                       
37 #include "runtime/handles.inline.hpp"                                                                                                
38 #include "runtime/mutexLocker.hpp"                                                                                                   
39 #include "runtime/stubRoutines.hpp"                                                                                                  
40 
41 DEF_STUB_INTERFACE(ICStub);                                                                                                          
42 
43 StubQueue* InlineCacheBuffer::_buffer    = NULL;                                                                                     
44 ICStub*    InlineCacheBuffer::_next_stub = NULL;                                                                                     
45 
46 CompiledICHolder* InlineCacheBuffer::_pending_released = NULL;                                                                       
47 int InlineCacheBuffer::_pending_count = 0;                                                                                           
                                                                                                                                     
48 
49 void ICStub::finalize() {                                                                                                            
50   if (!is_empty()) {                                                                                                                 
51     ResourceMark rm;                                                                                                                 
52     CompiledIC *ic = CompiledIC_at(CodeCache::find_compiled(ic_site()), ic_site());                                                  
53     assert(CodeCache::find_compiled(ic->instruction_address()) != NULL, "inline cache in non-compiled?");                            
54 
55     assert(this == ICStub_from_destination_address(ic->stub_address()), "wrong owner of ic buffer");                                 
56     ic->set_ic_destination_and_value(destination(), cached_value());                                                                 
57   }                                                                                                                                  
58 }                                                                                                                                    
59 
60 
61 address ICStub::destination() const {                                                                                                
62   return InlineCacheBuffer::ic_buffer_entry_point(code_begin());                                                                     
63 }                                                                                                                                    
64 
65 void* ICStub::cached_value() const {                                                                                                 
66   return InlineCacheBuffer::ic_buffer_cached_value(code_begin());                                                                    

24 #include "precompiled.hpp"
25 #include "code/codeCache.hpp"
26 #include "code/compiledIC.hpp"
27 #include "code/icBuffer.hpp"
28 #include "code/nmethod.hpp"
29 #include "code/scopeDesc.hpp"
30 #include "gc/shared/collectedHeap.inline.hpp"
31 #include "interpreter/interpreter.hpp"
32 #include "interpreter/linkResolver.hpp"
33 #include "memory/resourceArea.hpp"
34 #include "memory/universe.hpp"
35 #include "oops/method.hpp"
36 #include "oops/oop.inline.hpp"
37 #include "runtime/handles.inline.hpp"
38 #include "runtime/mutexLocker.hpp"
39 #include "runtime/stubRoutines.hpp"
40 
41 DEF_STUB_INTERFACE(ICStub);
42 
43 StubQueue* InlineCacheBuffer::_buffer    = NULL;

44 
45 CompiledICHolder* InlineCacheBuffer::_pending_released = NULL;
46 int InlineCacheBuffer::_pending_count = 0;
47 DEBUG_ONLY(volatile int InlineCacheBuffer::_needs_refill = 0;)
48 
49 void ICStub::finalize() {
50   if (!is_empty()) {
51     ResourceMark rm;
52     CompiledIC *ic = CompiledIC_at(CodeCache::find_compiled(ic_site()), ic_site());
53     assert(CodeCache::find_compiled(ic->instruction_address()) != NULL, "inline cache in non-compiled?");
54 
55     assert(this == ICStub_from_destination_address(ic->stub_address()), "wrong owner of ic buffer");
56     ic->set_ic_destination_and_value(destination(), cached_value());
57   }
58 }
59 
60 
61 address ICStub::destination() const {
62   return InlineCacheBuffer::ic_buffer_entry_point(code_begin());
63 }
64 
65 void* ICStub::cached_value() const {
66   return InlineCacheBuffer::ic_buffer_cached_value(code_begin());

85     InlineCacheBuffer::queue_for_release((CompiledICHolder*)cached_value());                                                         
86   }                                                                                                                                  
87   _ic_site = NULL;                                                                                                                   
88 }                                                                                                                                    
89 
90 
91 #ifndef PRODUCT                                                                                                                      
92 // anybody calling to this stub will trap                                                                                            
93 
94 void ICStub::verify() {                                                                                                              
95 }                                                                                                                                    
96 
97 void ICStub::print() {                                                                                                               
98   tty->print_cr("ICStub: site: " INTPTR_FORMAT, p2i(_ic_site));                                                                      
99 }                                                                                                                                    
100 #endif                                                                                                                               
101 
102 //-----------------------------------------------------------------------------------------------                                    
103 // Implementation of InlineCacheBuffer                                                                                               
104 
105 void InlineCacheBuffer::init_next_stub() {                                                                                           
106   ICStub* ic_stub = (ICStub*)buffer()->request_committed (ic_stub_code_size());                                                      
107   assert (ic_stub != NULL, "no room for a single stub");                                                                             
108   set_next_stub(ic_stub);                                                                                                            
109 }                                                                                                                                    
110 
111 void InlineCacheBuffer::initialize() {                                                                                               
112   if (_buffer != NULL) return; // already initialized                                                                                
113   _buffer = new StubQueue(new ICStubInterface, 10*K, InlineCacheBuffer_lock, "InlineCacheBuffer");                                   
114   assert (_buffer != NULL, "cannot allocate InlineCacheBuffer");                                                                     
115   init_next_stub();                                                                                                                  
116 }                                                                                                                                    
117 
118 
119 ICStub* InlineCacheBuffer::new_ic_stub() {                                                                                           
120   while (true) {                                                                                                                     
121     ICStub* ic_stub = (ICStub*)buffer()->request_committed(ic_stub_code_size());                                                     
122     if (ic_stub != NULL) {                                                                                                           
123       return ic_stub;                                                                                                                
124     }                                                                                                                                
125     // we ran out of inline cache buffer space; must enter safepoint.                                                                
126     // We do this by forcing a safepoint                                                                                             
127     EXCEPTION_MARK;                                                                                                                  
128                                                                                                                                      
129     VM_ICBufferFull ibf;                                                                                                             
130     VMThread::execute(&ibf);                                                                                                         
131     // We could potential get an async. exception at this point.                                                                     
132     // In that case we will rethrow it to ourselvs.                                                                                  
133     if (HAS_PENDING_EXCEPTION) {                                                                                                     
134       oop exception = PENDING_EXCEPTION;                                                                                             
135       CLEAR_PENDING_EXCEPTION;                                                                                                       
136       Thread::send_async_exception(JavaThread::current()->threadObj(), exception);                                                   
137     }                                                                                                                                
138   }                                                                                                                                  
139   ShouldNotReachHere();                                                                                                              
140   return NULL;                                                                                                                       
141 }                                                                                                                                    
142 
143 
144 void InlineCacheBuffer::update_inline_caches() {                                                                                     
145   if (buffer()->number_of_stubs() > 1) {                                                                                             
                                                                                                                                     
                                                                                                                                     
146     if (TraceICBuffer) {                                                                                                             
147       tty->print_cr("[updating inline caches with %d stubs]", buffer()->number_of_stubs());                                          
148     }                                                                                                                                
149     buffer()->remove_all();                                                                                                          
150     init_next_stub();                                                                                                                
151   }                                                                                                                                  
152   release_pending_icholders();                                                                                                       
153 }                                                                                                                                    
154 
155 
156 bool InlineCacheBuffer::contains(address instruction_address) {                                                                      
157   return buffer()->contains(instruction_address);                                                                                    
158 }                                                                                                                                    
159 
160 
161 bool InlineCacheBuffer::is_empty() {                                                                                                 
162   return buffer()->number_of_stubs() == 1;    // always has sentinel                                                                 
163 }                                                                                                                                    
164 
165 
166 void InlineCacheBuffer_init() {                                                                                                      
167   InlineCacheBuffer::initialize();                                                                                                   
168 }                                                                                                                                    
169 
170 
171 void InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) {                                  
172   MutexLockerEx ml(CompiledIC_lock->owned_by_self() ? NULL : CompiledIC_lock);                                                       
173   assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint");                                       
174   assert(CompiledICLocker::is_safe(ic->instruction_address()), "mt unsafe call");                                                    
175   if (TraceICBuffer) {                                                                                                               
176     tty->print_cr("  create transition stub for " INTPTR_FORMAT " destination " INTPTR_FORMAT " cached value " INTPTR_FORMAT,        
177                   p2i(ic->instruction_address()), p2i(entry), p2i(cached_value));                                                    
178   }                                                                                                                                  
179 
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
180   // If an transition stub is already associate with the inline cache, then we remove the association.                               
181   if (ic->is_in_transition_state()) {                                                                                                
182     ICStub* old_stub = ICStub_from_destination_address(ic->stub_address());                                                          
183     old_stub->clear();                                                                                                               
184   }                                                                                                                                  
185 
186   // allocate and initialize new "out-of-line" inline-cache                                                                          
187   ICStub* ic_stub = get_next_stub();                                                                                                 
188   ic_stub->set_stub(ic, cached_value, entry);                                                                                        
189 
190   // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache                                             
191   ic->set_ic_destination(ic_stub);                                                                                                   
192                                                                                                                                      
193   set_next_stub(new_ic_stub()); // can cause safepoint synchronization                                                               
194 }                                                                                                                                    
195 
196 
197 address InlineCacheBuffer::ic_destination_for(CompiledIC *ic) {                                                                      
198   ICStub* stub = ICStub_from_destination_address(ic->stub_address());                                                                
199   return stub->destination();                                                                                                        
200 }                                                                                                                                    
201 
202 
203 void* InlineCacheBuffer::cached_value_for(CompiledIC *ic) {                                                                          
204   ICStub* stub = ICStub_from_destination_address(ic->stub_address());                                                                
205   return stub->cached_value();                                                                                                       
206 }                                                                                                                                    
207 
208 
209 // Free CompiledICHolder*s that are no longer in use                                                                                 
210 void InlineCacheBuffer::release_pending_icholders() {                                                                                
211   assert(SafepointSynchronize::is_at_safepoint(), "should only be called during a safepoint");                                       
212   CompiledICHolder* holder = _pending_released;                                                                                      
213   _pending_released = NULL;                                                                                                          
214   while (holder != NULL) {                                                                                                           
215     CompiledICHolder* next = holder->next();                                                                                         
216     delete holder;                                                                                                                   
217     holder = next;                                                                                                                   
218     _pending_count--;                                                                                                                
219   }                                                                                                                                  
220   assert(_pending_count == 0, "wrong count");                                                                                        
221 }                                                                                                                                    
222 
223 // Enqueue this icholder for release during the next safepoint.  It's                                                                
224 // not safe to free them until them since they might be visible to                                                                   
225 // another thread.                                                                                                                   
226 void InlineCacheBuffer::queue_for_release(CompiledICHolder* icholder) {                                                              
227   MutexLockerEx mex1((CompiledIC_lock->owned_by_self() ||                                                                            
228                       SafepointSynchronize::is_at_safepoint()) ? NULL : CompiledIC_lock);                                            
229   MutexLockerEx mex2(InlineCacheBuffer_lock);                                                                                        
230   icholder->set_next(_pending_released);                                                                                             
231   _pending_released = icholder;                                                                                                      
232   _pending_count++;                                                                                                                  
233   if (TraceICBuffer) {                                                                                                               
234     tty->print_cr("enqueueing icholder " INTPTR_FORMAT " to be freed", p2i(icholder));                                               
235   }                                                                                                                                  
236 }                                                                                                                                    

85     InlineCacheBuffer::queue_for_release((CompiledICHolder*)cached_value());
86   }
87   _ic_site = NULL;
88 }
89 
90 
91 #ifndef PRODUCT
92 // anybody calling to this stub will trap
93 
94 void ICStub::verify() {
95 }
96 
97 void ICStub::print() {
98   tty->print_cr("ICStub: site: " INTPTR_FORMAT, p2i(_ic_site));
99 }
100 #endif
101 
102 //-----------------------------------------------------------------------------------------------
103 // Implementation of InlineCacheBuffer
104 





105 
106 void InlineCacheBuffer::initialize() {
107   if (_buffer != NULL) return; // already initialized
108   _buffer = new StubQueue(new ICStubInterface, 10*K, InlineCacheBuffer_lock, "InlineCacheBuffer");
109   assert (_buffer != NULL, "cannot allocate InlineCacheBuffer");

110 }
111 
112 
113 ICStub* InlineCacheBuffer::new_ic_stub() {
114   return (ICStub*)buffer()->request_committed(ic_stub_code_size());
115 }
116 
117 
118 void InlineCacheBuffer::refill_ic_stubs() {
119   DEBUG_ONLY(Atomic::store(0, &_needs_refill));
120   // we ran out of inline cache buffer space; must enter safepoint.
121   // We do this by forcing a safepoint
122   EXCEPTION_MARK;
123 
124   VM_ICBufferFull ibf;
125   VMThread::execute(&ibf);
126   // We could potential get an async. exception at this point.
127   // In that case we will rethrow it to ourselvs.
128   if (HAS_PENDING_EXCEPTION) {
129     oop exception = PENDING_EXCEPTION;
130     CLEAR_PENDING_EXCEPTION;
131     Thread::send_async_exception(JavaThread::current()->threadObj(), exception);
132   }


133 }
134 
135 
136 void InlineCacheBuffer::update_inline_caches() {
137   assert(_needs_refill == 0,
138          "Forgot to handle a failed IC transition requiring IC stubs");
139   if (buffer()->number_of_stubs() > 0) {
140     if (TraceICBuffer) {
141       tty->print_cr("[updating inline caches with %d stubs]", buffer()->number_of_stubs());
142     }
143     buffer()->remove_all();

144   }
145   release_pending_icholders();
146 }
147 
148 
149 bool InlineCacheBuffer::contains(address instruction_address) {
150   return buffer()->contains(instruction_address);
151 }
152 
153 
154 bool InlineCacheBuffer::is_empty() {
155   return buffer()->number_of_stubs() == 0;
156 }
157 
158 
159 void InlineCacheBuffer_init() {
160   InlineCacheBuffer::initialize();
161 }
162 
163 
164 bool InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) {

165   assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint");
166   assert(CompiledICLocker::is_safe(ic->instruction_address()), "mt unsafe call");
167   if (TraceICBuffer) {
168     tty->print_cr("  create transition stub for " INTPTR_FORMAT " destination " INTPTR_FORMAT " cached value " INTPTR_FORMAT,
169                   p2i(ic->instruction_address()), p2i(entry), p2i(cached_value));
170   }
171 
172   // allocate and initialize new "out-of-line" inline-cache
173   ICStub* ic_stub = new_ic_stub();
174   if (ic_stub == NULL) {
175     DEBUG_ONLY(Atomic::inc(&_needs_refill));
176     return false;
177   }
178 
179   // If an transition stub is already associate with the inline cache, then we remove the association.
180   if (ic->is_in_transition_state()) {
181     ICStub* old_stub = ICStub_from_destination_address(ic->stub_address());
182     old_stub->clear();
183   }
184 


185   ic_stub->set_stub(ic, cached_value, entry);
186 
187   // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache
188   ic->set_ic_destination(ic_stub);
189   return true;

190 }
191 
192 
193 address InlineCacheBuffer::ic_destination_for(CompiledIC *ic) {
194   ICStub* stub = ICStub_from_destination_address(ic->stub_address());
195   return stub->destination();
196 }
197 
198 
199 void* InlineCacheBuffer::cached_value_for(CompiledIC *ic) {
200   ICStub* stub = ICStub_from_destination_address(ic->stub_address());
201   return stub->cached_value();
202 }
203 
204 
205 // Free CompiledICHolder*s that are no longer in use
206 void InlineCacheBuffer::release_pending_icholders() {
207   assert(SafepointSynchronize::is_at_safepoint(), "should only be called during a safepoint");
208   CompiledICHolder* holder = _pending_released;
209   _pending_released = NULL;
210   while (holder != NULL) {
211     CompiledICHolder* next = holder->next();
212     delete holder;
213     holder = next;
214     _pending_count--;
215   }
216   assert(_pending_count == 0, "wrong count");
217 }
218 
219 // Enqueue this icholder for release during the next safepoint.  It's
220 // not safe to free them until them since they might be visible to
221 // another thread.
222 void InlineCacheBuffer::queue_for_release(CompiledICHolder* icholder) {
223   MutexLockerEx mex(InlineCacheBuffer_lock, Mutex::_no_safepoint_check_flag);


224   icholder->set_next(_pending_released);
225   _pending_released = icholder;
226   _pending_count++;
227   if (TraceICBuffer) {
228     tty->print_cr("enqueueing icholder " INTPTR_FORMAT " to be freed", p2i(icholder));
229   }
230 }
< prev index next >