Mercurial > hg > truffle
annotate src/share/vm/code/codeCache.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | 2a47bd84841f |
children | 3e8fbc61cee8 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1538
diff
changeset
|
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1538
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1538
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1538
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_codeCache.cpp.incl" | |
27 | |
28 // Helper class for printing in CodeCache | |
29 | |
30 class CodeBlob_sizes { | |
31 private: | |
32 int count; | |
33 int total_size; | |
34 int header_size; | |
35 int code_size; | |
36 int stub_size; | |
37 int relocation_size; | |
38 int scopes_oop_size; | |
39 int scopes_data_size; | |
40 int scopes_pcs_size; | |
41 | |
42 public: | |
43 CodeBlob_sizes() { | |
44 count = 0; | |
45 total_size = 0; | |
46 header_size = 0; | |
47 code_size = 0; | |
48 stub_size = 0; | |
49 relocation_size = 0; | |
50 scopes_oop_size = 0; | |
51 scopes_data_size = 0; | |
52 scopes_pcs_size = 0; | |
53 } | |
54 | |
55 int total() { return total_size; } | |
56 bool is_empty() { return count == 0; } | |
57 | |
58 void print(const char* title) { | |
59 tty->print_cr(" #%d %s = %dK (hdr %d%%, loc %d%%, code %d%%, stub %d%%, [oops %d%%, data %d%%, pcs %d%%])", | |
60 count, | |
61 title, | |
62 total() / K, | |
63 header_size * 100 / total_size, | |
64 relocation_size * 100 / total_size, | |
65 code_size * 100 / total_size, | |
66 stub_size * 100 / total_size, | |
67 scopes_oop_size * 100 / total_size, | |
68 scopes_data_size * 100 / total_size, | |
69 scopes_pcs_size * 100 / total_size); | |
70 } | |
71 | |
72 void add(CodeBlob* cb) { | |
73 count++; | |
74 total_size += cb->size(); | |
75 header_size += cb->header_size(); | |
76 relocation_size += cb->relocation_size(); | |
77 if (cb->is_nmethod()) { | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
78 nmethod* nm = cb->as_nmethod_or_null(); |
0 | 79 code_size += nm->code_size(); |
80 stub_size += nm->stub_size(); | |
81 | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
82 scopes_oop_size += nm->oops_size(); |
0 | 83 scopes_data_size += nm->scopes_data_size(); |
84 scopes_pcs_size += nm->scopes_pcs_size(); | |
85 } else { | |
86 code_size += cb->instructions_size(); | |
87 } | |
88 } | |
89 }; | |
90 | |
91 | |
92 // CodeCache implementation | |
93 | |
94 CodeHeap * CodeCache::_heap = new CodeHeap(); | |
95 int CodeCache::_number_of_blobs = 0; | |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
96 int CodeCache::_number_of_adapters = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
97 int CodeCache::_number_of_nmethods = 0; |
0 | 98 int CodeCache::_number_of_nmethods_with_dependencies = 0; |
99 bool CodeCache::_needs_cache_clean = false; | |
989 | 100 nmethod* CodeCache::_scavenge_root_nmethods = NULL; |
1202 | 101 nmethod* CodeCache::_saved_nmethods = NULL; |
0 | 102 |
103 | |
104 CodeBlob* CodeCache::first() { | |
105 assert_locked_or_safepoint(CodeCache_lock); | |
106 return (CodeBlob*)_heap->first(); | |
107 } | |
108 | |
109 | |
110 CodeBlob* CodeCache::next(CodeBlob* cb) { | |
111 assert_locked_or_safepoint(CodeCache_lock); | |
112 return (CodeBlob*)_heap->next(cb); | |
113 } | |
114 | |
115 | |
116 CodeBlob* CodeCache::alive(CodeBlob *cb) { | |
117 assert_locked_or_safepoint(CodeCache_lock); | |
118 while (cb != NULL && !cb->is_alive()) cb = next(cb); | |
119 return cb; | |
120 } | |
121 | |
122 | |
123 nmethod* CodeCache::alive_nmethod(CodeBlob* cb) { | |
124 assert_locked_or_safepoint(CodeCache_lock); | |
125 while (cb != NULL && (!cb->is_alive() || !cb->is_nmethod())) cb = next(cb); | |
126 return (nmethod*)cb; | |
127 } | |
128 | |
1538
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
129 nmethod* CodeCache::first_nmethod() { |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
130 assert_locked_or_safepoint(CodeCache_lock); |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
131 CodeBlob* cb = first(); |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
132 while (cb != NULL && !cb->is_nmethod()) { |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
133 cb = next(cb); |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
134 } |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
135 return (nmethod*)cb; |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
136 } |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
137 |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
138 nmethod* CodeCache::next_nmethod (CodeBlob* cb) { |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
139 assert_locked_or_safepoint(CodeCache_lock); |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
140 cb = next(cb); |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
141 while (cb != NULL && !cb->is_nmethod()) { |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
142 cb = next(cb); |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
143 } |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
144 return (nmethod*)cb; |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
145 } |
0 | 146 |
147 CodeBlob* CodeCache::allocate(int size) { | |
148 // Do not seize the CodeCache lock here--if the caller has not | |
149 // already done so, we are going to lose bigtime, since the code | |
150 // cache will contain a garbage CodeBlob until the caller can | |
151 // run the constructor for the CodeBlob subclass he is busy | |
152 // instantiating. | |
153 guarantee(size >= 0, "allocation request must be reasonable"); | |
154 assert_locked_or_safepoint(CodeCache_lock); | |
155 CodeBlob* cb = NULL; | |
156 _number_of_blobs++; | |
157 while (true) { | |
158 cb = (CodeBlob*)_heap->allocate(size); | |
159 if (cb != NULL) break; | |
160 if (!_heap->expand_by(CodeCacheExpansionSize)) { | |
161 // Expansion failed | |
162 return NULL; | |
163 } | |
164 if (PrintCodeCacheExtension) { | |
165 ResourceMark rm; | |
166 tty->print_cr("code cache extended to [" INTPTR_FORMAT ", " INTPTR_FORMAT "] (%d bytes)", | |
167 (intptr_t)_heap->begin(), (intptr_t)_heap->end(), | |
168 (address)_heap->end() - (address)_heap->begin()); | |
169 } | |
170 } | |
171 verify_if_often(); | |
989 | 172 print_trace("allocation", cb, size); |
0 | 173 return cb; |
174 } | |
175 | |
176 void CodeCache::free(CodeBlob* cb) { | |
177 assert_locked_or_safepoint(CodeCache_lock); | |
178 verify_if_often(); | |
179 | |
989 | 180 print_trace("free", cb); |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
181 if (cb->is_nmethod()) { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
182 _number_of_nmethods--; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
183 if (((nmethod *)cb)->has_dependencies()) { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
184 _number_of_nmethods_with_dependencies--; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
185 } |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
186 } |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
187 if (cb->is_adapter_blob()) { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
188 _number_of_adapters--; |
0 | 189 } |
190 _number_of_blobs--; | |
191 | |
192 _heap->deallocate(cb); | |
193 | |
194 verify_if_often(); | |
195 assert(_number_of_blobs >= 0, "sanity check"); | |
196 } | |
197 | |
198 | |
199 void CodeCache::commit(CodeBlob* cb) { | |
200 // this is called by nmethod::nmethod, which must already own CodeCache_lock | |
201 assert_locked_or_safepoint(CodeCache_lock); | |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
202 if (cb->is_nmethod()) { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
203 _number_of_nmethods++; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
204 if (((nmethod *)cb)->has_dependencies()) { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
205 _number_of_nmethods_with_dependencies++; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
206 } |
0 | 207 } |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
208 if (cb->is_adapter_blob()) { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
209 _number_of_adapters++; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
210 } |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1579
diff
changeset
|
211 |
0 | 212 // flush the hardware I-cache |
213 ICache::invalidate_range(cb->instructions_begin(), cb->instructions_size()); | |
214 } | |
215 | |
216 | |
217 void CodeCache::flush() { | |
218 assert_locked_or_safepoint(CodeCache_lock); | |
219 Unimplemented(); | |
220 } | |
221 | |
222 | |
223 // Iteration over CodeBlobs | |
224 | |
225 #define FOR_ALL_BLOBS(var) for (CodeBlob *var = first() ; var != NULL; var = next(var) ) | |
226 #define FOR_ALL_ALIVE_BLOBS(var) for (CodeBlob *var = alive(first()); var != NULL; var = alive(next(var))) | |
227 #define FOR_ALL_ALIVE_NMETHODS(var) for (nmethod *var = alive_nmethod(first()); var != NULL; var = alive_nmethod(next(var))) | |
228 | |
229 | |
230 bool CodeCache::contains(void *p) { | |
231 // It should be ok to call contains without holding a lock | |
232 return _heap->contains(p); | |
233 } | |
234 | |
235 | |
236 // This method is safe to call without holding the CodeCache_lock, as long as a dead codeblob is not | |
237 // looked up (i.e., one that has been marked for deletion). It only dependes on the _segmap to contain | |
238 // valid indices, which it will always do, as long as the CodeBlob is not in the process of being recycled. | |
239 CodeBlob* CodeCache::find_blob(void* start) { | |
240 CodeBlob* result = find_blob_unsafe(start); | |
241 if (result == NULL) return NULL; | |
242 // We could potientially look up non_entrant methods | |
243 guarantee(!result->is_zombie() || result->is_locked_by_vm() || is_error_reported(), "unsafe access to zombie method"); | |
244 return result; | |
245 } | |
246 | |
247 nmethod* CodeCache::find_nmethod(void* start) { | |
248 CodeBlob *cb = find_blob(start); | |
249 assert(cb == NULL || cb->is_nmethod(), "did not find an nmethod"); | |
250 return (nmethod*)cb; | |
251 } | |
252 | |
253 | |
254 void CodeCache::blobs_do(void f(CodeBlob* nm)) { | |
255 assert_locked_or_safepoint(CodeCache_lock); | |
256 FOR_ALL_BLOBS(p) { | |
257 f(p); | |
258 } | |
259 } | |
260 | |
261 | |
262 void CodeCache::nmethods_do(void f(nmethod* nm)) { | |
263 assert_locked_or_safepoint(CodeCache_lock); | |
264 FOR_ALL_BLOBS(nm) { | |
265 if (nm->is_nmethod()) f((nmethod*)nm); | |
266 } | |
267 } | |
268 | |
269 | |
270 int CodeCache::alignment_unit() { | |
271 return (int)_heap->alignment_unit(); | |
272 } | |
273 | |
274 | |
275 int CodeCache::alignment_offset() { | |
276 return (int)_heap->alignment_offset(); | |
277 } | |
278 | |
279 | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
280 // Mark nmethods for unloading if they contain otherwise unreachable |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
281 // oops. |
0 | 282 void CodeCache::do_unloading(BoolObjectClosure* is_alive, |
283 OopClosure* keep_alive, | |
284 bool unloading_occurred) { | |
285 assert_locked_or_safepoint(CodeCache_lock); | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
286 FOR_ALL_ALIVE_NMETHODS(nm) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
287 nm->do_unloading(is_alive, keep_alive, unloading_occurred); |
0 | 288 } |
289 } | |
290 | |
989 | 291 void CodeCache::blobs_do(CodeBlobClosure* f) { |
0 | 292 assert_locked_or_safepoint(CodeCache_lock); |
293 FOR_ALL_ALIVE_BLOBS(cb) { | |
989 | 294 f->do_code_blob(cb); |
295 | |
296 #ifdef ASSERT | |
297 if (cb->is_nmethod()) | |
298 ((nmethod*)cb)->verify_scavenge_root_oops(); | |
299 #endif //ASSERT | |
0 | 300 } |
301 } | |
302 | |
989 | 303 // Walk the list of methods which might contain non-perm oops. |
304 void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) { | |
305 assert_locked_or_safepoint(CodeCache_lock); | |
306 debug_only(mark_scavenge_root_nmethods()); | |
307 | |
308 for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) { | |
309 debug_only(cur->clear_scavenge_root_marked()); | |
310 assert(cur->scavenge_root_not_marked(), ""); | |
311 assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); | |
312 | |
313 bool is_live = (!cur->is_zombie() && !cur->is_unloaded()); | |
314 #ifndef PRODUCT | |
315 if (TraceScavenge) { | |
316 cur->print_on(tty, is_live ? "scavenge root" : "dead scavenge root"); tty->cr(); | |
317 } | |
318 #endif //PRODUCT | |
1363
ed4f78aa9282
6940520: CodeCache::scavenge_root_nmethods_do must fix oop relocations
twisti
parents:
1202
diff
changeset
|
319 if (is_live) { |
989 | 320 // Perform cur->oops_do(f), maybe just once per nmethod. |
321 f->do_code_blob(cur); | |
1363
ed4f78aa9282
6940520: CodeCache::scavenge_root_nmethods_do must fix oop relocations
twisti
parents:
1202
diff
changeset
|
322 cur->fix_oop_relocations(); |
ed4f78aa9282
6940520: CodeCache::scavenge_root_nmethods_do must fix oop relocations
twisti
parents:
1202
diff
changeset
|
323 } |
989 | 324 } |
325 | |
326 // Check for stray marks. | |
327 debug_only(verify_perm_nmethods(NULL)); | |
328 } | |
329 | |
330 void CodeCache::add_scavenge_root_nmethod(nmethod* nm) { | |
331 assert_locked_or_safepoint(CodeCache_lock); | |
332 nm->set_on_scavenge_root_list(); | |
333 nm->set_scavenge_root_link(_scavenge_root_nmethods); | |
334 set_scavenge_root_nmethods(nm); | |
335 print_trace("add_scavenge_root", nm); | |
336 } | |
337 | |
338 void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) { | |
339 assert_locked_or_safepoint(CodeCache_lock); | |
340 print_trace("drop_scavenge_root", nm); | |
341 nmethod* last = NULL; | |
342 nmethod* cur = scavenge_root_nmethods(); | |
343 while (cur != NULL) { | |
344 nmethod* next = cur->scavenge_root_link(); | |
345 if (cur == nm) { | |
346 if (last != NULL) | |
347 last->set_scavenge_root_link(next); | |
348 else set_scavenge_root_nmethods(next); | |
349 nm->set_scavenge_root_link(NULL); | |
350 nm->clear_on_scavenge_root_list(); | |
351 return; | |
352 } | |
353 last = cur; | |
354 cur = next; | |
355 } | |
356 assert(false, "should have been on list"); | |
357 } | |
358 | |
359 void CodeCache::prune_scavenge_root_nmethods() { | |
360 assert_locked_or_safepoint(CodeCache_lock); | |
361 debug_only(mark_scavenge_root_nmethods()); | |
362 | |
363 nmethod* last = NULL; | |
364 nmethod* cur = scavenge_root_nmethods(); | |
365 while (cur != NULL) { | |
366 nmethod* next = cur->scavenge_root_link(); | |
367 debug_only(cur->clear_scavenge_root_marked()); | |
368 assert(cur->scavenge_root_not_marked(), ""); | |
369 assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); | |
370 | |
371 if (!cur->is_zombie() && !cur->is_unloaded() | |
372 && cur->detect_scavenge_root_oops()) { | |
373 // Keep it. Advance 'last' to prevent deletion. | |
374 last = cur; | |
375 } else { | |
376 // Prune it from the list, so we don't have to look at it any more. | |
377 print_trace("prune_scavenge_root", cur); | |
378 cur->set_scavenge_root_link(NULL); | |
379 cur->clear_on_scavenge_root_list(); | |
380 if (last != NULL) | |
381 last->set_scavenge_root_link(next); | |
382 else set_scavenge_root_nmethods(next); | |
383 } | |
384 cur = next; | |
385 } | |
386 | |
387 // Check for stray marks. | |
388 debug_only(verify_perm_nmethods(NULL)); | |
389 } | |
390 | |
391 #ifndef PRODUCT | |
392 void CodeCache::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) { | |
393 // While we are here, verify the integrity of the list. | |
394 mark_scavenge_root_nmethods(); | |
395 for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) { | |
396 assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); | |
397 cur->clear_scavenge_root_marked(); | |
398 } | |
399 verify_perm_nmethods(f); | |
400 } | |
401 | |
402 // Temporarily mark nmethods that are claimed to be on the non-perm list. | |
403 void CodeCache::mark_scavenge_root_nmethods() { | |
404 FOR_ALL_ALIVE_BLOBS(cb) { | |
405 if (cb->is_nmethod()) { | |
406 nmethod *nm = (nmethod*)cb; | |
407 assert(nm->scavenge_root_not_marked(), "clean state"); | |
408 if (nm->on_scavenge_root_list()) | |
409 nm->set_scavenge_root_marked(); | |
410 } | |
411 } | |
412 } | |
413 | |
414 // If the closure is given, run it on the unlisted nmethods. | |
415 // Also make sure that the effects of mark_scavenge_root_nmethods is gone. | |
416 void CodeCache::verify_perm_nmethods(CodeBlobClosure* f_or_null) { | |
417 FOR_ALL_ALIVE_BLOBS(cb) { | |
418 bool call_f = (f_or_null != NULL); | |
419 if (cb->is_nmethod()) { | |
420 nmethod *nm = (nmethod*)cb; | |
421 assert(nm->scavenge_root_not_marked(), "must be already processed"); | |
422 if (nm->on_scavenge_root_list()) | |
423 call_f = false; // don't show this one to the client | |
424 nm->verify_scavenge_root_oops(); | |
425 } else { | |
426 call_f = false; // not an nmethod | |
427 } | |
428 if (call_f) f_or_null->do_code_blob(cb); | |
429 } | |
430 } | |
431 #endif //PRODUCT | |
432 | |
1202 | 433 |
434 nmethod* CodeCache::find_and_remove_saved_code(methodOop m) { | |
435 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); | |
436 nmethod* saved = _saved_nmethods; | |
437 nmethod* prev = NULL; | |
438 while (saved != NULL) { | |
439 if (saved->is_in_use() && saved->method() == m) { | |
440 if (prev != NULL) { | |
441 prev->set_saved_nmethod_link(saved->saved_nmethod_link()); | |
442 } else { | |
443 _saved_nmethods = saved->saved_nmethod_link(); | |
444 } | |
445 assert(saved->is_speculatively_disconnected(), "shouldn't call for other nmethods"); | |
446 saved->set_speculatively_disconnected(false); | |
447 saved->set_saved_nmethod_link(NULL); | |
448 if (PrintMethodFlushing) { | |
1538
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
449 saved->print_on(tty, " ### nmethod is reconnected\n"); |
1202 | 450 } |
451 if (LogCompilation && (xtty != NULL)) { | |
452 ttyLocker ttyl; | |
453 xtty->begin_elem("nmethod_reconnected compile_id='%3d'", saved->compile_id()); | |
454 xtty->method(methodOop(m)); | |
455 xtty->stamp(); | |
456 xtty->end_elem(); | |
457 } | |
458 return saved; | |
459 } | |
460 prev = saved; | |
461 saved = saved->saved_nmethod_link(); | |
462 } | |
463 return NULL; | |
464 } | |
465 | |
466 void CodeCache::remove_saved_code(nmethod* nm) { | |
1538
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
467 // For conc swpr this will be called with CodeCache_lock taken by caller |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
468 assert_locked_or_safepoint(CodeCache_lock); |
1202 | 469 assert(nm->is_speculatively_disconnected(), "shouldn't call for other nmethods"); |
470 nmethod* saved = _saved_nmethods; | |
471 nmethod* prev = NULL; | |
472 while (saved != NULL) { | |
473 if (saved == nm) { | |
474 if (prev != NULL) { | |
475 prev->set_saved_nmethod_link(saved->saved_nmethod_link()); | |
476 } else { | |
477 _saved_nmethods = saved->saved_nmethod_link(); | |
478 } | |
479 if (LogCompilation && (xtty != NULL)) { | |
480 ttyLocker ttyl; | |
481 xtty->begin_elem("nmethod_removed compile_id='%3d'", nm->compile_id()); | |
482 xtty->stamp(); | |
483 xtty->end_elem(); | |
484 } | |
485 return; | |
486 } | |
487 prev = saved; | |
488 saved = saved->saved_nmethod_link(); | |
489 } | |
490 ShouldNotReachHere(); | |
491 } | |
492 | |
493 void CodeCache::speculatively_disconnect(nmethod* nm) { | |
494 assert_locked_or_safepoint(CodeCache_lock); | |
495 assert(nm->is_in_use() && !nm->is_speculatively_disconnected(), "should only disconnect live nmethods"); | |
496 nm->set_saved_nmethod_link(_saved_nmethods); | |
497 _saved_nmethods = nm; | |
498 if (PrintMethodFlushing) { | |
1538
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1363
diff
changeset
|
499 nm->print_on(tty, " ### nmethod is speculatively disconnected\n"); |
1202 | 500 } |
501 if (LogCompilation && (xtty != NULL)) { | |
502 ttyLocker ttyl; | |
503 xtty->begin_elem("nmethod_disconnected compile_id='%3d'", nm->compile_id()); | |
504 xtty->method(methodOop(nm->method())); | |
505 xtty->stamp(); | |
506 xtty->end_elem(); | |
507 } | |
508 nm->method()->clear_code(); | |
509 nm->set_speculatively_disconnected(true); | |
510 } | |
511 | |
512 | |
0 | 513 void CodeCache::gc_prologue() { |
989 | 514 assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_epilogue must be called"); |
0 | 515 } |
516 | |
517 | |
518 void CodeCache::gc_epilogue() { | |
519 assert_locked_or_safepoint(CodeCache_lock); | |
520 FOR_ALL_ALIVE_BLOBS(cb) { | |
521 if (cb->is_nmethod()) { | |
522 nmethod *nm = (nmethod*)cb; | |
523 assert(!nm->is_unloaded(), "Tautology"); | |
524 if (needs_cache_clean()) { | |
525 nm->cleanup_inline_caches(); | |
526 } | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
527 DEBUG_ONLY(nm->verify()); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
528 nm->fix_oop_relocations(); |
0 | 529 } |
530 } | |
531 set_needs_cache_clean(false); | |
989 | 532 prune_scavenge_root_nmethods(); |
533 assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_prologue must be called"); | |
0 | 534 } |
535 | |
536 | |
537 address CodeCache::first_address() { | |
538 assert_locked_or_safepoint(CodeCache_lock); | |
539 return (address)_heap->begin(); | |
540 } | |
541 | |
542 | |
543 address CodeCache::last_address() { | |
544 assert_locked_or_safepoint(CodeCache_lock); | |
545 return (address)_heap->end(); | |
546 } | |
547 | |
548 | |
549 void icache_init(); | |
550 | |
551 void CodeCache::initialize() { | |
552 assert(CodeCacheSegmentSize >= (uintx)CodeEntryAlignment, "CodeCacheSegmentSize must be large enough to align entry points"); | |
553 #ifdef COMPILER2 | |
554 assert(CodeCacheSegmentSize >= (uintx)OptoLoopAlignment, "CodeCacheSegmentSize must be large enough to align inner loops"); | |
555 #endif | |
556 assert(CodeCacheSegmentSize >= sizeof(jdouble), "CodeCacheSegmentSize must be large enough to align constants"); | |
557 // This was originally just a check of the alignment, causing failure, instead, round | |
558 // the code cache to the page size. In particular, Solaris is moving to a larger | |
559 // default page size. | |
560 CodeCacheExpansionSize = round_to(CodeCacheExpansionSize, os::vm_page_size()); | |
561 InitialCodeCacheSize = round_to(InitialCodeCacheSize, os::vm_page_size()); | |
562 ReservedCodeCacheSize = round_to(ReservedCodeCacheSize, os::vm_page_size()); | |
563 if (!_heap->reserve(ReservedCodeCacheSize, InitialCodeCacheSize, CodeCacheSegmentSize)) { | |
564 vm_exit_during_initialization("Could not reserve enough space for code cache"); | |
565 } | |
566 | |
567 MemoryService::add_code_heap_memory_pool(_heap); | |
568 | |
569 // Initialize ICache flush mechanism | |
570 // This service is needed for os::register_code_area | |
571 icache_init(); | |
572 | |
573 // Give OS a chance to register generated code area. | |
574 // This is used on Windows 64 bit platforms to register | |
575 // Structured Exception Handlers for our generated code. | |
576 os::register_code_area(_heap->low_boundary(), _heap->high_boundary()); | |
577 } | |
578 | |
579 | |
580 void codeCache_init() { | |
581 CodeCache::initialize(); | |
582 } | |
583 | |
584 //------------------------------------------------------------------------------------------------ | |
585 | |
586 int CodeCache::number_of_nmethods_with_dependencies() { | |
587 return _number_of_nmethods_with_dependencies; | |
588 } | |
589 | |
590 void CodeCache::clear_inline_caches() { | |
591 assert_locked_or_safepoint(CodeCache_lock); | |
592 FOR_ALL_ALIVE_NMETHODS(nm) { | |
593 nm->clear_inline_caches(); | |
594 } | |
595 } | |
596 | |
597 #ifndef PRODUCT | |
598 // used to keep track of how much time is spent in mark_for_deoptimization | |
599 static elapsedTimer dependentCheckTime; | |
600 static int dependentCheckCount = 0; | |
601 #endif // PRODUCT | |
602 | |
603 | |
604 int CodeCache::mark_for_deoptimization(DepChange& changes) { | |
605 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); | |
606 | |
607 #ifndef PRODUCT | |
608 dependentCheckTime.start(); | |
609 dependentCheckCount++; | |
610 #endif // PRODUCT | |
611 | |
612 int number_of_marked_CodeBlobs = 0; | |
613 | |
614 // search the hierarchy looking for nmethods which are affected by the loading of this class | |
615 | |
616 // then search the interfaces this class implements looking for nmethods | |
617 // which might be dependent of the fact that an interface only had one | |
618 // implementor. | |
619 | |
620 { No_Safepoint_Verifier nsv; | |
621 for (DepChange::ContextStream str(changes, nsv); str.next(); ) { | |
622 klassOop d = str.klass(); | |
623 number_of_marked_CodeBlobs += instanceKlass::cast(d)->mark_dependent_nmethods(changes); | |
624 } | |
625 } | |
626 | |
627 if (VerifyDependencies) { | |
628 // Turn off dependency tracing while actually testing deps. | |
629 NOT_PRODUCT( FlagSetting fs(TraceDependencies, false) ); | |
630 FOR_ALL_ALIVE_NMETHODS(nm) { | |
631 if (!nm->is_marked_for_deoptimization() && | |
632 nm->check_all_dependencies()) { | |
633 ResourceMark rm; | |
634 tty->print_cr("Should have been marked for deoptimization:"); | |
635 changes.print(); | |
636 nm->print(); | |
637 nm->print_dependencies(); | |
638 } | |
639 } | |
640 } | |
641 | |
642 #ifndef PRODUCT | |
643 dependentCheckTime.stop(); | |
644 #endif // PRODUCT | |
645 | |
646 return number_of_marked_CodeBlobs; | |
647 } | |
648 | |
649 | |
650 #ifdef HOTSWAP | |
651 int CodeCache::mark_for_evol_deoptimization(instanceKlassHandle dependee) { | |
652 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); | |
653 int number_of_marked_CodeBlobs = 0; | |
654 | |
655 // Deoptimize all methods of the evolving class itself | |
656 objArrayOop old_methods = dependee->methods(); | |
657 for (int i = 0; i < old_methods->length(); i++) { | |
658 ResourceMark rm; | |
659 methodOop old_method = (methodOop) old_methods->obj_at(i); | |
660 nmethod *nm = old_method->code(); | |
661 if (nm != NULL) { | |
662 nm->mark_for_deoptimization(); | |
663 number_of_marked_CodeBlobs++; | |
664 } | |
665 } | |
666 | |
667 FOR_ALL_ALIVE_NMETHODS(nm) { | |
668 if (nm->is_marked_for_deoptimization()) { | |
669 // ...Already marked in the previous pass; don't count it again. | |
670 } else if (nm->is_evol_dependent_on(dependee())) { | |
671 ResourceMark rm; | |
672 nm->mark_for_deoptimization(); | |
673 number_of_marked_CodeBlobs++; | |
674 } else { | |
675 // flush caches in case they refer to a redefined methodOop | |
676 nm->clear_inline_caches(); | |
677 } | |
678 } | |
679 | |
680 return number_of_marked_CodeBlobs; | |
681 } | |
682 #endif // HOTSWAP | |
683 | |
684 | |
685 // Deoptimize all methods | |
686 void CodeCache::mark_all_nmethods_for_deoptimization() { | |
687 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); | |
688 FOR_ALL_ALIVE_NMETHODS(nm) { | |
689 nm->mark_for_deoptimization(); | |
690 } | |
691 } | |
692 | |
693 | |
694 int CodeCache::mark_for_deoptimization(methodOop dependee) { | |
695 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); | |
696 int number_of_marked_CodeBlobs = 0; | |
697 | |
698 FOR_ALL_ALIVE_NMETHODS(nm) { | |
699 if (nm->is_dependent_on_method(dependee)) { | |
700 ResourceMark rm; | |
701 nm->mark_for_deoptimization(); | |
702 number_of_marked_CodeBlobs++; | |
703 } | |
704 } | |
705 | |
706 return number_of_marked_CodeBlobs; | |
707 } | |
708 | |
709 void CodeCache::make_marked_nmethods_zombies() { | |
710 assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); | |
711 FOR_ALL_ALIVE_NMETHODS(nm) { | |
712 if (nm->is_marked_for_deoptimization()) { | |
713 | |
714 // If the nmethod has already been made non-entrant and it can be converted | |
715 // then zombie it now. Otherwise make it non-entrant and it will eventually | |
716 // be zombied when it is no longer seen on the stack. Note that the nmethod | |
717 // might be "entrant" and not on the stack and so could be zombied immediately | |
718 // but we can't tell because we don't track it on stack until it becomes | |
719 // non-entrant. | |
720 | |
721 if (nm->is_not_entrant() && nm->can_not_entrant_be_converted()) { | |
722 nm->make_zombie(); | |
723 } else { | |
724 nm->make_not_entrant(); | |
725 } | |
726 } | |
727 } | |
728 } | |
729 | |
730 void CodeCache::make_marked_nmethods_not_entrant() { | |
731 assert_locked_or_safepoint(CodeCache_lock); | |
732 FOR_ALL_ALIVE_NMETHODS(nm) { | |
733 if (nm->is_marked_for_deoptimization()) { | |
734 nm->make_not_entrant(); | |
735 } | |
736 } | |
737 } | |
738 | |
739 void CodeCache::verify() { | |
740 _heap->verify(); | |
741 FOR_ALL_ALIVE_BLOBS(p) { | |
742 p->verify(); | |
743 } | |
744 } | |
745 | |
746 //------------------------------------------------------------------------------------------------ | |
747 // Non-product version | |
748 | |
749 #ifndef PRODUCT | |
750 | |
751 void CodeCache::verify_if_often() { | |
752 if (VerifyCodeCacheOften) { | |
753 _heap->verify(); | |
754 } | |
755 } | |
756 | |
989 | 757 void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) { |
758 if (PrintCodeCache2) { // Need to add a new flag | |
759 ResourceMark rm; | |
760 if (size == 0) size = cb->size(); | |
761 tty->print_cr("CodeCache %s: addr: " INTPTR_FORMAT ", size: 0x%x", event, cb, size); | |
762 } | |
763 } | |
764 | |
0 | 765 void CodeCache::print_internals() { |
766 int nmethodCount = 0; | |
767 int runtimeStubCount = 0; | |
768 int adapterCount = 0; | |
769 int deoptimizationStubCount = 0; | |
770 int uncommonTrapStubCount = 0; | |
771 int bufferBlobCount = 0; | |
772 int total = 0; | |
773 int nmethodAlive = 0; | |
774 int nmethodNotEntrant = 0; | |
775 int nmethodZombie = 0; | |
776 int nmethodUnloaded = 0; | |
777 int nmethodJava = 0; | |
778 int nmethodNative = 0; | |
779 int maxCodeSize = 0; | |
780 ResourceMark rm; | |
781 | |
782 CodeBlob *cb; | |
783 for (cb = first(); cb != NULL; cb = next(cb)) { | |
784 total++; | |
785 if (cb->is_nmethod()) { | |
786 nmethod* nm = (nmethod*)cb; | |
787 | |
788 if (Verbose && nm->method() != NULL) { | |
789 ResourceMark rm; | |
790 char *method_name = nm->method()->name_and_sig_as_C_string(); | |
791 tty->print("%s", method_name); | |
792 if(nm->is_alive()) { tty->print_cr(" alive"); } | |
793 if(nm->is_not_entrant()) { tty->print_cr(" not-entrant"); } | |
794 if(nm->is_zombie()) { tty->print_cr(" zombie"); } | |
795 } | |
796 | |
797 nmethodCount++; | |
798 | |
799 if(nm->is_alive()) { nmethodAlive++; } | |
800 if(nm->is_not_entrant()) { nmethodNotEntrant++; } | |
801 if(nm->is_zombie()) { nmethodZombie++; } | |
802 if(nm->is_unloaded()) { nmethodUnloaded++; } | |
803 if(nm->is_native_method()) { nmethodNative++; } | |
804 | |
805 if(nm->method() != NULL && nm->is_java_method()) { | |
806 nmethodJava++; | |
807 if(nm->code_size() > maxCodeSize) { | |
808 maxCodeSize = nm->code_size(); | |
809 } | |
810 } | |
811 } else if (cb->is_runtime_stub()) { | |
812 runtimeStubCount++; | |
813 } else if (cb->is_deoptimization_stub()) { | |
814 deoptimizationStubCount++; | |
815 } else if (cb->is_uncommon_trap_stub()) { | |
816 uncommonTrapStubCount++; | |
817 } else if (cb->is_adapter_blob()) { | |
818 adapterCount++; | |
819 } else if (cb->is_buffer_blob()) { | |
820 bufferBlobCount++; | |
821 } | |
822 } | |
823 | |
824 int bucketSize = 512; | |
825 int bucketLimit = maxCodeSize / bucketSize + 1; | |
826 int *buckets = NEW_C_HEAP_ARRAY(int, bucketLimit); | |
827 memset(buckets,0,sizeof(int) * bucketLimit); | |
828 | |
829 for (cb = first(); cb != NULL; cb = next(cb)) { | |
830 if (cb->is_nmethod()) { | |
831 nmethod* nm = (nmethod*)cb; | |
832 if(nm->is_java_method()) { | |
833 buckets[nm->code_size() / bucketSize]++; | |
834 } | |
835 } | |
836 } | |
837 tty->print_cr("Code Cache Entries (total of %d)",total); | |
838 tty->print_cr("-------------------------------------------------"); | |
839 tty->print_cr("nmethods: %d",nmethodCount); | |
840 tty->print_cr("\talive: %d",nmethodAlive); | |
841 tty->print_cr("\tnot_entrant: %d",nmethodNotEntrant); | |
842 tty->print_cr("\tzombie: %d",nmethodZombie); | |
843 tty->print_cr("\tunloaded: %d",nmethodUnloaded); | |
844 tty->print_cr("\tjava: %d",nmethodJava); | |
845 tty->print_cr("\tnative: %d",nmethodNative); | |
846 tty->print_cr("runtime_stubs: %d",runtimeStubCount); | |
847 tty->print_cr("adapters: %d",adapterCount); | |
848 tty->print_cr("buffer blobs: %d",bufferBlobCount); | |
849 tty->print_cr("deoptimization_stubs: %d",deoptimizationStubCount); | |
850 tty->print_cr("uncommon_traps: %d",uncommonTrapStubCount); | |
851 tty->print_cr("\nnmethod size distribution (non-zombie java)"); | |
852 tty->print_cr("-------------------------------------------------"); | |
853 | |
854 for(int i=0; i<bucketLimit; i++) { | |
855 if(buckets[i] != 0) { | |
856 tty->print("%d - %d bytes",i*bucketSize,(i+1)*bucketSize); | |
857 tty->fill_to(40); | |
858 tty->print_cr("%d",buckets[i]); | |
859 } | |
860 } | |
861 | |
862 FREE_C_HEAP_ARRAY(int, buckets); | |
863 } | |
864 | |
865 void CodeCache::print() { | |
866 CodeBlob_sizes live; | |
867 CodeBlob_sizes dead; | |
868 | |
869 FOR_ALL_BLOBS(p) { | |
870 if (!p->is_alive()) { | |
871 dead.add(p); | |
872 } else { | |
873 live.add(p); | |
874 } | |
875 } | |
876 | |
877 tty->print_cr("CodeCache:"); | |
878 | |
879 tty->print_cr("nmethod dependency checking time %f", dependentCheckTime.seconds(), | |
880 dependentCheckTime.seconds() / dependentCheckCount); | |
881 | |
882 if (!live.is_empty()) { | |
883 live.print("live"); | |
884 } | |
885 if (!dead.is_empty()) { | |
886 dead.print("dead"); | |
887 } | |
888 | |
889 | |
890 if (Verbose) { | |
891 // print the oop_map usage | |
892 int code_size = 0; | |
893 int number_of_blobs = 0; | |
894 int number_of_oop_maps = 0; | |
895 int map_size = 0; | |
896 FOR_ALL_BLOBS(p) { | |
897 if (p->is_alive()) { | |
898 number_of_blobs++; | |
899 code_size += p->instructions_size(); | |
900 OopMapSet* set = p->oop_maps(); | |
901 if (set != NULL) { | |
902 number_of_oop_maps += set->size(); | |
903 map_size += set->heap_size(); | |
904 } | |
905 } | |
906 } | |
907 tty->print_cr("OopMaps"); | |
908 tty->print_cr(" #blobs = %d", number_of_blobs); | |
909 tty->print_cr(" code size = %d", code_size); | |
910 tty->print_cr(" #oop_maps = %d", number_of_oop_maps); | |
911 tty->print_cr(" map size = %d", map_size); | |
912 } | |
913 | |
914 } | |
915 | |
916 #endif // PRODUCT |