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 }
|