Mercurial > hg > truffle
annotate src/share/vm/code/nmethod.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 | d2ede61b7a12 |
children | 71faaa8e3ccc |
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/_nmethod.cpp.incl" | |
27 | |
28 #ifdef DTRACE_ENABLED | |
29 | |
30 // Only bother with this argument setup if dtrace is available | |
31 | |
32 HS_DTRACE_PROBE_DECL8(hotspot, compiled__method__load, | |
33 const char*, int, const char*, int, const char*, int, void*, size_t); | |
34 | |
35 HS_DTRACE_PROBE_DECL6(hotspot, compiled__method__unload, | |
36 char*, int, char*, int, char*, int); | |
37 | |
38 #define DTRACE_METHOD_UNLOAD_PROBE(method) \ | |
39 { \ | |
40 methodOop m = (method); \ | |
41 if (m != NULL) { \ | |
42 symbolOop klass_name = m->klass_name(); \ | |
43 symbolOop name = m->name(); \ | |
44 symbolOop signature = m->signature(); \ | |
45 HS_DTRACE_PROBE6(hotspot, compiled__method__unload, \ | |
46 klass_name->bytes(), klass_name->utf8_length(), \ | |
47 name->bytes(), name->utf8_length(), \ | |
48 signature->bytes(), signature->utf8_length()); \ | |
49 } \ | |
50 } | |
51 | |
52 #else // ndef DTRACE_ENABLED | |
53 | |
54 #define DTRACE_METHOD_UNLOAD_PROBE(method) | |
55 | |
56 #endif | |
57 | |
58 bool nmethod::is_compiled_by_c1() const { | |
1155
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
59 if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing |
0 | 60 if (is_native_method()) return false; |
61 return compiler()->is_c1(); | |
62 } | |
63 bool nmethod::is_compiled_by_c2() const { | |
1155
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
64 if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing |
0 | 65 if (is_native_method()) return false; |
66 return compiler()->is_c2(); | |
67 } | |
1692 | 68 bool nmethod::is_compiled_by_shark() const { |
69 if (is_native_method()) return false; | |
70 assert(compiler() != NULL, "must be"); | |
71 return compiler()->is_shark(); | |
72 } | |
0 | 73 |
74 | |
75 | |
76 //--------------------------------------------------------------------------------- | |
77 // NMethod statistics | |
78 // They are printed under various flags, including: | |
79 // PrintC1Statistics, PrintOptoStatistics, LogVMOutput, and LogCompilation. | |
80 // (In the latter two cases, they like other stats are printed to the log only.) | |
81 | |
82 #ifndef PRODUCT | |
83 // These variables are put into one block to reduce relocations | |
84 // and make it simpler to print from the debugger. | |
85 static | |
86 struct nmethod_stats_struct { | |
87 int nmethod_count; | |
88 int total_size; | |
89 int relocation_size; | |
90 int code_size; | |
91 int stub_size; | |
92 int consts_size; | |
93 int scopes_data_size; | |
94 int scopes_pcs_size; | |
95 int dependencies_size; | |
96 int handler_table_size; | |
97 int nul_chk_table_size; | |
98 int oops_size; | |
99 | |
100 void note_nmethod(nmethod* nm) { | |
101 nmethod_count += 1; | |
102 total_size += nm->size(); | |
103 relocation_size += nm->relocation_size(); | |
104 code_size += nm->code_size(); | |
105 stub_size += nm->stub_size(); | |
106 consts_size += nm->consts_size(); | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
107 oops_size += nm->oops_size(); |
0 | 108 scopes_data_size += nm->scopes_data_size(); |
109 scopes_pcs_size += nm->scopes_pcs_size(); | |
110 dependencies_size += nm->dependencies_size(); | |
111 handler_table_size += nm->handler_table_size(); | |
112 nul_chk_table_size += nm->nul_chk_table_size(); | |
113 } | |
114 void print_nmethod_stats() { | |
115 if (nmethod_count == 0) return; | |
116 tty->print_cr("Statistics for %d bytecoded nmethods:", nmethod_count); | |
117 if (total_size != 0) tty->print_cr(" total in heap = %d", total_size); | |
118 if (relocation_size != 0) tty->print_cr(" relocation = %d", relocation_size); | |
119 if (code_size != 0) tty->print_cr(" main code = %d", code_size); | |
120 if (stub_size != 0) tty->print_cr(" stub code = %d", stub_size); | |
121 if (consts_size != 0) tty->print_cr(" constants = %d", consts_size); | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
122 if (oops_size != 0) tty->print_cr(" oops = %d", oops_size); |
0 | 123 if (scopes_data_size != 0) tty->print_cr(" scopes data = %d", scopes_data_size); |
124 if (scopes_pcs_size != 0) tty->print_cr(" scopes pcs = %d", scopes_pcs_size); | |
125 if (dependencies_size != 0) tty->print_cr(" dependencies = %d", dependencies_size); | |
126 if (handler_table_size != 0) tty->print_cr(" handler table = %d", handler_table_size); | |
127 if (nul_chk_table_size != 0) tty->print_cr(" nul chk table = %d", nul_chk_table_size); | |
128 } | |
129 | |
130 int native_nmethod_count; | |
131 int native_total_size; | |
132 int native_relocation_size; | |
133 int native_code_size; | |
134 int native_oops_size; | |
135 void note_native_nmethod(nmethod* nm) { | |
136 native_nmethod_count += 1; | |
137 native_total_size += nm->size(); | |
138 native_relocation_size += nm->relocation_size(); | |
139 native_code_size += nm->code_size(); | |
140 native_oops_size += nm->oops_size(); | |
141 } | |
142 void print_native_nmethod_stats() { | |
143 if (native_nmethod_count == 0) return; | |
144 tty->print_cr("Statistics for %d native nmethods:", native_nmethod_count); | |
145 if (native_total_size != 0) tty->print_cr(" N. total size = %d", native_total_size); | |
146 if (native_relocation_size != 0) tty->print_cr(" N. relocation = %d", native_relocation_size); | |
147 if (native_code_size != 0) tty->print_cr(" N. main code = %d", native_code_size); | |
148 if (native_oops_size != 0) tty->print_cr(" N. oops = %d", native_oops_size); | |
149 } | |
150 | |
151 int pc_desc_resets; // number of resets (= number of caches) | |
152 int pc_desc_queries; // queries to nmethod::find_pc_desc | |
153 int pc_desc_approx; // number of those which have approximate true | |
154 int pc_desc_repeats; // number of _last_pc_desc hits | |
155 int pc_desc_hits; // number of LRU cache hits | |
156 int pc_desc_tests; // total number of PcDesc examinations | |
157 int pc_desc_searches; // total number of quasi-binary search steps | |
158 int pc_desc_adds; // number of LUR cache insertions | |
159 | |
160 void print_pc_stats() { | |
161 tty->print_cr("PcDesc Statistics: %d queries, %.2f comparisons per query", | |
162 pc_desc_queries, | |
163 (double)(pc_desc_tests + pc_desc_searches) | |
164 / pc_desc_queries); | |
165 tty->print_cr(" caches=%d queries=%d/%d, hits=%d+%d, tests=%d+%d, adds=%d", | |
166 pc_desc_resets, | |
167 pc_desc_queries, pc_desc_approx, | |
168 pc_desc_repeats, pc_desc_hits, | |
169 pc_desc_tests, pc_desc_searches, pc_desc_adds); | |
170 } | |
171 } nmethod_stats; | |
172 #endif //PRODUCT | |
173 | |
174 //--------------------------------------------------------------------------------- | |
175 | |
176 | |
177 // The _unwind_handler is a special marker address, which says that | |
178 // for given exception oop and address, the frame should be removed | |
179 // as the tuple cannot be caught in the nmethod | |
180 address ExceptionCache::_unwind_handler = (address) -1; | |
181 | |
182 | |
183 ExceptionCache::ExceptionCache(Handle exception, address pc, address handler) { | |
184 assert(pc != NULL, "Must be non null"); | |
185 assert(exception.not_null(), "Must be non null"); | |
186 assert(handler != NULL, "Must be non null"); | |
187 | |
188 _count = 0; | |
189 _exception_type = exception->klass(); | |
190 _next = NULL; | |
191 | |
192 add_address_and_handler(pc,handler); | |
193 } | |
194 | |
195 | |
196 address ExceptionCache::match(Handle exception, address pc) { | |
197 assert(pc != NULL,"Must be non null"); | |
198 assert(exception.not_null(),"Must be non null"); | |
199 if (exception->klass() == exception_type()) { | |
200 return (test_address(pc)); | |
201 } | |
202 | |
203 return NULL; | |
204 } | |
205 | |
206 | |
207 bool ExceptionCache::match_exception_with_space(Handle exception) { | |
208 assert(exception.not_null(),"Must be non null"); | |
209 if (exception->klass() == exception_type() && count() < cache_size) { | |
210 return true; | |
211 } | |
212 return false; | |
213 } | |
214 | |
215 | |
216 address ExceptionCache::test_address(address addr) { | |
217 for (int i=0; i<count(); i++) { | |
218 if (pc_at(i) == addr) { | |
219 return handler_at(i); | |
220 } | |
221 } | |
222 return NULL; | |
223 } | |
224 | |
225 | |
226 bool ExceptionCache::add_address_and_handler(address addr, address handler) { | |
227 if (test_address(addr) == handler) return true; | |
228 if (count() < cache_size) { | |
229 set_pc_at(count(),addr); | |
230 set_handler_at(count(), handler); | |
231 increment_count(); | |
232 return true; | |
233 } | |
234 return false; | |
235 } | |
236 | |
237 | |
238 // private method for handling exception cache | |
239 // These methods are private, and used to manipulate the exception cache | |
240 // directly. | |
241 ExceptionCache* nmethod::exception_cache_entry_for_exception(Handle exception) { | |
242 ExceptionCache* ec = exception_cache(); | |
243 while (ec != NULL) { | |
244 if (ec->match_exception_with_space(exception)) { | |
245 return ec; | |
246 } | |
247 ec = ec->next(); | |
248 } | |
249 return NULL; | |
250 } | |
251 | |
252 | |
253 //----------------------------------------------------------------------------- | |
254 | |
255 | |
256 // Helper used by both find_pc_desc methods. | |
257 static inline bool match_desc(PcDesc* pc, int pc_offset, bool approximate) { | |
258 NOT_PRODUCT(++nmethod_stats.pc_desc_tests); | |
259 if (!approximate) | |
260 return pc->pc_offset() == pc_offset; | |
261 else | |
262 return (pc-1)->pc_offset() < pc_offset && pc_offset <= pc->pc_offset(); | |
263 } | |
264 | |
265 void PcDescCache::reset_to(PcDesc* initial_pc_desc) { | |
266 if (initial_pc_desc == NULL) { | |
267 _last_pc_desc = NULL; // native method | |
268 return; | |
269 } | |
270 NOT_PRODUCT(++nmethod_stats.pc_desc_resets); | |
271 // reset the cache by filling it with benign (non-null) values | |
272 assert(initial_pc_desc->pc_offset() < 0, "must be sentinel"); | |
273 _last_pc_desc = initial_pc_desc + 1; // first valid one is after sentinel | |
274 for (int i = 0; i < cache_size; i++) | |
275 _pc_descs[i] = initial_pc_desc; | |
276 } | |
277 | |
278 PcDesc* PcDescCache::find_pc_desc(int pc_offset, bool approximate) { | |
279 NOT_PRODUCT(++nmethod_stats.pc_desc_queries); | |
280 NOT_PRODUCT(if (approximate) ++nmethod_stats.pc_desc_approx); | |
281 | |
282 // In order to prevent race conditions do not load cache elements | |
283 // repeatedly, but use a local copy: | |
284 PcDesc* res; | |
285 | |
286 // Step one: Check the most recently returned value. | |
287 res = _last_pc_desc; | |
288 if (res == NULL) return NULL; // native method; no PcDescs at all | |
289 if (match_desc(res, pc_offset, approximate)) { | |
290 NOT_PRODUCT(++nmethod_stats.pc_desc_repeats); | |
291 return res; | |
292 } | |
293 | |
294 // Step two: Check the LRU cache. | |
295 for (int i = 0; i < cache_size; i++) { | |
296 res = _pc_descs[i]; | |
297 if (res->pc_offset() < 0) break; // optimization: skip empty cache | |
298 if (match_desc(res, pc_offset, approximate)) { | |
299 NOT_PRODUCT(++nmethod_stats.pc_desc_hits); | |
300 _last_pc_desc = res; // record this cache hit in case of repeat | |
301 return res; | |
302 } | |
303 } | |
304 | |
305 // Report failure. | |
306 return NULL; | |
307 } | |
308 | |
309 void PcDescCache::add_pc_desc(PcDesc* pc_desc) { | |
310 NOT_PRODUCT(++nmethod_stats.pc_desc_adds); | |
311 // Update the LRU cache by shifting pc_desc forward: | |
312 for (int i = 0; i < cache_size; i++) { | |
313 PcDesc* next = _pc_descs[i]; | |
314 _pc_descs[i] = pc_desc; | |
315 pc_desc = next; | |
316 } | |
317 // Note: Do not update _last_pc_desc. It fronts for the LRU cache. | |
318 } | |
319 | |
320 // adjust pcs_size so that it is a multiple of both oopSize and | |
321 // sizeof(PcDesc) (assumes that if sizeof(PcDesc) is not a multiple | |
322 // of oopSize, then 2*sizeof(PcDesc) is) | |
323 static int adjust_pcs_size(int pcs_size) { | |
324 int nsize = round_to(pcs_size, oopSize); | |
325 if ((nsize % sizeof(PcDesc)) != 0) { | |
326 nsize = pcs_size + sizeof(PcDesc); | |
327 } | |
328 assert((nsize % oopSize) == 0, "correct alignment"); | |
329 return nsize; | |
330 } | |
331 | |
332 //----------------------------------------------------------------------------- | |
333 | |
334 | |
335 void nmethod::add_exception_cache_entry(ExceptionCache* new_entry) { | |
336 assert(ExceptionCache_lock->owned_by_self(),"Must hold the ExceptionCache_lock"); | |
337 assert(new_entry != NULL,"Must be non null"); | |
338 assert(new_entry->next() == NULL, "Must be null"); | |
339 | |
340 if (exception_cache() != NULL) { | |
341 new_entry->set_next(exception_cache()); | |
342 } | |
343 set_exception_cache(new_entry); | |
344 } | |
345 | |
346 void nmethod::remove_from_exception_cache(ExceptionCache* ec) { | |
347 ExceptionCache* prev = NULL; | |
348 ExceptionCache* curr = exception_cache(); | |
349 assert(curr != NULL, "nothing to remove"); | |
350 // find the previous and next entry of ec | |
351 while (curr != ec) { | |
352 prev = curr; | |
353 curr = curr->next(); | |
354 assert(curr != NULL, "ExceptionCache not found"); | |
355 } | |
356 // now: curr == ec | |
357 ExceptionCache* next = curr->next(); | |
358 if (prev == NULL) { | |
359 set_exception_cache(next); | |
360 } else { | |
361 prev->set_next(next); | |
362 } | |
363 delete curr; | |
364 } | |
365 | |
366 | |
367 // public method for accessing the exception cache | |
368 // These are the public access methods. | |
369 address nmethod::handler_for_exception_and_pc(Handle exception, address pc) { | |
370 // We never grab a lock to read the exception cache, so we may | |
371 // have false negatives. This is okay, as it can only happen during | |
372 // the first few exception lookups for a given nmethod. | |
373 ExceptionCache* ec = exception_cache(); | |
374 while (ec != NULL) { | |
375 address ret_val; | |
376 if ((ret_val = ec->match(exception,pc)) != NULL) { | |
377 return ret_val; | |
378 } | |
379 ec = ec->next(); | |
380 } | |
381 return NULL; | |
382 } | |
383 | |
384 | |
385 void nmethod::add_handler_for_exception_and_pc(Handle exception, address pc, address handler) { | |
386 // There are potential race conditions during exception cache updates, so we | |
387 // must own the ExceptionCache_lock before doing ANY modifications. Because | |
605 | 388 // we don't lock during reads, it is possible to have several threads attempt |
0 | 389 // to update the cache with the same data. We need to check for already inserted |
390 // copies of the current data before adding it. | |
391 | |
392 MutexLocker ml(ExceptionCache_lock); | |
393 ExceptionCache* target_entry = exception_cache_entry_for_exception(exception); | |
394 | |
395 if (target_entry == NULL || !target_entry->add_address_and_handler(pc,handler)) { | |
396 target_entry = new ExceptionCache(exception,pc,handler); | |
397 add_exception_cache_entry(target_entry); | |
398 } | |
399 } | |
400 | |
401 | |
402 //-------------end of code for ExceptionCache-------------- | |
403 | |
404 | |
405 int nmethod::total_size() const { | |
406 return | |
407 code_size() + | |
408 stub_size() + | |
409 consts_size() + | |
410 scopes_data_size() + | |
411 scopes_pcs_size() + | |
412 handler_table_size() + | |
413 nul_chk_table_size(); | |
414 } | |
415 | |
416 const char* nmethod::compile_kind() const { | |
417 if (is_osr_method()) return "osr"; | |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
418 if (method() != NULL && is_native_method()) return "c2n"; |
0 | 419 return NULL; |
420 } | |
421 | |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
422 // Fill in default values for various flag fields |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
423 void nmethod::init_defaults() { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
424 _state = alive; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
425 _marked_for_reclamation = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
426 _has_flushed_dependencies = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
427 _speculatively_disconnected = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
428 _has_unsafe_access = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
429 _has_method_handle_invokes = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
430 _marked_for_deoptimization = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
431 _lock_count = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
432 _stack_traversal_mark = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
433 _unload_reported = false; // jvmti state |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
434 |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
435 NOT_PRODUCT(_has_debug_info = false); |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
436 _oops_do_mark_link = NULL; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
437 _jmethod_id = NULL; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
438 _osr_link = NULL; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
439 _scavenge_root_link = NULL; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
440 _scavenge_root_state = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
441 _saved_nmethod_link = NULL; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
442 _compiler = NULL; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
443 |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
444 #ifdef HAVE_DTRACE_H |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
445 _trap_offset = 0; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
446 #endif // def HAVE_DTRACE_H |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
447 } |
0 | 448 |
449 | |
450 nmethod* nmethod::new_native_nmethod(methodHandle method, | |
451 CodeBuffer *code_buffer, | |
452 int vep_offset, | |
453 int frame_complete, | |
454 int frame_size, | |
455 ByteSize basic_lock_owner_sp_offset, | |
456 ByteSize basic_lock_sp_offset, | |
457 OopMapSet* oop_maps) { | |
458 // create nmethod | |
459 nmethod* nm = NULL; | |
460 { | |
461 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); | |
462 int native_nmethod_size = allocation_size(code_buffer, sizeof(nmethod)); | |
463 CodeOffsets offsets; | |
464 offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); | |
465 offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); | |
466 nm = new (native_nmethod_size) | |
467 nmethod(method(), native_nmethod_size, &offsets, | |
468 code_buffer, frame_size, | |
469 basic_lock_owner_sp_offset, basic_lock_sp_offset, | |
470 oop_maps); | |
471 NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_native_nmethod(nm)); | |
472 if (PrintAssembly && nm != NULL) | |
473 Disassembler::decode(nm); | |
474 } | |
475 // verify nmethod | |
476 debug_only(if (nm) nm->verify();) // might block | |
477 | |
478 if (nm != NULL) { | |
479 nm->log_new_nmethod(); | |
480 } | |
481 | |
482 return nm; | |
483 } | |
484 | |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
485 #ifdef HAVE_DTRACE_H |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
486 nmethod* nmethod::new_dtrace_nmethod(methodHandle method, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
487 CodeBuffer *code_buffer, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
488 int vep_offset, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
489 int trap_offset, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
490 int frame_complete, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
491 int frame_size) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
492 // create nmethod |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
493 nmethod* nm = NULL; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
494 { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
495 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
496 int nmethod_size = allocation_size(code_buffer, sizeof(nmethod)); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
497 CodeOffsets offsets; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
498 offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
499 offsets.set_value(CodeOffsets::Dtrace_trap, trap_offset); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
500 offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
501 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
502 nm = new (nmethod_size) nmethod(method(), nmethod_size, &offsets, code_buffer, frame_size); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
503 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
504 NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_nmethod(nm)); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
505 if (PrintAssembly && nm != NULL) |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
506 Disassembler::decode(nm); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
507 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
508 // verify nmethod |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
509 debug_only(if (nm) nm->verify();) // might block |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
510 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
511 if (nm != NULL) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
512 nm->log_new_nmethod(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
513 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
514 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
515 return nm; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
516 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
517 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
518 #endif // def HAVE_DTRACE_H |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
519 |
0 | 520 nmethod* nmethod::new_nmethod(methodHandle method, |
521 int compile_id, | |
522 int entry_bci, | |
523 CodeOffsets* offsets, | |
524 int orig_pc_offset, | |
525 DebugInformationRecorder* debug_info, | |
526 Dependencies* dependencies, | |
527 CodeBuffer* code_buffer, int frame_size, | |
528 OopMapSet* oop_maps, | |
529 ExceptionHandlerTable* handler_table, | |
530 ImplicitExceptionTable* nul_chk_table, | |
531 AbstractCompiler* compiler, | |
532 int comp_level | |
533 ) | |
534 { | |
535 assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR"); | |
536 // create nmethod | |
537 nmethod* nm = NULL; | |
538 { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); | |
539 int nmethod_size = | |
540 allocation_size(code_buffer, sizeof(nmethod)) | |
541 + adjust_pcs_size(debug_info->pcs_size()) | |
542 + round_to(dependencies->size_in_bytes() , oopSize) | |
543 + round_to(handler_table->size_in_bytes(), oopSize) | |
544 + round_to(nul_chk_table->size_in_bytes(), oopSize) | |
545 + round_to(debug_info->data_size() , oopSize); | |
546 nm = new (nmethod_size) | |
547 nmethod(method(), nmethod_size, compile_id, entry_bci, offsets, | |
548 orig_pc_offset, debug_info, dependencies, code_buffer, frame_size, | |
549 oop_maps, | |
550 handler_table, | |
551 nul_chk_table, | |
552 compiler, | |
553 comp_level); | |
554 if (nm != NULL) { | |
555 // To make dependency checking during class loading fast, record | |
556 // the nmethod dependencies in the classes it is dependent on. | |
557 // This allows the dependency checking code to simply walk the | |
558 // class hierarchy above the loaded class, checking only nmethods | |
559 // which are dependent on those classes. The slow way is to | |
560 // check every nmethod for dependencies which makes it linear in | |
561 // the number of methods compiled. For applications with a lot | |
562 // classes the slow way is too slow. | |
563 for (Dependencies::DepStream deps(nm); deps.next(); ) { | |
564 klassOop klass = deps.context_type(); | |
565 if (klass == NULL) continue; // ignore things like evol_method | |
566 | |
567 // record this nmethod as dependent on this klass | |
568 instanceKlass::cast(klass)->add_dependent_nmethod(nm); | |
569 } | |
570 } | |
571 NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_nmethod(nm)); | |
572 if (PrintAssembly && nm != NULL) | |
573 Disassembler::decode(nm); | |
574 } | |
575 | |
576 // verify nmethod | |
577 debug_only(if (nm) nm->verify();) // might block | |
578 | |
579 if (nm != NULL) { | |
580 nm->log_new_nmethod(); | |
581 } | |
582 | |
583 // done | |
584 return nm; | |
585 } | |
586 | |
587 | |
588 // For native wrappers | |
589 nmethod::nmethod( | |
590 methodOop method, | |
591 int nmethod_size, | |
592 CodeOffsets* offsets, | |
593 CodeBuffer* code_buffer, | |
594 int frame_size, | |
595 ByteSize basic_lock_owner_sp_offset, | |
596 ByteSize basic_lock_sp_offset, | |
597 OopMapSet* oop_maps ) | |
598 : CodeBlob("native nmethod", code_buffer, sizeof(nmethod), | |
599 nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps), | |
600 _compiled_synchronized_native_basic_lock_owner_sp_offset(basic_lock_owner_sp_offset), | |
601 _compiled_synchronized_native_basic_lock_sp_offset(basic_lock_sp_offset) | |
602 { | |
603 { | |
604 debug_only(No_Safepoint_Verifier nsv;) | |
605 assert_locked_or_safepoint(CodeCache_lock); | |
606 | |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
607 init_defaults(); |
0 | 608 _method = method; |
609 _entry_bci = InvocationEntryBci; | |
610 // We have no exception handler or deopt handler make the | |
611 // values something that will never match a pc like the nmethod vtable entry | |
612 _exception_offset = 0; | |
613 _deoptimize_offset = 0; | |
1204 | 614 _deoptimize_mh_offset = 0; |
0 | 615 _orig_pc_offset = 0; |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
616 |
0 | 617 _stub_offset = data_offset(); |
618 _consts_offset = data_offset(); | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
619 _oops_offset = data_offset(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
620 _scopes_data_offset = _oops_offset + round_to(code_buffer->total_oop_size(), oopSize); |
0 | 621 _scopes_pcs_offset = _scopes_data_offset; |
622 _dependencies_offset = _scopes_pcs_offset; | |
623 _handler_table_offset = _dependencies_offset; | |
624 _nul_chk_table_offset = _handler_table_offset; | |
625 _nmethod_end_offset = _nul_chk_table_offset; | |
626 _compile_id = 0; // default | |
627 _comp_level = CompLevel_none; | |
628 _entry_point = instructions_begin(); | |
629 _verified_entry_point = instructions_begin() + offsets->value(CodeOffsets::Verified_Entry); | |
630 _osr_entry_point = NULL; | |
631 _exception_cache = NULL; | |
632 _pc_desc_cache.reset_to(NULL); | |
633 | |
634 code_buffer->copy_oops_to(this); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
635 debug_only(verify_scavenge_root_oops()); |
0 | 636 CodeCache::commit(this); |
637 } | |
638 | |
639 if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) { | |
640 ttyLocker ttyl; // keep the following output all in one block | |
641 // This output goes directly to the tty, not the compiler log. | |
642 // To enable tools to match it up with the compilation activity, | |
643 // be sure to tag this tty output with the compile ID. | |
644 if (xtty != NULL) { | |
645 xtty->begin_head("print_native_nmethod"); | |
646 xtty->method(_method); | |
647 xtty->stamp(); | |
648 xtty->end_head(" address='" INTPTR_FORMAT "'", (intptr_t) this); | |
649 } | |
650 // print the header part first | |
651 print(); | |
652 // then print the requested information | |
653 if (PrintNativeNMethods) { | |
654 print_code(); | |
655 oop_maps->print(); | |
656 } | |
657 if (PrintRelocations) { | |
658 print_relocations(); | |
659 } | |
660 if (xtty != NULL) { | |
661 xtty->tail("print_native_nmethod"); | |
662 } | |
663 } | |
664 Events::log("Create nmethod " INTPTR_FORMAT, this); | |
665 } | |
666 | |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
667 // For dtrace wrappers |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
668 #ifdef HAVE_DTRACE_H |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
669 nmethod::nmethod( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
670 methodOop method, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
671 int nmethod_size, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
672 CodeOffsets* offsets, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
673 CodeBuffer* code_buffer, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
674 int frame_size) |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
675 : CodeBlob("dtrace nmethod", code_buffer, sizeof(nmethod), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
676 nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, NULL), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
677 _compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
678 _compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1)) |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
679 { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
680 { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
681 debug_only(No_Safepoint_Verifier nsv;) |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
682 assert_locked_or_safepoint(CodeCache_lock); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
683 |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
684 init_defaults(); |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
685 _method = method; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
686 _entry_bci = InvocationEntryBci; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
687 // We have no exception handler or deopt handler make the |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
688 // values something that will never match a pc like the nmethod vtable entry |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
689 _exception_offset = 0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
690 _deoptimize_offset = 0; |
1204 | 691 _deoptimize_mh_offset = 0; |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1253
diff
changeset
|
692 _unwind_handler_offset = -1; |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
693 _trap_offset = offsets->value(CodeOffsets::Dtrace_trap); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
694 _orig_pc_offset = 0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
695 _stub_offset = data_offset(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
696 _consts_offset = data_offset(); |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
697 _oops_offset = data_offset(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
698 _scopes_data_offset = _oops_offset + round_to(code_buffer->total_oop_size(), oopSize); |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
699 _scopes_pcs_offset = _scopes_data_offset; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
700 _dependencies_offset = _scopes_pcs_offset; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
701 _handler_table_offset = _dependencies_offset; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
702 _nul_chk_table_offset = _handler_table_offset; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
703 _nmethod_end_offset = _nul_chk_table_offset; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
704 _compile_id = 0; // default |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
705 _comp_level = CompLevel_none; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
706 _entry_point = instructions_begin(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
707 _verified_entry_point = instructions_begin() + offsets->value(CodeOffsets::Verified_Entry); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
708 _osr_entry_point = NULL; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
709 _exception_cache = NULL; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
710 _pc_desc_cache.reset_to(NULL); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
711 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
712 code_buffer->copy_oops_to(this); |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
713 debug_only(verify_scavenge_root_oops()); |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
714 CodeCache::commit(this); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
715 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
716 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
717 if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
718 ttyLocker ttyl; // keep the following output all in one block |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
719 // This output goes directly to the tty, not the compiler log. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
720 // To enable tools to match it up with the compilation activity, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
721 // be sure to tag this tty output with the compile ID. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
722 if (xtty != NULL) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
723 xtty->begin_head("print_dtrace_nmethod"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
724 xtty->method(_method); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
725 xtty->stamp(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
726 xtty->end_head(" address='" INTPTR_FORMAT "'", (intptr_t) this); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
727 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
728 // print the header part first |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
729 print(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
730 // then print the requested information |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
731 if (PrintNMethods) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
732 print_code(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
733 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
734 if (PrintRelocations) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
735 print_relocations(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
736 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
737 if (xtty != NULL) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
738 xtty->tail("print_dtrace_nmethod"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
739 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
740 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
741 Events::log("Create nmethod " INTPTR_FORMAT, this); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
742 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
100
diff
changeset
|
743 #endif // def HAVE_DTRACE_H |
0 | 744 |
745 void* nmethod::operator new(size_t size, int nmethod_size) { | |
746 // Always leave some room in the CodeCache for I2C/C2I adapters | |
747 if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) return NULL; | |
748 return CodeCache::allocate(nmethod_size); | |
749 } | |
750 | |
751 | |
752 nmethod::nmethod( | |
753 methodOop method, | |
754 int nmethod_size, | |
755 int compile_id, | |
756 int entry_bci, | |
757 CodeOffsets* offsets, | |
758 int orig_pc_offset, | |
759 DebugInformationRecorder* debug_info, | |
760 Dependencies* dependencies, | |
761 CodeBuffer *code_buffer, | |
762 int frame_size, | |
763 OopMapSet* oop_maps, | |
764 ExceptionHandlerTable* handler_table, | |
765 ImplicitExceptionTable* nul_chk_table, | |
766 AbstractCompiler* compiler, | |
767 int comp_level | |
768 ) | |
769 : CodeBlob("nmethod", code_buffer, sizeof(nmethod), | |
770 nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps), | |
771 _compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)), | |
772 _compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1)) | |
773 { | |
774 assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR"); | |
775 { | |
776 debug_only(No_Safepoint_Verifier nsv;) | |
777 assert_locked_or_safepoint(CodeCache_lock); | |
778 | |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
779 init_defaults(); |
0 | 780 _method = method; |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
781 _entry_bci = entry_bci; |
0 | 782 _compile_id = compile_id; |
783 _comp_level = comp_level; | |
784 _compiler = compiler; | |
785 _orig_pc_offset = orig_pc_offset; | |
786 _stub_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start()); | |
787 | |
788 // Exception handler and deopt handler are in the stub section | |
789 _exception_offset = _stub_offset + offsets->value(CodeOffsets::Exceptions); | |
790 _deoptimize_offset = _stub_offset + offsets->value(CodeOffsets::Deopt); | |
1204 | 791 _deoptimize_mh_offset = _stub_offset + offsets->value(CodeOffsets::DeoptMH); |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1253
diff
changeset
|
792 if (offsets->value(CodeOffsets::UnwindHandler) != -1) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1253
diff
changeset
|
793 _unwind_handler_offset = instructions_offset() + offsets->value(CodeOffsets::UnwindHandler); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1253
diff
changeset
|
794 } else { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1253
diff
changeset
|
795 _unwind_handler_offset = -1; |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1253
diff
changeset
|
796 } |
0 | 797 _consts_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->consts()->start()); |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
798 _oops_offset = data_offset(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
799 _scopes_data_offset = _oops_offset + round_to(code_buffer->total_oop_size (), oopSize); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
800 _scopes_pcs_offset = _scopes_data_offset + round_to(debug_info->data_size (), oopSize); |
0 | 801 _dependencies_offset = _scopes_pcs_offset + adjust_pcs_size(debug_info->pcs_size()); |
802 _handler_table_offset = _dependencies_offset + round_to(dependencies->size_in_bytes (), oopSize); | |
803 _nul_chk_table_offset = _handler_table_offset + round_to(handler_table->size_in_bytes(), oopSize); | |
804 _nmethod_end_offset = _nul_chk_table_offset + round_to(nul_chk_table->size_in_bytes(), oopSize); | |
805 | |
806 _entry_point = instructions_begin(); | |
807 _verified_entry_point = instructions_begin() + offsets->value(CodeOffsets::Verified_Entry); | |
808 _osr_entry_point = instructions_begin() + offsets->value(CodeOffsets::OSR_Entry); | |
809 _exception_cache = NULL; | |
810 _pc_desc_cache.reset_to(scopes_pcs_begin()); | |
811 | |
812 // Copy contents of ScopeDescRecorder to nmethod | |
813 code_buffer->copy_oops_to(this); | |
814 debug_info->copy_to(this); | |
815 dependencies->copy_to(this); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
816 if (ScavengeRootsInCode && detect_scavenge_root_oops()) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
817 CodeCache::add_scavenge_root_nmethod(this); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
818 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
819 debug_only(verify_scavenge_root_oops()); |
0 | 820 |
821 CodeCache::commit(this); | |
822 | |
823 // Copy contents of ExceptionHandlerTable to nmethod | |
824 handler_table->copy_to(this); | |
825 nul_chk_table->copy_to(this); | |
826 | |
827 // we use the information of entry points to find out if a method is | |
828 // static or non static | |
829 assert(compiler->is_c2() || | |
830 _method->is_static() == (entry_point() == _verified_entry_point), | |
831 " entry points must be same for static methods and vice versa"); | |
832 } | |
833 | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
834 bool printnmethods = PrintNMethods |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
835 || CompilerOracle::should_print(_method) |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
836 || CompilerOracle::has_option_string(_method, "PrintNMethods"); |
0 | 837 if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) { |
838 print_nmethod(printnmethods); | |
839 } | |
840 | |
841 // Note: Do not verify in here as the CodeCache_lock is | |
842 // taken which would conflict with the CompiledIC_lock | |
843 // which taken during the verification of call sites. | |
844 // (was bug - gri 10/25/99) | |
845 | |
846 Events::log("Create nmethod " INTPTR_FORMAT, this); | |
847 } | |
848 | |
849 | |
850 // Print a short set of xml attributes to identify this nmethod. The | |
851 // output should be embedded in some other element. | |
852 void nmethod::log_identity(xmlStream* log) const { | |
853 log->print(" compile_id='%d'", compile_id()); | |
854 const char* nm_kind = compile_kind(); | |
855 if (nm_kind != NULL) log->print(" compile_kind='%s'", nm_kind); | |
856 if (compiler() != NULL) { | |
857 log->print(" compiler='%s'", compiler()->name()); | |
858 } | |
859 #ifdef TIERED | |
860 log->print(" level='%d'", comp_level()); | |
861 #endif // TIERED | |
862 } | |
863 | |
864 | |
865 #define LOG_OFFSET(log, name) \ | |
866 if ((intptr_t)name##_end() - (intptr_t)name##_begin()) \ | |
867 log->print(" " XSTR(name) "_offset='%d'" , \ | |
868 (intptr_t)name##_begin() - (intptr_t)this) | |
869 | |
870 | |
871 void nmethod::log_new_nmethod() const { | |
872 if (LogCompilation && xtty != NULL) { | |
873 ttyLocker ttyl; | |
874 HandleMark hm; | |
875 xtty->begin_elem("nmethod"); | |
876 log_identity(xtty); | |
877 xtty->print(" entry='" INTPTR_FORMAT "' size='%d'", | |
878 instructions_begin(), size()); | |
879 xtty->print(" address='" INTPTR_FORMAT "'", (intptr_t) this); | |
880 | |
881 LOG_OFFSET(xtty, relocation); | |
882 LOG_OFFSET(xtty, code); | |
883 LOG_OFFSET(xtty, stub); | |
884 LOG_OFFSET(xtty, consts); | |
885 LOG_OFFSET(xtty, scopes_data); | |
886 LOG_OFFSET(xtty, scopes_pcs); | |
887 LOG_OFFSET(xtty, dependencies); | |
888 LOG_OFFSET(xtty, handler_table); | |
889 LOG_OFFSET(xtty, nul_chk_table); | |
890 LOG_OFFSET(xtty, oops); | |
891 | |
892 xtty->method(method()); | |
893 xtty->stamp(); | |
894 xtty->end_elem(); | |
895 } | |
896 } | |
897 | |
898 #undef LOG_OFFSET | |
899 | |
900 | |
901 // Print out more verbose output usually for a newly created nmethod. | |
902 void nmethod::print_on(outputStream* st, const char* title) const { | |
903 if (st != NULL) { | |
904 ttyLocker ttyl; | |
905 // Print a little tag line that looks like +PrintCompilation output: | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
906 int tlen = (int) strlen(title); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
907 bool do_nl = false; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
908 if (tlen > 0 && title[tlen-1] == '\n') { tlen--; do_nl = true; } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
909 st->print("%3d%c %.*s", |
0 | 910 compile_id(), |
911 is_osr_method() ? '%' : | |
912 method() != NULL && | |
913 is_native_method() ? 'n' : ' ', | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
914 tlen, title); |
0 | 915 #ifdef TIERED |
916 st->print(" (%d) ", comp_level()); | |
917 #endif // TIERED | |
918 if (WizardMode) st->print(" (" INTPTR_FORMAT ")", this); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
919 if (Universe::heap()->is_gc_active() && method() != NULL) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
920 st->print("(method)"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
921 } else if (method() != NULL) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
922 method()->print_short_name(st); |
0 | 923 if (is_osr_method()) |
924 st->print(" @ %d", osr_entry_bci()); | |
925 if (method()->code_size() > 0) | |
926 st->print(" (%d bytes)", method()->code_size()); | |
927 } | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
928 |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
929 if (do_nl) st->cr(); |
0 | 930 } |
931 } | |
932 | |
933 | |
934 void nmethod::print_nmethod(bool printmethod) { | |
935 ttyLocker ttyl; // keep the following output all in one block | |
936 if (xtty != NULL) { | |
937 xtty->begin_head("print_nmethod"); | |
938 xtty->stamp(); | |
939 xtty->end_head(); | |
940 } | |
941 // print the header part first | |
942 print(); | |
943 // then print the requested information | |
944 if (printmethod) { | |
945 print_code(); | |
946 print_pcs(); | |
947 oop_maps()->print(); | |
948 } | |
949 if (PrintDebugInfo) { | |
950 print_scopes(); | |
951 } | |
952 if (PrintRelocations) { | |
953 print_relocations(); | |
954 } | |
955 if (PrintDependencies) { | |
956 print_dependencies(); | |
957 } | |
958 if (PrintExceptionHandlers) { | |
959 print_handler_table(); | |
960 print_nul_chk_table(); | |
961 } | |
962 if (xtty != NULL) { | |
963 xtty->tail("print_nmethod"); | |
964 } | |
965 } | |
966 | |
967 | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
968 // Promote one word from an assembly-time handle to a live embedded oop. |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
969 inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
970 if (handle == NULL || |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
971 // As a special case, IC oops are initialized to 1 or -1. |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
972 handle == (jobject) Universe::non_oop_word()) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
973 (*dest) = (oop) handle; |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
974 } else { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
975 (*dest) = JNIHandles::resolve_non_null(handle); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
976 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
977 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
978 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
979 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
980 void nmethod::copy_oops(GrowableArray<jobject>* array) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
981 //assert(oops_size() == 0, "do this handshake just once, please"); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
982 int length = array->length(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
983 assert((address)(oops_begin() + length) <= data_end(), "oops big enough"); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
984 oop* dest = oops_begin(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
985 for (int index = 0 ; index < length; index++) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
986 initialize_immediate_oop(&dest[index], array->at(index)); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
987 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
988 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
989 // Now we can fix up all the oops in the code. We need to do this |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
990 // in the code because the assembler uses jobjects as placeholders. |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
991 // The code and relocations have already been initialized by the |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
992 // CodeBlob constructor, so it is valid even at this early point to |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
993 // iterate over relocations and patch the code. |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
994 fix_oop_relocations(NULL, NULL, /*initialize_immediates=*/ true); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
995 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
996 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
997 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
998 bool nmethod::is_at_poll_return(address pc) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
999 RelocIterator iter(this, pc, pc+1); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1000 while (iter.next()) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1001 if (iter.type() == relocInfo::poll_return_type) |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1002 return true; |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1003 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1004 return false; |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1005 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1006 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1007 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1008 bool nmethod::is_at_poll_or_poll_return(address pc) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1009 RelocIterator iter(this, pc, pc+1); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1010 while (iter.next()) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1011 relocInfo::relocType t = iter.type(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1012 if (t == relocInfo::poll_return_type || t == relocInfo::poll_type) |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1013 return true; |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1014 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1015 return false; |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1016 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1017 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1018 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1019 void nmethod::fix_oop_relocations(address begin, address end, bool initialize_immediates) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1020 // re-patch all oop-bearing instructions, just in case some oops moved |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1021 RelocIterator iter(this, begin, end); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1022 while (iter.next()) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1023 if (iter.type() == relocInfo::oop_type) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1024 oop_Relocation* reloc = iter.oop_reloc(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1025 if (initialize_immediates && reloc->oop_is_immediate()) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1026 oop* dest = reloc->oop_addr(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1027 initialize_immediate_oop(dest, (jobject) *dest); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1028 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1029 // Refresh the oop-related bits of this instruction. |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1030 reloc->fix_oop_relocation(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1031 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1032 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1033 // There must not be any interfering patches or breakpoints. |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1034 assert(!(iter.type() == relocInfo::breakpoint_type |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1035 && iter.breakpoint_reloc()->active()), |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1036 "no active breakpoint"); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1037 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1038 } |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1039 |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
1040 |
0 | 1041 ScopeDesc* nmethod::scope_desc_at(address pc) { |
1042 PcDesc* pd = pc_desc_at(pc); | |
1043 guarantee(pd != NULL, "scope must be present"); | |
1044 return new ScopeDesc(this, pd->scope_decode_offset(), | |
1253
f70b0d9ab095
6910618: C2: Error: assert(d->is_oop(),"JVM_ArrayCopy: dst not an oop")
kvn
parents:
1250
diff
changeset
|
1045 pd->obj_decode_offset(), pd->should_reexecute(), |
f70b0d9ab095
6910618: C2: Error: assert(d->is_oop(),"JVM_ArrayCopy: dst not an oop")
kvn
parents:
1250
diff
changeset
|
1046 pd->return_oop()); |
0 | 1047 } |
1048 | |
1049 | |
1050 void nmethod::clear_inline_caches() { | |
1051 assert(SafepointSynchronize::is_at_safepoint(), "cleaning of IC's only allowed at safepoint"); | |
1052 if (is_zombie()) { | |
1053 return; | |
1054 } | |
1055 | |
1056 RelocIterator iter(this); | |
1057 while (iter.next()) { | |
1058 iter.reloc()->clear_inline_cache(); | |
1059 } | |
1060 } | |
1061 | |
1062 | |
1063 void nmethod::cleanup_inline_caches() { | |
1064 | |
1538
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1065 assert_locked_or_safepoint(CompiledIC_lock); |
0 | 1066 |
1067 // If the method is not entrant or zombie then a JMP is plastered over the | |
1068 // first few bytes. If an oop in the old code was there, that oop | |
1069 // should not get GC'd. Skip the first few bytes of oops on | |
1070 // not-entrant methods. | |
1071 address low_boundary = verified_entry_point(); | |
1072 if (!is_in_use()) { | |
1073 low_boundary += NativeJump::instruction_size; | |
1074 // %%% Note: On SPARC we patch only a 4-byte trap, not a full NativeJump. | |
1075 // This means that the low_boundary is going to be a little too high. | |
1076 // This shouldn't matter, since oops of non-entrant methods are never used. | |
1077 // In fact, why are we bothering to look at oops in a non-entrant method?? | |
1078 } | |
1079 | |
1080 // Find all calls in an nmethod, and clear the ones that points to zombie methods | |
1081 ResourceMark rm; | |
1082 RelocIterator iter(this, low_boundary); | |
1083 while(iter.next()) { | |
1084 switch(iter.type()) { | |
1085 case relocInfo::virtual_call_type: | |
1086 case relocInfo::opt_virtual_call_type: { | |
1087 CompiledIC *ic = CompiledIC_at(iter.reloc()); | |
1088 // Ok, to lookup references to zombies here | |
1089 CodeBlob *cb = CodeCache::find_blob_unsafe(ic->ic_destination()); | |
1090 if( cb != NULL && cb->is_nmethod() ) { | |
1091 nmethod* nm = (nmethod*)cb; | |
1092 // Clean inline caches pointing to both zombie and not_entrant methods | |
1202 | 1093 if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean(); |
0 | 1094 } |
1095 break; | |
1096 } | |
1097 case relocInfo::static_call_type: { | |
1098 CompiledStaticCall *csc = compiledStaticCall_at(iter.reloc()); | |
1099 CodeBlob *cb = CodeCache::find_blob_unsafe(csc->destination()); | |
1100 if( cb != NULL && cb->is_nmethod() ) { | |
1101 nmethod* nm = (nmethod*)cb; | |
1102 // Clean inline caches pointing to both zombie and not_entrant methods | |
1202 | 1103 if (!nm->is_in_use() || (nm->method()->code() != nm)) csc->set_to_clean(); |
0 | 1104 } |
1105 break; | |
1106 } | |
1107 } | |
1108 } | |
1109 } | |
1110 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1111 // This is a private interface with the sweeper. |
0 | 1112 void nmethod::mark_as_seen_on_stack() { |
1113 assert(is_not_entrant(), "must be a non-entrant method"); | |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1114 // Set the traversal mark to ensure that the sweeper does 2 |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1115 // cleaning passes before moving to zombie. |
0 | 1116 set_stack_traversal_mark(NMethodSweeper::traversal_count()); |
1117 } | |
1118 | |
1119 // Tell if a non-entrant method can be converted to a zombie (i.e., there is no activations on the stack) | |
1120 bool nmethod::can_not_entrant_be_converted() { | |
1121 assert(is_not_entrant(), "must be a non-entrant method"); | |
1122 | |
1123 // Since the nmethod sweeper only does partial sweep the sweeper's traversal | |
1124 // count can be greater than the stack traversal count before it hits the | |
1125 // nmethod for the second time. | |
1126 return stack_traversal_mark()+1 < NMethodSweeper::traversal_count(); | |
1127 } | |
1128 | |
1129 void nmethod::inc_decompile_count() { | |
1130 // Could be gated by ProfileTraps, but do not bother... | |
1131 methodOop m = method(); | |
1132 if (m == NULL) return; | |
1133 methodDataOop mdo = m->method_data(); | |
1134 if (mdo == NULL) return; | |
1135 // There is a benign race here. See comments in methodDataOop.hpp. | |
1136 mdo->inc_decompile_count(); | |
1137 } | |
1138 | |
1139 void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) { | |
1140 | |
1141 post_compiled_method_unload(); | |
1142 | |
1143 // Since this nmethod is being unloaded, make sure that dependencies | |
1144 // recorded in instanceKlasses get flushed and pass non-NULL closure to | |
1145 // indicate that this work is being done during a GC. | |
1146 assert(Universe::heap()->is_gc_active(), "should only be called during gc"); | |
1147 assert(is_alive != NULL, "Should be non-NULL"); | |
1148 // A non-NULL is_alive closure indicates that this is being called during GC. | |
1149 flush_dependencies(is_alive); | |
1150 | |
1151 // Break cycle between nmethod & method | |
1152 if (TraceClassUnloading && WizardMode) { | |
1153 tty->print_cr("[Class unloading: Making nmethod " INTPTR_FORMAT | |
1154 " unloadable], methodOop(" INTPTR_FORMAT | |
1155 "), cause(" INTPTR_FORMAT ")", | |
1156 this, (address)_method, (address)cause); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1157 if (!Universe::heap()->is_gc_active()) |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1158 cause->klass()->print(); |
0 | 1159 } |
941 | 1160 // Unlink the osr method, so we do not look this up again |
1161 if (is_osr_method()) { | |
1162 invalidate_osr_method(); | |
1163 } | |
0 | 1164 // If _method is already NULL the methodOop is about to be unloaded, |
1165 // so we don't have to break the cycle. Note that it is possible to | |
1166 // have the methodOop live here, in case we unload the nmethod because | |
1167 // it is pointing to some oop (other than the methodOop) being unloaded. | |
1168 if (_method != NULL) { | |
1169 // OSR methods point to the methodOop, but the methodOop does not | |
1170 // point back! | |
1171 if (_method->code() == this) { | |
1172 _method->clear_code(); // Break a cycle | |
1173 } | |
1174 _method = NULL; // Clear the method of this dead nmethod | |
1175 } | |
1176 // Make the class unloaded - i.e., change state and notify sweeper | |
1538
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1177 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); |
0 | 1178 if (is_in_use()) { |
1179 // Transitioning directly from live to unloaded -- so | |
1180 // we need to force a cache clean-up; remember this | |
1181 // for later on. | |
1182 CodeCache::set_needs_cache_clean(true); | |
1183 } | |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1184 _state = unloaded; |
0 | 1185 |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1186 // Log the unloading. |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1187 log_state_change(); |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1188 |
0 | 1189 // The methodOop is gone at this point |
1190 assert(_method == NULL, "Tautology"); | |
1191 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1192 set_osr_link(NULL); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1193 //set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods |
0 | 1194 NMethodSweeper::notify(this); |
1195 } | |
1196 | |
1197 void nmethod::invalidate_osr_method() { | |
1198 assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); | |
1199 // Remove from list of active nmethods | |
1200 if (method() != NULL) | |
1201 instanceKlass::cast(method()->method_holder())->remove_osr_nmethod(this); | |
1202 // Set entry as invalid | |
1203 _entry_bci = InvalidOSREntryBci; | |
1204 } | |
1205 | |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1206 void nmethod::log_state_change() const { |
0 | 1207 if (LogCompilation) { |
1208 if (xtty != NULL) { | |
1209 ttyLocker ttyl; // keep the following output all in one block | |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1210 if (_state == unloaded) { |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1211 xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'", |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1212 os::current_thread_id()); |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1213 } else { |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1214 xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s", |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1215 os::current_thread_id(), |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1216 (_state == zombie ? " zombie='1'" : "")); |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1217 } |
0 | 1218 log_identity(xtty); |
1219 xtty->stamp(); | |
1220 xtty->end_elem(); | |
1221 } | |
1222 } | |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1223 if (PrintCompilation && _state != unloaded) { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1224 print_on(tty, _state == zombie ? "made zombie " : "made not entrant "); |
0 | 1225 tty->cr(); |
1226 } | |
1227 } | |
1228 | |
1229 // Common functionality for both make_not_entrant and make_zombie | |
1141 | 1230 bool nmethod::make_not_entrant_or_zombie(unsigned int state) { |
0 | 1231 assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); |
1232 | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
1233 bool was_alive = false; |
0 | 1234 |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1235 // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below. |
0 | 1236 nmethodLocker nml(this); |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1237 methodHandle the_method(method()); |
0 | 1238 |
1239 { | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
1240 // If the method is already zombie there is nothing to do |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
1241 if (is_zombie()) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
1242 return false; |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
1243 } |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
1244 |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1245 // invalidate osr nmethod before acquiring the patching lock since |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1246 // they both acquire leaf locks and we don't want a deadlock. |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1247 // This logic is equivalent to the logic below for patching the |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1248 // verified entry point of regular methods. |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1249 if (is_osr_method()) { |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1250 // this effectively makes the osr nmethod not entrant |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1251 invalidate_osr_method(); |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1252 } |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1253 |
0 | 1254 // Enter critical section. Does not block for safepoint. |
1255 MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag); | |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1256 |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1257 if (_state == state) { |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1258 // another thread already performed this transition so nothing |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1259 // to do, but return false to indicate this. |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1260 return false; |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1261 } |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1262 |
0 | 1263 // The caller can be calling the method statically or through an inline |
1264 // cache call. | |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1265 if (!is_osr_method() && !is_not_entrant()) { |
0 | 1266 NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), |
1267 SharedRuntime::get_handle_wrong_method_stub()); | |
1268 } | |
1269 | |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1270 if (is_in_use()) { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1271 // It's a true state change, so mark the method as decompiled. |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1272 // Do it only for transition from alive. |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1273 inc_decompile_count(); |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1274 } |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
1275 |
0 | 1276 // Change state |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1277 _state = state; |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1278 |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1279 // Log the transition once |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1280 log_state_change(); |
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1281 |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1282 // Remove nmethod from method. |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1283 // We need to check if both the _code and _from_compiled_code_entry_point |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1284 // refer to this nmethod because there is a race in setting these two fields |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1285 // in methodOop as seen in bugid 4947125. |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1286 // If the vep() points to the zombie nmethod, the memory for the nmethod |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1287 // could be flushed and the compiler and vtable stubs could still call |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1288 // through it. |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1289 if (method() != NULL && (method()->code() == this || |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1290 method()->from_compiled_entry() == verified_entry_point())) { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1291 HandleMark hm; |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1292 method()->clear_code(); |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1293 } |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1294 |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1295 if (state == not_entrant) { |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1296 mark_as_seen_on_stack(); |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1297 } |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1298 |
0 | 1299 } // leave critical region under Patching_lock |
1300 | |
1538
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1301 // When the nmethod becomes zombie it is no longer alive so the |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1302 // dependencies must be flushed. nmethods in the not_entrant |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1303 // state will be flushed later when the transition to zombie |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1304 // happens or they get unloaded. |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1305 if (state == zombie) { |
1644
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1306 // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1307 // and it hasn't already been reported for this nmethod then report it now. |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1308 // (the event may have been reported earilier if the GC marked it for unloading). |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1309 post_compiled_method_unload(); |
2a47bd84841f
6965184: possible races in make_not_entrant_or_zombie
never
parents:
1616
diff
changeset
|
1310 |
1538
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1311 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1312 flush_dependencies(NULL); |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1313 } else { |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1314 assert(state == not_entrant, "other cases may need to be handled differently"); |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1315 } |
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1316 |
0 | 1317 if (TraceCreateZombies) { |
1318 tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie"); | |
1319 } | |
1320 | |
1321 // Make sweeper aware that there is a zombie method that needs to be removed | |
1322 NMethodSweeper::notify(this); | |
1323 | |
1109
032260830071
5057818: codecache full and compiler disabled in bigapps fastdebug run
never
parents:
994
diff
changeset
|
1324 return true; |
0 | 1325 } |
1326 | |
1327 void nmethod::flush() { | |
1328 // Note that there are no valid oops in the nmethod anymore. | |
1329 assert(is_zombie() || (is_osr_method() && is_unloaded()), "must be a zombie method"); | |
1330 assert(is_marked_for_reclamation() || (is_osr_method() && is_unloaded()), "must be marked for reclamation"); | |
1331 | |
1332 assert (!is_locked_by_vm(), "locked methods shouldn't be flushed"); | |
1538
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1333 assert_locked_or_safepoint(CodeCache_lock); |
0 | 1334 |
1335 // completely deallocate this method | |
1336 EventMark m("flushing nmethod " INTPTR_FORMAT " %s", this, ""); | |
1337 if (PrintMethodFlushing) { | |
1202 | 1338 tty->print_cr("*flushing nmethod %3d/" INTPTR_FORMAT ". Live blobs:" UINT32_FORMAT "/Free CodeCache:" SIZE_FORMAT "Kb", |
1339 _compile_id, this, CodeCache::nof_blobs(), CodeCache::unallocated_capacity()/1024); | |
0 | 1340 } |
1341 | |
1342 // We need to deallocate any ExceptionCache data. | |
1343 // Note that we do not need to grab the nmethod lock for this, it | |
1344 // better be thread safe if we're disposing of it! | |
1345 ExceptionCache* ec = exception_cache(); | |
1346 set_exception_cache(NULL); | |
1347 while(ec != NULL) { | |
1348 ExceptionCache* next = ec->next(); | |
1349 delete ec; | |
1350 ec = next; | |
1351 } | |
1352 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1353 if (on_scavenge_root_list()) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1354 CodeCache::drop_scavenge_root_nmethod(this); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1355 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1356 |
1202 | 1357 if (is_speculatively_disconnected()) { |
1358 CodeCache::remove_saved_code(this); | |
1359 } | |
1360 | |
1692 | 1361 #ifdef SHARK |
1362 ((SharkCompiler *) compiler())->free_compiled_method(instructions_begin()); | |
1363 #endif // SHARK | |
1364 | |
0 | 1365 ((CodeBlob*)(this))->flush(); |
1366 | |
1367 CodeCache::free(this); | |
1368 } | |
1369 | |
1370 | |
1371 // | |
1372 // Notify all classes this nmethod is dependent on that it is no | |
1373 // longer dependent. This should only be called in two situations. | |
1374 // First, when a nmethod transitions to a zombie all dependents need | |
1375 // to be clear. Since zombification happens at a safepoint there's no | |
1376 // synchronization issues. The second place is a little more tricky. | |
1377 // During phase 1 of mark sweep class unloading may happen and as a | |
1378 // result some nmethods may get unloaded. In this case the flushing | |
1379 // of dependencies must happen during phase 1 since after GC any | |
1380 // dependencies in the unloaded nmethod won't be updated, so | |
1381 // traversing the dependency information in unsafe. In that case this | |
1382 // function is called with a non-NULL argument and this function only | |
1383 // notifies instanceKlasses that are reachable | |
1384 | |
1385 void nmethod::flush_dependencies(BoolObjectClosure* is_alive) { | |
1538
bfe29ec02863
6950075: nmethod sweeper should operate concurrently
never
parents:
1490
diff
changeset
|
1386 assert_locked_or_safepoint(CodeCache_lock); |
0 | 1387 assert(Universe::heap()->is_gc_active() == (is_alive != NULL), |
1388 "is_alive is non-NULL if and only if we are called during GC"); | |
1389 if (!has_flushed_dependencies()) { | |
1390 set_has_flushed_dependencies(); | |
1391 for (Dependencies::DepStream deps(this); deps.next(); ) { | |
1392 klassOop klass = deps.context_type(); | |
1393 if (klass == NULL) continue; // ignore things like evol_method | |
1394 | |
1395 // During GC the is_alive closure is non-NULL, and is used to | |
1396 // determine liveness of dependees that need to be updated. | |
1397 if (is_alive == NULL || is_alive->do_object_b(klass)) { | |
1398 instanceKlass::cast(klass)->remove_dependent_nmethod(this); | |
1399 } | |
1400 } | |
1401 } | |
1402 } | |
1403 | |
1404 | |
1405 // If this oop is not live, the nmethod can be unloaded. | |
1406 bool nmethod::can_unload(BoolObjectClosure* is_alive, | |
1407 OopClosure* keep_alive, | |
1408 oop* root, bool unloading_occurred) { | |
1409 assert(root != NULL, "just checking"); | |
1410 oop obj = *root; | |
1411 if (obj == NULL || is_alive->do_object_b(obj)) { | |
1412 return false; | |
1413 } | |
1414 if (obj->is_compiledICHolder()) { | |
1415 compiledICHolderOop cichk_oop = compiledICHolderOop(obj); | |
1416 if (is_alive->do_object_b( | |
1417 cichk_oop->holder_method()->method_holder()) && | |
1418 is_alive->do_object_b(cichk_oop->holder_klass())) { | |
1419 // The oop should be kept alive | |
1420 keep_alive->do_oop(root); | |
1421 return false; | |
1422 } | |
1423 } | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1424 // If ScavengeRootsInCode is true, an nmethod might be unloaded |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1425 // simply because one of its constant oops has gone dead. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1426 // No actual classes need to be unloaded in order for this to occur. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1427 assert(unloading_occurred || ScavengeRootsInCode, "Inconsistency in unloading"); |
0 | 1428 make_unloaded(is_alive, obj); |
1429 return true; | |
1430 } | |
1431 | |
1432 // ------------------------------------------------------------------ | |
1433 // post_compiled_method_load_event | |
1434 // new method for install_code() path | |
1435 // Transfer information from compilation to jvmti | |
1436 void nmethod::post_compiled_method_load_event() { | |
1437 | |
1438 methodOop moop = method(); | |
1439 HS_DTRACE_PROBE8(hotspot, compiled__method__load, | |
1440 moop->klass_name()->bytes(), | |
1441 moop->klass_name()->utf8_length(), | |
1442 moop->name()->bytes(), | |
1443 moop->name()->utf8_length(), | |
1444 moop->signature()->bytes(), | |
1445 moop->signature()->utf8_length(), | |
1446 code_begin(), code_size()); | |
1447 | |
1616
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1448 if (JvmtiExport::should_post_compiled_method_load() || |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1449 JvmtiExport::should_post_compiled_method_unload()) { |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1450 get_and_cache_jmethod_id(); |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1451 } |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1452 |
0 | 1453 if (JvmtiExport::should_post_compiled_method_load()) { |
1454 JvmtiExport::post_compiled_method_load(this); | |
1455 } | |
1456 } | |
1457 | |
1616
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1458 jmethodID nmethod::get_and_cache_jmethod_id() { |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1459 if (_jmethod_id == NULL) { |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1460 // Cache the jmethod_id since it can no longer be looked up once the |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1461 // method itself has been marked for unloading. |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1462 _jmethod_id = method()->jmethod_id(); |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1463 } |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1464 return _jmethod_id; |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1465 } |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1466 |
0 | 1467 void nmethod::post_compiled_method_unload() { |
1577
852d0157c696
6956931: assert(SafepointSynchronize::is_at_safepoint()) failed: must be executed at a safepoint
never
parents:
1563
diff
changeset
|
1468 if (unload_reported()) { |
852d0157c696
6956931: assert(SafepointSynchronize::is_at_safepoint()) failed: must be executed at a safepoint
never
parents:
1563
diff
changeset
|
1469 // During unloading we transition to unloaded and then to zombie |
852d0157c696
6956931: assert(SafepointSynchronize::is_at_safepoint()) failed: must be executed at a safepoint
never
parents:
1563
diff
changeset
|
1470 // and the unloading is reported during the first transition. |
852d0157c696
6956931: assert(SafepointSynchronize::is_at_safepoint()) failed: must be executed at a safepoint
never
parents:
1563
diff
changeset
|
1471 return; |
852d0157c696
6956931: assert(SafepointSynchronize::is_at_safepoint()) failed: must be executed at a safepoint
never
parents:
1563
diff
changeset
|
1472 } |
852d0157c696
6956931: assert(SafepointSynchronize::is_at_safepoint()) failed: must be executed at a safepoint
never
parents:
1563
diff
changeset
|
1473 |
0 | 1474 assert(_method != NULL && !is_unloaded(), "just checking"); |
1475 DTRACE_METHOD_UNLOAD_PROBE(method()); | |
1476 | |
1477 // If a JVMTI agent has enabled the CompiledMethodUnload event then | |
1616
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1478 // post the event. Sometime later this nmethod will be made a zombie |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1479 // by the sweeper but the methodOop will not be valid at that point. |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1480 // If the _jmethod_id is null then no load event was ever requested |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1481 // so don't bother posting the unload. The main reason for this is |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1482 // that the jmethodID is a weak reference to the methodOop so if |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1483 // it's being unloaded there's no way to look it up since the weak |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1484 // ref will have been cleared. |
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1485 if (_jmethod_id != NULL && JvmtiExport::should_post_compiled_method_unload()) { |
0 | 1486 assert(!unload_reported(), "already unloaded"); |
1487 HandleMark hm; | |
1616
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1602
diff
changeset
|
1488 JvmtiExport::post_compiled_method_unload(_jmethod_id, code_begin()); |
0 | 1489 } |
1490 | |
1491 // The JVMTI CompiledMethodUnload event can be enabled or disabled at | |
1492 // any time. As the nmethod is being unloaded now we mark it has | |
1493 // having the unload event reported - this will ensure that we don't | |
1494 // attempt to report the event in the unlikely scenario where the | |
1495 // event is enabled at the time the nmethod is made a zombie. | |
1496 set_unload_reported(); | |
1497 } | |
1498 | |
1499 // This is called at the end of the strong tracing/marking phase of a | |
1500 // GC to unload an nmethod if it contains otherwise unreachable | |
1501 // oops. | |
1502 | |
1503 void nmethod::do_unloading(BoolObjectClosure* is_alive, | |
1504 OopClosure* keep_alive, bool unloading_occurred) { | |
1505 // Make sure the oop's ready to receive visitors | |
1506 assert(!is_zombie() && !is_unloaded(), | |
1507 "should not call follow on zombie or unloaded nmethod"); | |
1508 | |
1509 // If the method is not entrant then a JMP is plastered over the | |
1510 // first few bytes. If an oop in the old code was there, that oop | |
1511 // should not get GC'd. Skip the first few bytes of oops on | |
1512 // not-entrant methods. | |
1513 address low_boundary = verified_entry_point(); | |
1514 if (is_not_entrant()) { | |
1515 low_boundary += NativeJump::instruction_size; | |
1516 // %%% Note: On SPARC we patch only a 4-byte trap, not a full NativeJump. | |
1517 // (See comment above.) | |
1518 } | |
1519 | |
1520 // The RedefineClasses() API can cause the class unloading invariant | |
1521 // to no longer be true. See jvmtiExport.hpp for details. | |
1522 // Also, leave a debugging breadcrumb in local flag. | |
1523 bool a_class_was_redefined = JvmtiExport::has_redefined_a_class(); | |
1524 if (a_class_was_redefined) { | |
1525 // This set of the unloading_occurred flag is done before the | |
1526 // call to post_compiled_method_unload() so that the unloading | |
1527 // of this nmethod is reported. | |
1528 unloading_occurred = true; | |
1529 } | |
1530 | |
1531 // Follow methodOop | |
1532 if (can_unload(is_alive, keep_alive, (oop*)&_method, unloading_occurred)) { | |
1533 return; | |
1534 } | |
1535 | |
1536 // Exception cache | |
1537 ExceptionCache* ec = exception_cache(); | |
1538 while (ec != NULL) { | |
1539 oop* ex_addr = (oop*)ec->exception_type_addr(); | |
1540 oop ex = *ex_addr; | |
1541 ExceptionCache* next_ec = ec->next(); | |
1542 if (ex != NULL && !is_alive->do_object_b(ex)) { | |
1543 assert(!ex->is_compiledICHolder(), "Possible error here"); | |
1544 remove_from_exception_cache(ec); | |
1545 } | |
1546 ec = next_ec; | |
1547 } | |
1548 | |
1549 // If class unloading occurred we first iterate over all inline caches and | |
1550 // clear ICs where the cached oop is referring to an unloaded klass or method. | |
1551 // The remaining live cached oops will be traversed in the relocInfo::oop_type | |
1552 // iteration below. | |
1553 if (unloading_occurred) { | |
1554 RelocIterator iter(this, low_boundary); | |
1555 while(iter.next()) { | |
1556 if (iter.type() == relocInfo::virtual_call_type) { | |
1557 CompiledIC *ic = CompiledIC_at(iter.reloc()); | |
1558 oop ic_oop = ic->cached_oop(); | |
1559 if (ic_oop != NULL && !is_alive->do_object_b(ic_oop)) { | |
1560 // The only exception is compiledICHolder oops which may | |
1561 // yet be marked below. (We check this further below). | |
1562 if (ic_oop->is_compiledICHolder()) { | |
1563 compiledICHolderOop cichk_oop = compiledICHolderOop(ic_oop); | |
1564 if (is_alive->do_object_b( | |
1565 cichk_oop->holder_method()->method_holder()) && | |
1566 is_alive->do_object_b(cichk_oop->holder_klass())) { | |
1567 continue; | |
1568 } | |
1569 } | |
1570 ic->set_to_clean(); | |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
1378
diff
changeset
|
1571 assert(ic->cached_oop() == NULL, |
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
1378
diff
changeset
|
1572 "cached oop in IC should be cleared"); |
0 | 1573 } |
1574 } | |
1575 } | |
1576 } | |
1577 | |
1578 // Compiled code | |
1579 RelocIterator iter(this, low_boundary); | |
1580 while (iter.next()) { | |
1581 if (iter.type() == relocInfo::oop_type) { | |
1582 oop_Relocation* r = iter.oop_reloc(); | |
1583 // In this loop, we must only traverse those oops directly embedded in | |
1584 // the code. Other oops (oop_index>0) are seen as part of scopes_oops. | |
1585 assert(1 == (r->oop_is_immediate()) + | |
1586 (r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()), | |
1587 "oop must be found in exactly one place"); | |
1588 if (r->oop_is_immediate() && r->oop_value() != NULL) { | |
1589 if (can_unload(is_alive, keep_alive, r->oop_addr(), unloading_occurred)) { | |
1590 return; | |
1591 } | |
1592 } | |
1593 } | |
1594 } | |
1595 | |
1596 | |
1597 // Scopes | |
1598 for (oop* p = oops_begin(); p < oops_end(); p++) { | |
1599 if (*p == Universe::non_oop_word()) continue; // skip non-oops | |
1600 if (can_unload(is_alive, keep_alive, p, unloading_occurred)) { | |
1601 return; | |
1602 } | |
1603 } | |
1604 | |
1605 #ifndef PRODUCT | |
1606 // This nmethod was not unloaded; check below that all CompiledICs | |
1607 // refer to marked oops. | |
1608 { | |
1609 RelocIterator iter(this, low_boundary); | |
1610 while (iter.next()) { | |
1611 if (iter.type() == relocInfo::virtual_call_type) { | |
1612 CompiledIC *ic = CompiledIC_at(iter.reloc()); | |
1613 oop ic_oop = ic->cached_oop(); | |
1614 assert(ic_oop == NULL || is_alive->do_object_b(ic_oop), | |
1615 "Found unmarked ic_oop in reachable nmethod"); | |
1616 } | |
1617 } | |
1618 } | |
1619 #endif // !PRODUCT | |
1620 } | |
1621 | |
941 | 1622 // This method is called twice during GC -- once while |
1623 // tracing the "active" nmethods on thread stacks during | |
1624 // the (strong) marking phase, and then again when walking | |
1625 // the code cache contents during the weak roots processing | |
1626 // phase. The two uses are distinguished by means of the | |
994
753cf9794df9
6885169: merge of 4957990 and 6863023 causes conflict on do_nmethods
jrose
parents:
993
diff
changeset
|
1627 // 'do_strong_roots_only' flag, which is true in the first |
941 | 1628 // case. We want to walk the weak roots in the nmethod |
1629 // only in the second case. The weak roots in the nmethod | |
1630 // are the oops in the ExceptionCache and the InlineCache | |
1631 // oops. | |
994
753cf9794df9
6885169: merge of 4957990 and 6863023 causes conflict on do_nmethods
jrose
parents:
993
diff
changeset
|
1632 void nmethod::oops_do(OopClosure* f, bool do_strong_roots_only) { |
0 | 1633 // make sure the oops ready to receive visitors |
1634 assert(!is_zombie() && !is_unloaded(), | |
1635 "should not call follow on zombie or unloaded nmethod"); | |
1636 | |
1637 // If the method is not entrant or zombie then a JMP is plastered over the | |
1638 // first few bytes. If an oop in the old code was there, that oop | |
1639 // should not get GC'd. Skip the first few bytes of oops on | |
1640 // not-entrant methods. | |
1641 address low_boundary = verified_entry_point(); | |
1642 if (is_not_entrant()) { | |
1643 low_boundary += NativeJump::instruction_size; | |
1644 // %%% Note: On SPARC we patch only a 4-byte trap, not a full NativeJump. | |
1645 // (See comment above.) | |
1646 } | |
1647 | |
1648 // Compiled code | |
1649 f->do_oop((oop*) &_method); | |
994
753cf9794df9
6885169: merge of 4957990 and 6863023 causes conflict on do_nmethods
jrose
parents:
993
diff
changeset
|
1650 if (!do_strong_roots_only) { |
941 | 1651 // weak roots processing phase -- update ExceptionCache oops |
1652 ExceptionCache* ec = exception_cache(); | |
1653 while(ec != NULL) { | |
1654 f->do_oop((oop*)ec->exception_type_addr()); | |
1655 ec = ec->next(); | |
1656 } | |
1657 } // Else strong roots phase -- skip oops in ExceptionCache | |
0 | 1658 |
1659 RelocIterator iter(this, low_boundary); | |
941 | 1660 |
0 | 1661 while (iter.next()) { |
1662 if (iter.type() == relocInfo::oop_type ) { | |
1663 oop_Relocation* r = iter.oop_reloc(); | |
1664 // In this loop, we must only follow those oops directly embedded in | |
1665 // the code. Other oops (oop_index>0) are seen as part of scopes_oops. | |
941 | 1666 assert(1 == (r->oop_is_immediate()) + |
1667 (r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()), | |
1668 "oop must be found in exactly one place"); | |
0 | 1669 if (r->oop_is_immediate() && r->oop_value() != NULL) { |
1670 f->do_oop(r->oop_addr()); | |
1671 } | |
1672 } | |
1673 } | |
1674 | |
1675 // Scopes | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1676 // This includes oop constants not inlined in the code stream. |
0 | 1677 for (oop* p = oops_begin(); p < oops_end(); p++) { |
1678 if (*p == Universe::non_oop_word()) continue; // skip non-oops | |
1679 f->do_oop(p); | |
1680 } | |
1681 } | |
1682 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1683 #define NMETHOD_SENTINEL ((nmethod*)badAddress) |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1684 |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1685 nmethod* volatile nmethod::_oops_do_mark_nmethods; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1686 |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1687 // An nmethod is "marked" if its _mark_link is set non-null. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1688 // Even if it is the end of the linked list, it will have a non-null link value, |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1689 // as long as it is on the list. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1690 // This code must be MP safe, because it is used from parallel GC passes. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1691 bool nmethod::test_set_oops_do_mark() { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1692 assert(nmethod::oops_do_marking_is_active(), "oops_do_marking_prologue must be called"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1693 nmethod* observed_mark_link = _oops_do_mark_link; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1694 if (observed_mark_link == NULL) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1695 // Claim this nmethod for this thread to mark. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1696 observed_mark_link = (nmethod*) |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1697 Atomic::cmpxchg_ptr(NMETHOD_SENTINEL, &_oops_do_mark_link, NULL); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1698 if (observed_mark_link == NULL) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1699 |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1700 // Atomically append this nmethod (now claimed) to the head of the list: |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1701 nmethod* observed_mark_nmethods = _oops_do_mark_nmethods; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1702 for (;;) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1703 nmethod* required_mark_nmethods = observed_mark_nmethods; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1704 _oops_do_mark_link = required_mark_nmethods; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1705 observed_mark_nmethods = (nmethod*) |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1706 Atomic::cmpxchg_ptr(this, &_oops_do_mark_nmethods, required_mark_nmethods); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1707 if (observed_mark_nmethods == required_mark_nmethods) |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1708 break; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1709 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1710 // Mark was clear when we first saw this guy. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1711 NOT_PRODUCT(if (TraceScavenge) print_on(tty, "oops_do, mark\n")); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1712 return false; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1713 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1714 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1715 // On fall through, another racing thread marked this nmethod before we did. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1716 return true; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1717 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1718 |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1719 void nmethod::oops_do_marking_prologue() { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1720 NOT_PRODUCT(if (TraceScavenge) tty->print_cr("[oops_do_marking_prologue")); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1721 assert(_oops_do_mark_nmethods == NULL, "must not call oops_do_marking_prologue twice in a row"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1722 // We use cmpxchg_ptr instead of regular assignment here because the user |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1723 // may fork a bunch of threads, and we need them all to see the same state. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1724 void* observed = Atomic::cmpxchg_ptr(NMETHOD_SENTINEL, &_oops_do_mark_nmethods, NULL); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1725 guarantee(observed == NULL, "no races in this sequential code"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1726 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1727 |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1728 void nmethod::oops_do_marking_epilogue() { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1729 assert(_oops_do_mark_nmethods != NULL, "must not call oops_do_marking_epilogue twice in a row"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1730 nmethod* cur = _oops_do_mark_nmethods; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1731 while (cur != NMETHOD_SENTINEL) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1732 assert(cur != NULL, "not NULL-terminated"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1733 nmethod* next = cur->_oops_do_mark_link; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1734 cur->_oops_do_mark_link = NULL; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1735 NOT_PRODUCT(if (TraceScavenge) cur->print_on(tty, "oops_do, unmark\n")); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1736 cur = next; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1737 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1738 void* required = _oops_do_mark_nmethods; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1739 void* observed = Atomic::cmpxchg_ptr(NULL, &_oops_do_mark_nmethods, required); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1740 guarantee(observed == required, "no races in this sequential code"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1741 NOT_PRODUCT(if (TraceScavenge) tty->print_cr("oops_do_marking_epilogue]")); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1742 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1743 |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1744 class DetectScavengeRoot: public OopClosure { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1745 bool _detected_scavenge_root; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1746 public: |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1747 DetectScavengeRoot() : _detected_scavenge_root(false) |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1748 { NOT_PRODUCT(_print_nm = NULL); } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1749 bool detected_scavenge_root() { return _detected_scavenge_root; } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1750 virtual void do_oop(oop* p) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1751 if ((*p) != NULL && (*p)->is_scavengable()) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1752 NOT_PRODUCT(maybe_print(p)); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1753 _detected_scavenge_root = true; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1754 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1755 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1756 virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1757 |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1758 #ifndef PRODUCT |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1759 nmethod* _print_nm; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1760 void maybe_print(oop* p) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1761 if (_print_nm == NULL) return; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1762 if (!_detected_scavenge_root) _print_nm->print_on(tty, "new scavenge root"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1763 tty->print_cr(""PTR_FORMAT"[offset=%d] detected non-perm oop "PTR_FORMAT" (found at "PTR_FORMAT")", |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1764 _print_nm, (int)((intptr_t)p - (intptr_t)_print_nm), |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1765 (intptr_t)(*p), (intptr_t)p); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1766 (*p)->print(); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1767 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1768 #endif //PRODUCT |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1769 }; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1770 |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1771 bool nmethod::detect_scavenge_root_oops() { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1772 DetectScavengeRoot detect_scavenge_root; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1773 NOT_PRODUCT(if (TraceScavenge) detect_scavenge_root._print_nm = this); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1774 oops_do(&detect_scavenge_root); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1775 return detect_scavenge_root.detected_scavenge_root(); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1776 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
1777 |
0 | 1778 // Method that knows how to preserve outgoing arguments at call. This method must be |
1779 // called with a frame corresponding to a Java invoke | |
1780 void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { | |
1692 | 1781 #ifndef SHARK |
0 | 1782 if (!method()->is_native()) { |
1783 SimpleScopeDesc ssd(this, fr.pc()); | |
1784 Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci()); | |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1135
diff
changeset
|
1785 bool has_receiver = call->has_receiver(); |
0 | 1786 symbolOop signature = call->signature(); |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1135
diff
changeset
|
1787 fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f); |
0 | 1788 } |
1692 | 1789 #endif // !SHARK |
0 | 1790 } |
1791 | |
1792 | |
1793 oop nmethod::embeddedOop_at(u_char* p) { | |
1794 RelocIterator iter(this, p, p + oopSize); | |
1795 while (iter.next()) | |
1796 if (iter.type() == relocInfo::oop_type) { | |
1797 return iter.oop_reloc()->oop_value(); | |
1798 } | |
1799 return NULL; | |
1800 } | |
1801 | |
1802 | |
1803 inline bool includes(void* p, void* from, void* to) { | |
1804 return from <= p && p < to; | |
1805 } | |
1806 | |
1807 | |
1808 void nmethod::copy_scopes_pcs(PcDesc* pcs, int count) { | |
1809 assert(count >= 2, "must be sentinel values, at least"); | |
1810 | |
1811 #ifdef ASSERT | |
1812 // must be sorted and unique; we do a binary search in find_pc_desc() | |
1813 int prev_offset = pcs[0].pc_offset(); | |
1814 assert(prev_offset == PcDesc::lower_offset_limit, | |
1815 "must start with a sentinel"); | |
1816 for (int i = 1; i < count; i++) { | |
1817 int this_offset = pcs[i].pc_offset(); | |
1818 assert(this_offset > prev_offset, "offsets must be sorted"); | |
1819 prev_offset = this_offset; | |
1820 } | |
1821 assert(prev_offset == PcDesc::upper_offset_limit, | |
1822 "must end with a sentinel"); | |
1823 #endif //ASSERT | |
1824 | |
1135
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
1825 // Search for MethodHandle invokes and tag the nmethod. |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
1826 for (int i = 0; i < count; i++) { |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
1827 if (pcs[i].is_method_handle_invoke()) { |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
1828 set_has_method_handle_invokes(true); |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
1829 break; |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
1830 } |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
1831 } |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
1832 |
0 | 1833 int size = count * sizeof(PcDesc); |
1834 assert(scopes_pcs_size() >= size, "oob"); | |
1835 memcpy(scopes_pcs_begin(), pcs, size); | |
1836 | |
1837 // Adjust the final sentinel downward. | |
1838 PcDesc* last_pc = &scopes_pcs_begin()[count-1]; | |
1839 assert(last_pc->pc_offset() == PcDesc::upper_offset_limit, "sanity"); | |
1840 last_pc->set_pc_offset(instructions_size() + 1); | |
1841 for (; last_pc + 1 < scopes_pcs_end(); last_pc += 1) { | |
1842 // Fill any rounding gaps with copies of the last record. | |
1843 last_pc[1] = last_pc[0]; | |
1844 } | |
1845 // The following assert could fail if sizeof(PcDesc) is not | |
1846 // an integral multiple of oopSize (the rounding term). | |
1847 // If it fails, change the logic to always allocate a multiple | |
1848 // of sizeof(PcDesc), and fill unused words with copies of *last_pc. | |
1849 assert(last_pc + 1 == scopes_pcs_end(), "must match exactly"); | |
1850 } | |
1851 | |
1852 void nmethod::copy_scopes_data(u_char* buffer, int size) { | |
1853 assert(scopes_data_size() >= size, "oob"); | |
1854 memcpy(scopes_data_begin(), buffer, size); | |
1855 } | |
1856 | |
1857 | |
1858 #ifdef ASSERT | |
1859 static PcDesc* linear_search(nmethod* nm, int pc_offset, bool approximate) { | |
1860 PcDesc* lower = nm->scopes_pcs_begin(); | |
1861 PcDesc* upper = nm->scopes_pcs_end(); | |
1862 lower += 1; // exclude initial sentinel | |
1863 PcDesc* res = NULL; | |
1864 for (PcDesc* p = lower; p < upper; p++) { | |
1865 NOT_PRODUCT(--nmethod_stats.pc_desc_tests); // don't count this call to match_desc | |
1866 if (match_desc(p, pc_offset, approximate)) { | |
1867 if (res == NULL) | |
1868 res = p; | |
1869 else | |
1870 res = (PcDesc*) badAddress; | |
1871 } | |
1872 } | |
1873 return res; | |
1874 } | |
1875 #endif | |
1876 | |
1877 | |
1878 // Finds a PcDesc with real-pc equal to "pc" | |
1879 PcDesc* nmethod::find_pc_desc_internal(address pc, bool approximate) { | |
1880 address base_address = instructions_begin(); | |
1881 if ((pc < base_address) || | |
1882 (pc - base_address) >= (ptrdiff_t) PcDesc::upper_offset_limit) { | |
1883 return NULL; // PC is wildly out of range | |
1884 } | |
1885 int pc_offset = (int) (pc - base_address); | |
1886 | |
1887 // Check the PcDesc cache if it contains the desired PcDesc | |
1888 // (This as an almost 100% hit rate.) | |
1889 PcDesc* res = _pc_desc_cache.find_pc_desc(pc_offset, approximate); | |
1890 if (res != NULL) { | |
1891 assert(res == linear_search(this, pc_offset, approximate), "cache ok"); | |
1892 return res; | |
1893 } | |
1894 | |
1895 // Fallback algorithm: quasi-linear search for the PcDesc | |
1896 // Find the last pc_offset less than the given offset. | |
1897 // The successor must be the required match, if there is a match at all. | |
1898 // (Use a fixed radix to avoid expensive affine pointer arithmetic.) | |
1899 PcDesc* lower = scopes_pcs_begin(); | |
1900 PcDesc* upper = scopes_pcs_end(); | |
1901 upper -= 1; // exclude final sentinel | |
1902 if (lower >= upper) return NULL; // native method; no PcDescs at all | |
1903 | |
1904 #define assert_LU_OK \ | |
1905 /* invariant on lower..upper during the following search: */ \ | |
1906 assert(lower->pc_offset() < pc_offset, "sanity"); \ | |
1907 assert(upper->pc_offset() >= pc_offset, "sanity") | |
1908 assert_LU_OK; | |
1909 | |
1910 // Use the last successful return as a split point. | |
1911 PcDesc* mid = _pc_desc_cache.last_pc_desc(); | |
1912 NOT_PRODUCT(++nmethod_stats.pc_desc_searches); | |
1913 if (mid->pc_offset() < pc_offset) { | |
1914 lower = mid; | |
1915 } else { | |
1916 upper = mid; | |
1917 } | |
1918 | |
1919 // Take giant steps at first (4096, then 256, then 16, then 1) | |
1920 const int LOG2_RADIX = 4 /*smaller steps in debug mode:*/ debug_only(-1); | |
1921 const int RADIX = (1 << LOG2_RADIX); | |
1922 for (int step = (1 << (LOG2_RADIX*3)); step > 1; step >>= LOG2_RADIX) { | |
1923 while ((mid = lower + step) < upper) { | |
1924 assert_LU_OK; | |
1925 NOT_PRODUCT(++nmethod_stats.pc_desc_searches); | |
1926 if (mid->pc_offset() < pc_offset) { | |
1927 lower = mid; | |
1928 } else { | |
1929 upper = mid; | |
1930 break; | |
1931 } | |
1932 } | |
1933 assert_LU_OK; | |
1934 } | |
1935 | |
1936 // Sneak up on the value with a linear search of length ~16. | |
1937 while (true) { | |
1938 assert_LU_OK; | |
1939 mid = lower + 1; | |
1940 NOT_PRODUCT(++nmethod_stats.pc_desc_searches); | |
1941 if (mid->pc_offset() < pc_offset) { | |
1942 lower = mid; | |
1943 } else { | |
1944 upper = mid; | |
1945 break; | |
1946 } | |
1947 } | |
1948 #undef assert_LU_OK | |
1949 | |
1950 if (match_desc(upper, pc_offset, approximate)) { | |
1951 assert(upper == linear_search(this, pc_offset, approximate), "search ok"); | |
1952 _pc_desc_cache.add_pc_desc(upper); | |
1953 return upper; | |
1954 } else { | |
1955 assert(NULL == linear_search(this, pc_offset, approximate), "search ok"); | |
1956 return NULL; | |
1957 } | |
1958 } | |
1959 | |
1960 | |
1961 bool nmethod::check_all_dependencies() { | |
1962 bool found_check = false; | |
1963 // wholesale check of all dependencies | |
1964 for (Dependencies::DepStream deps(this); deps.next(); ) { | |
1965 if (deps.check_dependency() != NULL) { | |
1966 found_check = true; | |
1967 NOT_DEBUG(break); | |
1968 } | |
1969 } | |
1970 return found_check; // tell caller if we found anything | |
1971 } | |
1972 | |
1973 bool nmethod::check_dependency_on(DepChange& changes) { | |
1974 // What has happened: | |
1975 // 1) a new class dependee has been added | |
1976 // 2) dependee and all its super classes have been marked | |
1977 bool found_check = false; // set true if we are upset | |
1978 for (Dependencies::DepStream deps(this); deps.next(); ) { | |
1979 // Evaluate only relevant dependencies. | |
1980 if (deps.spot_check_dependency_at(changes) != NULL) { | |
1981 found_check = true; | |
1982 NOT_DEBUG(break); | |
1983 } | |
1984 } | |
1985 return found_check; | |
1986 } | |
1987 | |
1988 bool nmethod::is_evol_dependent_on(klassOop dependee) { | |
1989 instanceKlass *dependee_ik = instanceKlass::cast(dependee); | |
1990 objArrayOop dependee_methods = dependee_ik->methods(); | |
1991 for (Dependencies::DepStream deps(this); deps.next(); ) { | |
1992 if (deps.type() == Dependencies::evol_method) { | |
1993 methodOop method = deps.method_argument(0); | |
1994 for (int j = 0; j < dependee_methods->length(); j++) { | |
1995 if ((methodOop) dependee_methods->obj_at(j) == method) { | |
1996 // RC_TRACE macro has an embedded ResourceMark | |
1997 RC_TRACE(0x01000000, | |
1998 ("Found evol dependency of nmethod %s.%s(%s) compile_id=%d on method %s.%s(%s)", | |
1999 _method->method_holder()->klass_part()->external_name(), | |
2000 _method->name()->as_C_string(), | |
2001 _method->signature()->as_C_string(), compile_id(), | |
2002 method->method_holder()->klass_part()->external_name(), | |
2003 method->name()->as_C_string(), | |
2004 method->signature()->as_C_string())); | |
2005 if (TraceDependencies || LogCompilation) | |
2006 deps.log_dependency(dependee); | |
2007 return true; | |
2008 } | |
2009 } | |
2010 } | |
2011 } | |
2012 return false; | |
2013 } | |
2014 | |
2015 // Called from mark_for_deoptimization, when dependee is invalidated. | |
2016 bool nmethod::is_dependent_on_method(methodOop dependee) { | |
2017 for (Dependencies::DepStream deps(this); deps.next(); ) { | |
2018 if (deps.type() != Dependencies::evol_method) | |
2019 continue; | |
2020 methodOop method = deps.method_argument(0); | |
2021 if (method == dependee) return true; | |
2022 } | |
2023 return false; | |
2024 } | |
2025 | |
2026 | |
2027 bool nmethod::is_patchable_at(address instr_addr) { | |
2028 assert (code_contains(instr_addr), "wrong nmethod used"); | |
2029 if (is_zombie()) { | |
2030 // a zombie may never be patched | |
2031 return false; | |
2032 } | |
2033 return true; | |
2034 } | |
2035 | |
2036 | |
2037 address nmethod::continuation_for_implicit_exception(address pc) { | |
2038 // Exception happened outside inline-cache check code => we are inside | |
2039 // an active nmethod => use cpc to determine a return address | |
2040 int exception_offset = pc - instructions_begin(); | |
2041 int cont_offset = ImplicitExceptionTable(this).at( exception_offset ); | |
2042 #ifdef ASSERT | |
2043 if (cont_offset == 0) { | |
2044 Thread* thread = ThreadLocalStorage::get_thread_slow(); | |
2045 ResetNoHandleMark rnm; // Might be called from LEAF/QUICK ENTRY | |
2046 HandleMark hm(thread); | |
2047 ResourceMark rm(thread); | |
2048 CodeBlob* cb = CodeCache::find_blob(pc); | |
2049 assert(cb != NULL && cb == this, ""); | |
2050 tty->print_cr("implicit exception happened at " INTPTR_FORMAT, pc); | |
2051 print(); | |
2052 method()->print_codes(); | |
2053 print_code(); | |
2054 print_pcs(); | |
2055 } | |
2056 #endif | |
1250 | 2057 if (cont_offset == 0) { |
2058 // Let the normal error handling report the exception | |
2059 return NULL; | |
2060 } | |
0 | 2061 return instructions_begin() + cont_offset; |
2062 } | |
2063 | |
2064 | |
2065 | |
2066 void nmethod_init() { | |
2067 // make sure you didn't forget to adjust the filler fields | |
2068 assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word"); | |
2069 } | |
2070 | |
2071 | |
2072 //------------------------------------------------------------------------------------------- | |
2073 | |
2074 | |
2075 // QQQ might we make this work from a frame?? | |
2076 nmethodLocker::nmethodLocker(address pc) { | |
2077 CodeBlob* cb = CodeCache::find_blob(pc); | |
2078 guarantee(cb != NULL && cb->is_nmethod(), "bad pc for a nmethod found"); | |
2079 _nm = (nmethod*)cb; | |
2080 lock_nmethod(_nm); | |
2081 } | |
2082 | |
2083 void nmethodLocker::lock_nmethod(nmethod* nm) { | |
2084 if (nm == NULL) return; | |
2085 Atomic::inc(&nm->_lock_count); | |
2086 guarantee(!nm->is_zombie(), "cannot lock a zombie method"); | |
2087 } | |
2088 | |
2089 void nmethodLocker::unlock_nmethod(nmethod* nm) { | |
2090 if (nm == NULL) return; | |
2091 Atomic::dec(&nm->_lock_count); | |
2092 guarantee(nm->_lock_count >= 0, "unmatched nmethod lock/unlock"); | |
2093 } | |
2094 | |
1204 | 2095 |
2096 // ----------------------------------------------------------------------------- | |
2097 // nmethod::get_deopt_original_pc | |
2098 // | |
2099 // Return the original PC for the given PC if: | |
2100 // (a) the given PC belongs to a nmethod and | |
2101 // (b) it is a deopt PC | |
2102 address nmethod::get_deopt_original_pc(const frame* fr) { | |
2103 if (fr->cb() == NULL) return NULL; | |
2104 | |
2105 nmethod* nm = fr->cb()->as_nmethod_or_null(); | |
2106 if (nm != NULL && nm->is_deopt_pc(fr->pc())) | |
2107 return nm->get_original_pc(fr); | |
2108 | |
2109 return NULL; | |
0 | 2110 } |
2111 | |
2112 | |
2113 // ----------------------------------------------------------------------------- | |
1135
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2114 // MethodHandle |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2115 |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2116 bool nmethod::is_method_handle_return(address return_pc) { |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2117 if (!has_method_handle_invokes()) return false; |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2118 PcDesc* pd = pc_desc_at(return_pc); |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2119 if (pd == NULL) |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2120 return false; |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2121 return pd->is_method_handle_invoke(); |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2122 } |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2123 |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2124 |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1109
diff
changeset
|
2125 // ----------------------------------------------------------------------------- |
0 | 2126 // Verification |
2127 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2128 class VerifyOopsClosure: public OopClosure { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2129 nmethod* _nm; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2130 bool _ok; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2131 public: |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2132 VerifyOopsClosure(nmethod* nm) : _nm(nm), _ok(true) { } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2133 bool ok() { return _ok; } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2134 virtual void do_oop(oop* p) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2135 if ((*p) == NULL || (*p)->is_oop()) return; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2136 if (_ok) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2137 _nm->print_nmethod(true); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2138 _ok = false; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2139 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2140 tty->print_cr("*** non-oop "PTR_FORMAT" found at "PTR_FORMAT" (offset %d)", |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2141 (intptr_t)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm)); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2142 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2143 virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2144 }; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2145 |
0 | 2146 void nmethod::verify() { |
2147 | |
2148 // Hmm. OSR methods can be deopted but not marked as zombie or not_entrant | |
2149 // seems odd. | |
2150 | |
2151 if( is_zombie() || is_not_entrant() ) | |
2152 return; | |
2153 | |
2154 // Make sure all the entry points are correctly aligned for patching. | |
2155 NativeJump::check_verified_entry_alignment(entry_point(), verified_entry_point()); | |
2156 | |
2157 assert(method()->is_oop(), "must be valid"); | |
2158 | |
2159 ResourceMark rm; | |
2160 | |
2161 if (!CodeCache::contains(this)) { | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
1489
diff
changeset
|
2162 fatal(err_msg("nmethod at " INTPTR_FORMAT " not in zone", this)); |
0 | 2163 } |
2164 | |
2165 if(is_native_method() ) | |
2166 return; | |
2167 | |
2168 nmethod* nm = CodeCache::find_nmethod(verified_entry_point()); | |
2169 if (nm != this) { | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
1489
diff
changeset
|
2170 fatal(err_msg("findNMethod did not find this nmethod (" INTPTR_FORMAT ")", |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
1489
diff
changeset
|
2171 this)); |
0 | 2172 } |
2173 | |
2174 for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) { | |
2175 if (! p->verify(this)) { | |
2176 tty->print_cr("\t\tin nmethod at " INTPTR_FORMAT " (pcs)", this); | |
2177 } | |
2178 } | |
2179 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2180 VerifyOopsClosure voc(this); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2181 oops_do(&voc); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2182 assert(voc.ok(), "embedded oops must be OK"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2183 verify_scavenge_root_oops(); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2184 |
0 | 2185 verify_scopes(); |
2186 } | |
2187 | |
2188 | |
2189 void nmethod::verify_interrupt_point(address call_site) { | |
2190 // This code does not work in release mode since | |
2191 // owns_lock only is available in debug mode. | |
2192 CompiledIC* ic = NULL; | |
2193 Thread *cur = Thread::current(); | |
2194 if (CompiledIC_lock->owner() == cur || | |
2195 ((cur->is_VM_thread() || cur->is_ConcurrentGC_thread()) && | |
2196 SafepointSynchronize::is_at_safepoint())) { | |
2197 ic = CompiledIC_at(call_site); | |
2198 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); | |
2199 } else { | |
2200 MutexLocker ml_verify (CompiledIC_lock); | |
2201 ic = CompiledIC_at(call_site); | |
2202 } | |
2203 PcDesc* pd = pc_desc_at(ic->end_of_call()); | |
2204 assert(pd != NULL, "PcDesc must exist"); | |
2205 for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(), | |
1253
f70b0d9ab095
6910618: C2: Error: assert(d->is_oop(),"JVM_ArrayCopy: dst not an oop")
kvn
parents:
1250
diff
changeset
|
2206 pd->obj_decode_offset(), pd->should_reexecute(), |
f70b0d9ab095
6910618: C2: Error: assert(d->is_oop(),"JVM_ArrayCopy: dst not an oop")
kvn
parents:
1250
diff
changeset
|
2207 pd->return_oop()); |
0 | 2208 !sd->is_top(); sd = sd->sender()) { |
2209 sd->verify(); | |
2210 } | |
2211 } | |
2212 | |
2213 void nmethod::verify_scopes() { | |
2214 if( !method() ) return; // Runtime stubs have no scope | |
2215 if (method()->is_native()) return; // Ignore stub methods. | |
2216 // iterate through all interrupt point | |
2217 // and verify the debug information is valid. | |
2218 RelocIterator iter((nmethod*)this); | |
2219 while (iter.next()) { | |
2220 address stub = NULL; | |
2221 switch (iter.type()) { | |
2222 case relocInfo::virtual_call_type: | |
2223 verify_interrupt_point(iter.addr()); | |
2224 break; | |
2225 case relocInfo::opt_virtual_call_type: | |
2226 stub = iter.opt_virtual_call_reloc()->static_stub(); | |
2227 verify_interrupt_point(iter.addr()); | |
2228 break; | |
2229 case relocInfo::static_call_type: | |
2230 stub = iter.static_call_reloc()->static_stub(); | |
2231 //verify_interrupt_point(iter.addr()); | |
2232 break; | |
2233 case relocInfo::runtime_call_type: | |
2234 address destination = iter.reloc()->value(); | |
2235 // Right now there is no way to find out which entries support | |
2236 // an interrupt point. It would be nice if we had this | |
2237 // information in a table. | |
2238 break; | |
2239 } | |
2240 assert(stub == NULL || stub_contains(stub), "static call stub outside stub section"); | |
2241 } | |
2242 } | |
2243 | |
2244 | |
2245 // ----------------------------------------------------------------------------- | |
2246 // Non-product code | |
2247 #ifndef PRODUCT | |
2248 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2249 class DebugScavengeRoot: public OopClosure { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2250 nmethod* _nm; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2251 bool _ok; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2252 public: |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2253 DebugScavengeRoot(nmethod* nm) : _nm(nm), _ok(true) { } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2254 bool ok() { return _ok; } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2255 virtual void do_oop(oop* p) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2256 if ((*p) == NULL || !(*p)->is_scavengable()) return; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2257 if (_ok) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2258 _nm->print_nmethod(true); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2259 _ok = false; |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2260 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2261 tty->print_cr("*** non-perm oop "PTR_FORMAT" found at "PTR_FORMAT" (offset %d)", |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2262 (intptr_t)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm)); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2263 (*p)->print(); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2264 } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2265 virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2266 }; |
0 | 2267 |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2268 void nmethod::verify_scavenge_root_oops() { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2269 if (!on_scavenge_root_list()) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2270 // Actually look inside, to verify the claim that it's clean. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2271 DebugScavengeRoot debug_scavenge_root(this); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2272 oops_do(&debug_scavenge_root); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2273 if (!debug_scavenge_root.ok()) |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2274 fatal("found an unadvertised bad non-perm oop in the code cache"); |
0 | 2275 } |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2276 assert(scavenge_root_not_marked(), ""); |
0 | 2277 } |
2278 | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2279 #endif // PRODUCT |
0 | 2280 |
2281 // Printing operations | |
2282 | |
2283 void nmethod::print() const { | |
2284 ResourceMark rm; | |
2285 ttyLocker ttyl; // keep the following output all in one block | |
2286 | |
2287 tty->print("Compiled "); | |
2288 | |
2289 if (is_compiled_by_c1()) { | |
2290 tty->print("(c1) "); | |
2291 } else if (is_compiled_by_c2()) { | |
2292 tty->print("(c2) "); | |
1692 | 2293 } else if (is_compiled_by_shark()) { |
2294 tty->print("(shark) "); | |
0 | 2295 } else { |
2296 tty->print("(nm) "); | |
2297 } | |
2298 | |
2299 print_on(tty, "nmethod"); | |
2300 tty->cr(); | |
2301 if (WizardMode) { | |
2302 tty->print("((nmethod*) "INTPTR_FORMAT ") ", this); | |
2303 tty->print(" for method " INTPTR_FORMAT , (address)method()); | |
2304 tty->print(" { "); | |
2305 if (is_in_use()) tty->print("in_use "); | |
2306 if (is_not_entrant()) tty->print("not_entrant "); | |
2307 if (is_zombie()) tty->print("zombie "); | |
2308 if (is_unloaded()) tty->print("unloaded "); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
2309 if (on_scavenge_root_list()) tty->print("scavenge_root "); |
0 | 2310 tty->print_cr("}:"); |
2311 } | |
2312 if (size () > 0) tty->print_cr(" total in heap [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", | |
2313 (address)this, | |
2314 (address)this + size(), | |
2315 size()); | |
2316 if (relocation_size () > 0) tty->print_cr(" relocation [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", | |
2317 relocation_begin(), | |
2318 relocation_end(), | |
2319 relocation_size()); | |
2320 if (code_size () > 0) tty->print_cr(" main code [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", | |
2321 code_begin(), | |
2322 code_end(), | |
2323 code_size()); | |
2324 if (stub_size () > 0) tty->print_cr(" stub code [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", | |
2325 stub_begin(), | |
2326 stub_end(), | |
2327 stub_size()); | |
2328 if (consts_size () > 0) tty->print_cr(" constants [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", | |
2329 consts_begin(), | |
2330 consts_end(), | |
2331 consts_size()); | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
2332 if (oops_size () > 0) tty->print_cr(" oops [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
2333 oops_begin(), |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
2334 oops_end(), |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
1538
diff
changeset
|
2335 oops_size()); |
0 | 2336 if (scopes_data_size () > 0) tty->print_cr(" scopes data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", |
2337 scopes_data_begin(), | |
2338 scopes_data_end(), | |
2339 scopes_data_size()); | |
2340 if (scopes_pcs_size () > 0) tty->print_cr(" scopes pcs [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", | |
2341 scopes_pcs_begin(), | |
2342 scopes_pcs_end(), | |
2343 scopes_pcs_size()); | |
2344 if (dependencies_size () > 0) tty->print_cr(" dependencies [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", | |
2345 dependencies_begin(), | |
2346 dependencies_end(), | |
2347 dependencies_size()); | |
2348 if (handler_table_size() > 0) tty->print_cr(" handler table [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", | |
2349 handler_table_begin(), | |
2350 handler_table_end(), | |
2351 handler_table_size()); | |
2352 if (nul_chk_table_size() > 0) tty->print_cr(" nul chk table [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", | |
2353 nul_chk_table_begin(), | |
2354 nul_chk_table_end(), | |
2355 nul_chk_table_size()); | |
2356 if (oops_size () > 0) tty->print_cr(" oops [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", | |
2357 oops_begin(), | |
2358 oops_end(), | |
2359 oops_size()); | |
2360 } | |
2361 | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2362 void nmethod::print_code() { |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2363 HandleMark hm; |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2364 ResourceMark m; |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2365 Disassembler::decode(this); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2366 } |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2367 |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2368 |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2369 #ifndef PRODUCT |
0 | 2370 |
2371 void nmethod::print_scopes() { | |
2372 // Find the first pc desc for all scopes in the code and print it. | |
2373 ResourceMark rm; | |
2374 for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) { | |
2375 if (p->scope_decode_offset() == DebugInformationRecorder::serialized_null) | |
2376 continue; | |
2377 | |
2378 ScopeDesc* sd = scope_desc_at(p->real_pc(this)); | |
2379 sd->print_on(tty, p); | |
2380 } | |
2381 } | |
2382 | |
2383 void nmethod::print_dependencies() { | |
2384 ResourceMark rm; | |
2385 ttyLocker ttyl; // keep the following output all in one block | |
2386 tty->print_cr("Dependencies:"); | |
2387 for (Dependencies::DepStream deps(this); deps.next(); ) { | |
2388 deps.print_dependency(); | |
2389 klassOop ctxk = deps.context_type(); | |
2390 if (ctxk != NULL) { | |
2391 Klass* k = Klass::cast(ctxk); | |
2392 if (k->oop_is_instance() && ((instanceKlass*)k)->is_dependent_nmethod(this)) { | |
30 | 2393 tty->print_cr(" [nmethod<=klass]%s", k->external_name()); |
0 | 2394 } |
2395 } | |
2396 deps.log_dependency(); // put it into the xml log also | |
2397 } | |
2398 } | |
2399 | |
2400 | |
2401 void nmethod::print_relocations() { | |
2402 ResourceMark m; // in case methods get printed via the debugger | |
2403 tty->print_cr("relocations:"); | |
2404 RelocIterator iter(this); | |
2405 iter.print(); | |
2406 if (UseRelocIndex) { | |
2407 jint* index_end = (jint*)relocation_end() - 1; | |
2408 jint index_size = *index_end; | |
2409 jint* index_start = (jint*)( (address)index_end - index_size ); | |
2410 tty->print_cr(" index @" INTPTR_FORMAT ": index_size=%d", index_start, index_size); | |
2411 if (index_size > 0) { | |
2412 jint* ip; | |
2413 for (ip = index_start; ip+2 <= index_end; ip += 2) | |
2414 tty->print_cr(" (%d %d) addr=" INTPTR_FORMAT " @" INTPTR_FORMAT, | |
2415 ip[0], | |
2416 ip[1], | |
2417 header_end()+ip[0], | |
2418 relocation_begin()-1+ip[1]); | |
2419 for (; ip < index_end; ip++) | |
2420 tty->print_cr(" (%d ?)", ip[0]); | |
2421 tty->print_cr(" @" INTPTR_FORMAT ": index_size=%d", ip, *ip++); | |
2422 tty->print_cr("reloc_end @" INTPTR_FORMAT ":", ip); | |
2423 } | |
2424 } | |
2425 } | |
2426 | |
2427 | |
2428 void nmethod::print_pcs() { | |
2429 ResourceMark m; // in case methods get printed via debugger | |
2430 tty->print_cr("pc-bytecode offsets:"); | |
2431 for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) { | |
2432 p->print(this); | |
2433 } | |
2434 } | |
2435 | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2436 #endif // PRODUCT |
0 | 2437 |
2438 const char* nmethod::reloc_string_for(u_char* begin, u_char* end) { | |
2439 RelocIterator iter(this, begin, end); | |
2440 bool have_one = false; | |
2441 while (iter.next()) { | |
2442 have_one = true; | |
2443 switch (iter.type()) { | |
2444 case relocInfo::none: return "no_reloc"; | |
2445 case relocInfo::oop_type: { | |
2446 stringStream st; | |
2447 oop_Relocation* r = iter.oop_reloc(); | |
2448 oop obj = r->oop_value(); | |
2449 st.print("oop("); | |
2450 if (obj == NULL) st.print("NULL"); | |
2451 else obj->print_value_on(&st); | |
2452 st.print(")"); | |
2453 return st.as_string(); | |
2454 } | |
2455 case relocInfo::virtual_call_type: return "virtual_call"; | |
2456 case relocInfo::opt_virtual_call_type: return "optimized virtual_call"; | |
2457 case relocInfo::static_call_type: return "static_call"; | |
2458 case relocInfo::static_stub_type: return "static_stub"; | |
2459 case relocInfo::runtime_call_type: return "runtime_call"; | |
2460 case relocInfo::external_word_type: return "external_word"; | |
2461 case relocInfo::internal_word_type: return "internal_word"; | |
2462 case relocInfo::section_word_type: return "section_word"; | |
2463 case relocInfo::poll_type: return "poll"; | |
2464 case relocInfo::poll_return_type: return "poll_return"; | |
2465 case relocInfo::type_mask: return "type_bit_mask"; | |
2466 } | |
2467 } | |
2468 return have_one ? "other" : NULL; | |
2469 } | |
2470 | |
2471 // Return a the last scope in (begin..end] | |
2472 ScopeDesc* nmethod::scope_desc_in(address begin, address end) { | |
2473 PcDesc* p = pc_desc_near(begin+1); | |
2474 if (p != NULL && p->real_pc(this) <= end) { | |
2475 return new ScopeDesc(this, p->scope_decode_offset(), | |
1253
f70b0d9ab095
6910618: C2: Error: assert(d->is_oop(),"JVM_ArrayCopy: dst not an oop")
kvn
parents:
1250
diff
changeset
|
2476 p->obj_decode_offset(), p->should_reexecute(), |
f70b0d9ab095
6910618: C2: Error: assert(d->is_oop(),"JVM_ArrayCopy: dst not an oop")
kvn
parents:
1250
diff
changeset
|
2477 p->return_oop()); |
0 | 2478 } |
2479 return NULL; | |
2480 } | |
2481 | |
1155
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2482 void nmethod::print_nmethod_labels(outputStream* stream, address block_begin) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2483 if (block_begin == entry_point()) stream->print_cr("[Entry Point]"); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2484 if (block_begin == verified_entry_point()) stream->print_cr("[Verified Entry Point]"); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2485 if (block_begin == exception_begin()) stream->print_cr("[Exception Handler]"); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2486 if (block_begin == stub_begin()) stream->print_cr("[Stub Code]"); |
1204 | 2487 if (block_begin == deopt_handler_begin()) stream->print_cr("[Deopt Handler Code]"); |
1691
4a665be40fd3
6975855: don't emit deopt MH handler in C1 if not required
twisti
parents:
1644
diff
changeset
|
2488 |
4a665be40fd3
6975855: don't emit deopt MH handler in C1 if not required
twisti
parents:
1644
diff
changeset
|
2489 if (has_method_handle_invokes()) |
4a665be40fd3
6975855: don't emit deopt MH handler in C1 if not required
twisti
parents:
1644
diff
changeset
|
2490 if (block_begin == deopt_mh_handler_begin()) stream->print_cr("[Deopt MH Handler Code]"); |
4a665be40fd3
6975855: don't emit deopt MH handler in C1 if not required
twisti
parents:
1644
diff
changeset
|
2491 |
1155
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2492 if (block_begin == consts_begin()) stream->print_cr("[Constants]"); |
1691
4a665be40fd3
6975855: don't emit deopt MH handler in C1 if not required
twisti
parents:
1644
diff
changeset
|
2493 |
1155
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2494 if (block_begin == entry_point()) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2495 methodHandle m = method(); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2496 if (m.not_null()) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2497 stream->print(" # "); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2498 m->print_value_on(stream); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2499 stream->cr(); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2500 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2501 if (m.not_null() && !is_osr_method()) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2502 ResourceMark rm; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2503 int sizeargs = m->size_of_parameters(); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2504 BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, sizeargs); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2505 VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, sizeargs); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2506 { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2507 int sig_index = 0; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2508 if (!m->is_static()) |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2509 sig_bt[sig_index++] = T_OBJECT; // 'this' |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2510 for (SignatureStream ss(m->signature()); !ss.at_return_type(); ss.next()) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2511 BasicType t = ss.type(); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2512 sig_bt[sig_index++] = t; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2513 if (type2size[t] == 2) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2514 sig_bt[sig_index++] = T_VOID; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2515 } else { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2516 assert(type2size[t] == 1, "size is 1 or 2"); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2517 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2518 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2519 assert(sig_index == sizeargs, ""); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2520 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2521 const char* spname = "sp"; // make arch-specific? |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2522 intptr_t out_preserve = SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs, false); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2523 int stack_slot_offset = this->frame_size() * wordSize; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2524 int tab1 = 14, tab2 = 24; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2525 int sig_index = 0; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2526 int arg_index = (m->is_static() ? 0 : -1); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2527 bool did_old_sp = false; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2528 for (SignatureStream ss(m->signature()); !ss.at_return_type(); ) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2529 bool at_this = (arg_index == -1); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2530 bool at_old_sp = false; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2531 BasicType t = (at_this ? T_OBJECT : ss.type()); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2532 assert(t == sig_bt[sig_index], "sigs in sync"); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2533 if (at_this) |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2534 stream->print(" # this: "); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2535 else |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2536 stream->print(" # parm%d: ", arg_index); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2537 stream->move_to(tab1); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2538 VMReg fst = regs[sig_index].first(); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2539 VMReg snd = regs[sig_index].second(); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2540 if (fst->is_reg()) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2541 stream->print("%s", fst->name()); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2542 if (snd->is_valid()) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2543 stream->print(":%s", snd->name()); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2544 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2545 } else if (fst->is_stack()) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2546 int offset = fst->reg2stack() * VMRegImpl::stack_slot_size + stack_slot_offset; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2547 if (offset == stack_slot_offset) at_old_sp = true; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2548 stream->print("[%s+0x%x]", spname, offset); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2549 } else { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2550 stream->print("reg%d:%d??", (int)(intptr_t)fst, (int)(intptr_t)snd); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2551 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2552 stream->print(" "); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2553 stream->move_to(tab2); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2554 stream->print("= "); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2555 if (at_this) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2556 m->method_holder()->print_value_on(stream); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2557 } else { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2558 bool did_name = false; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2559 if (!at_this && ss.is_object()) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2560 symbolOop name = ss.as_symbol_or_null(); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2561 if (name != NULL) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2562 name->print_value_on(stream); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2563 did_name = true; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2564 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2565 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2566 if (!did_name) |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2567 stream->print("%s", type2name(t)); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2568 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2569 if (at_old_sp) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2570 stream->print(" (%s of caller)", spname); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2571 did_old_sp = true; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2572 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2573 stream->cr(); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2574 sig_index += type2size[t]; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2575 arg_index += 1; |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2576 if (!at_this) ss.next(); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2577 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2578 if (!did_old_sp) { |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2579 stream->print(" # "); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2580 stream->move_to(tab1); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2581 stream->print("[%s+0x%x]", spname, stack_slot_offset); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2582 stream->print(" (%s of caller)", spname); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2583 stream->cr(); |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2584 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2585 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2586 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2587 } |
4e6abf09f540
6912062: disassembler plugin needs to produce symbolic information in product mode
jrose
parents:
1141
diff
changeset
|
2588 |
0 | 2589 void nmethod::print_code_comment_on(outputStream* st, int column, u_char* begin, u_char* end) { |
2590 // First, find an oopmap in (begin, end]. | |
2591 // We use the odd half-closed interval so that oop maps and scope descs | |
2592 // which are tied to the byte after a call are printed with the call itself. | |
2593 address base = instructions_begin(); | |
2594 OopMapSet* oms = oop_maps(); | |
2595 if (oms != NULL) { | |
2596 for (int i = 0, imax = oms->size(); i < imax; i++) { | |
2597 OopMap* om = oms->at(i); | |
2598 address pc = base + om->offset(); | |
2599 if (pc > begin) { | |
2600 if (pc <= end) { | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2601 st->move_to(column); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2602 st->print("; "); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2603 om->print_on(st); |
0 | 2604 } |
2605 break; | |
2606 } | |
2607 } | |
2608 } | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2609 |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2610 // Print any debug info present at this pc. |
0 | 2611 ScopeDesc* sd = scope_desc_in(begin, end); |
2612 if (sd != NULL) { | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2613 st->move_to(column); |
0 | 2614 if (sd->bci() == SynchronizationEntryBCI) { |
2615 st->print(";*synchronization entry"); | |
2616 } else { | |
2617 if (sd->method().is_null()) { | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2618 st->print("method is NULL"); |
0 | 2619 } else if (sd->method()->is_native()) { |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2620 st->print("method is native"); |
0 | 2621 } else { |
2622 address bcp = sd->method()->bcp_from(sd->bci()); | |
2623 Bytecodes::Code bc = Bytecodes::java_code_at(bcp); | |
2624 st->print(";*%s", Bytecodes::name(bc)); | |
2625 switch (bc) { | |
2626 case Bytecodes::_invokevirtual: | |
2627 case Bytecodes::_invokespecial: | |
2628 case Bytecodes::_invokestatic: | |
2629 case Bytecodes::_invokeinterface: | |
2630 { | |
2631 Bytecode_invoke* invoke = Bytecode_invoke_at(sd->method(), sd->bci()); | |
2632 st->print(" "); | |
2633 if (invoke->name() != NULL) | |
2634 invoke->name()->print_symbol_on(st); | |
2635 else | |
2636 st->print("<UNKNOWN>"); | |
2637 break; | |
2638 } | |
2639 case Bytecodes::_getfield: | |
2640 case Bytecodes::_putfield: | |
2641 case Bytecodes::_getstatic: | |
2642 case Bytecodes::_putstatic: | |
2643 { | |
1602 | 2644 Bytecode_field* field = Bytecode_field_at(sd->method(), sd->bci()); |
0 | 2645 st->print(" "); |
1602 | 2646 if (field->name() != NULL) |
2647 field->name()->print_symbol_on(st); | |
0 | 2648 else |
2649 st->print("<UNKNOWN>"); | |
2650 } | |
2651 } | |
2652 } | |
2653 } | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2654 |
0 | 2655 // Print all scopes |
2656 for (;sd != NULL; sd = sd->sender()) { | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2657 st->move_to(column); |
0 | 2658 st->print("; -"); |
2659 if (sd->method().is_null()) { | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2660 st->print("method is NULL"); |
0 | 2661 } else { |
2662 sd->method()->print_short_name(st); | |
2663 } | |
2664 int lineno = sd->method()->line_number_from_bci(sd->bci()); | |
2665 if (lineno != -1) { | |
2666 st->print("@%d (line %d)", sd->bci(), lineno); | |
2667 } else { | |
2668 st->print("@%d", sd->bci()); | |
2669 } | |
2670 st->cr(); | |
2671 } | |
2672 } | |
2673 | |
2674 // Print relocation information | |
2675 const char* str = reloc_string_for(begin, end); | |
2676 if (str != NULL) { | |
2677 if (sd != NULL) st->cr(); | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2678 st->move_to(column); |
0 | 2679 st->print("; {%s}", str); |
2680 } | |
2681 int cont_offset = ImplicitExceptionTable(this).at(begin - instructions_begin()); | |
2682 if (cont_offset != 0) { | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2683 st->move_to(column); |
0 | 2684 st->print("; implicit exception: dispatches to " INTPTR_FORMAT, instructions_begin() + cont_offset); |
2685 } | |
2686 | |
2687 } | |
2688 | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2689 #ifndef PRODUCT |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
30
diff
changeset
|
2690 |
0 | 2691 void nmethod::print_value_on(outputStream* st) const { |
2692 print_on(st, "nmethod"); | |
2693 } | |
2694 | |
2695 void nmethod::print_calls(outputStream* st) { | |
2696 RelocIterator iter(this); | |
2697 while (iter.next()) { | |
2698 switch (iter.type()) { | |
2699 case relocInfo::virtual_call_type: | |
2700 case relocInfo::opt_virtual_call_type: { | |
2701 VerifyMutexLocker mc(CompiledIC_lock); | |
2702 CompiledIC_at(iter.reloc())->print(); | |
2703 break; | |
2704 } | |
2705 case relocInfo::static_call_type: | |
2706 st->print_cr("Static call at " INTPTR_FORMAT, iter.reloc()->addr()); | |
2707 compiledStaticCall_at(iter.reloc())->print(); | |
2708 break; | |
2709 } | |
2710 } | |
2711 } | |
2712 | |
2713 void nmethod::print_handler_table() { | |
2714 ExceptionHandlerTable(this).print(); | |
2715 } | |
2716 | |
2717 void nmethod::print_nul_chk_table() { | |
2718 ImplicitExceptionTable(this).print(instructions_begin()); | |
2719 } | |
2720 | |
2721 void nmethod::print_statistics() { | |
2722 ttyLocker ttyl; | |
2723 if (xtty != NULL) xtty->head("statistics type='nmethod'"); | |
2724 nmethod_stats.print_native_nmethod_stats(); | |
2725 nmethod_stats.print_nmethod_stats(); | |
2726 DebugInformationRecorder::print_statistics(); | |
2727 nmethod_stats.print_pc_stats(); | |
2728 Dependencies::print_statistics(); | |
2729 if (xtty != NULL) xtty->tail("statistics"); | |
2730 } | |
2731 | |
2732 #endif // PRODUCT |