< prev index next >

src/hotspot/share/code/icBuffer.cpp


20  * questions.                                                                                                                        
21  *                                                                                                                                   
22  */                                                                                                                                  
23 
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());                                                                    

20  * questions.
21  *
22  */
23 
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 #include "runtime/thread.hpp"
41 
42 DEF_STUB_INTERFACE(ICStub);
43 
44 StubQueue* InlineCacheBuffer::_buffer    = NULL;
45 
46 CompiledICHolder* InlineCacheBuffer::_pending_released = NULL;
47 int InlineCacheBuffer::_pending_count = 0;
48 
49 #ifdef ASSERT
50 ICRefillVerifier::ICRefillVerifier()
51   : _refill_requested(false),
52     _refill_remembered(false)
53 {
54   Thread* thread = Thread::current();
55   assert(thread->missed_ic_stub_refill_mark() == NULL, "nesting not supported");
56   thread->set_missed_ic_stub_refill_mark(this);
57 }
58 
59 ICRefillVerifier::~ICRefillVerifier() {
60   assert(!_refill_requested || _refill_remembered,
61          "Forgot to refill IC stubs after failed IC transition");
62   Thread::current()->set_missed_ic_stub_refill_mark(NULL);
63 }
64 
65 ICRefillVerifierMark::ICRefillVerifierMark(ICRefillVerifier* verifier) {
66   Thread* thread = Thread::current();
67   assert(thread->missed_ic_stub_refill_mark() == NULL, "nesting not supported");
68   thread->set_missed_ic_stub_refill_mark(this);
69 }
70 
71 ICRefillVerifierMark::~ICRefillVerifierMark() {
72   Thread::current()->set_missed_ic_stub_refill_mark(NULL);
73 }
74 
75 static ICRefillVerifier* current_ic_refill_verifier() {
76   Thread* current = Thread::current();
77   ICRefillVerifier* verifier = reinterpret_cast<ICRefillVerifier*>(current->missed_ic_stub_refill_mark());
78   assert(verifier != NULL, "need a verifier for safety");
79   return verifier;
80 }
81 #endif
82 
83 void ICStub::finalize() {
84   if (!is_empty()) {
85     ResourceMark rm;
86     CompiledIC *ic = CompiledIC_at(CodeCache::find_compiled(ic_site()), ic_site());
87     assert(CodeCache::find_compiled(ic->instruction_address()) != NULL, "inline cache in non-compiled?");
88 
89     assert(this == ICStub_from_destination_address(ic->stub_address()), "wrong owner of ic buffer");
90     ic->set_ic_destination_and_value(destination(), cached_value());
91   }
92 }
93 
94 
95 address ICStub::destination() const {
96   return InlineCacheBuffer::ic_buffer_entry_point(code_begin());
97 }
98 
99 void* ICStub::cached_value() const {
100   return InlineCacheBuffer::ic_buffer_cached_value(code_begin());

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());                                                                

133 }
134 #endif
135 
136 //-----------------------------------------------------------------------------------------------
137 // Implementation of InlineCacheBuffer
138 
139 
140 void InlineCacheBuffer::initialize() {
141   if (_buffer != NULL) return; // already initialized
142   _buffer = new StubQueue(new ICStubInterface, 10*K, InlineCacheBuffer_lock, "InlineCacheBuffer");
143   assert (_buffer != NULL, "cannot allocate InlineCacheBuffer");
144 }
145 
146 
147 ICStub* InlineCacheBuffer::new_ic_stub() {
148   return (ICStub*)buffer()->request_committed(ic_stub_code_size());
149 }
150 
151 
152 void InlineCacheBuffer::refill_ic_stubs() {
153 #ifdef ASSERT
154   ICRefillVerifier* verifier = current_ic_refill_verifier();
155   verifier->request_remembered();
156 #endif
157   // we ran out of inline cache buffer space; must enter safepoint.
158   // We do this by forcing a safepoint
159   EXCEPTION_MARK;
160 
161   VM_ICBufferFull ibf;
162   VMThread::execute(&ibf);
163   // We could potential get an async. exception at this point.
164   // In that case we will rethrow it to ourselvs.
165   if (HAS_PENDING_EXCEPTION) {
166     oop exception = PENDING_EXCEPTION;
167     CLEAR_PENDING_EXCEPTION;
168     Thread::send_async_exception(JavaThread::current()->threadObj(), exception);
169   }
170 }
171 
172 
173 void InlineCacheBuffer::update_inline_caches() {


174   if (buffer()->number_of_stubs() > 0) {
175     if (TraceICBuffer) {
176       tty->print_cr("[updating inline caches with %d stubs]", buffer()->number_of_stubs());
177     }
178     buffer()->remove_all();
179   }
180   release_pending_icholders();
181 }
182 
183 
184 bool InlineCacheBuffer::contains(address instruction_address) {
185   return buffer()->contains(instruction_address);
186 }
187 
188 
189 bool InlineCacheBuffer::is_empty() {
190   return buffer()->number_of_stubs() == 0;
191 }
192 
193 
194 void InlineCacheBuffer_init() {
195   InlineCacheBuffer::initialize();
196 }
197 

198 bool InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) {
199   assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint");
200   assert(CompiledICLocker::is_safe(ic->instruction_address()), "mt unsafe call");
201   if (TraceICBuffer) {
202     tty->print_cr("  create transition stub for " INTPTR_FORMAT " destination " INTPTR_FORMAT " cached value " INTPTR_FORMAT,
203                   p2i(ic->instruction_address()), p2i(entry), p2i(cached_value));
204   }
205 
206   // allocate and initialize new "out-of-line" inline-cache
207   ICStub* ic_stub = new_ic_stub();
208   if (ic_stub == NULL) {
209 #ifdef ASSERT
210     ICRefillVerifier* verifier = current_ic_refill_verifier();
211     verifier->request_refill();
212 #endif
213     return false;
214   }
215 
216   // If an transition stub is already associate with the inline cache, then we remove the association.
217   if (ic->is_in_transition_state()) {
218     ICStub* old_stub = ICStub_from_destination_address(ic->stub_address());
219     old_stub->clear();
220   }
221 
222   ic_stub->set_stub(ic, cached_value, entry);
223 
224   // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache
225   ic->set_ic_destination(ic_stub);
226   return true;
227 }
228 
229 
230 address InlineCacheBuffer::ic_destination_for(CompiledIC *ic) {
231   ICStub* stub = ICStub_from_destination_address(ic->stub_address());
< prev index next >