Mercurial > hg > truffle
annotate src/share/vm/interpreter/bytecodeTracer.cpp @ 4181:319860ae697a
Simplify FrameMap: make offsets of spill slots and outgoing parameters independent so that they can be allocated at the same time, eliminating the separate phases. This makes the separate StackBlock unnecesary. Change CiStackSlot to use byte offsets instead of spill slot index. This makes CiTarget.spillSlotSize unnecessary.
author | Christian Wimmer <Christian.Wimmer@Oracle.com> |
---|---|
date | Mon, 02 Jan 2012 14:16:08 -0800 |
parents | b20d64f83668 |
children | da91efe96a93 |
rev | line source |
---|---|
0 | 1 /* |
2142 | 2 * Copyright (c) 1997, 2011, 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:
1138
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1138
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:
1138
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "interpreter/bytecodeHistogram.hpp" | |
27 #include "interpreter/bytecodeTracer.hpp" | |
28 #include "interpreter/bytecodes.hpp" | |
29 #include "interpreter/interpreter.hpp" | |
30 #include "interpreter/interpreterRuntime.hpp" | |
31 #include "memory/resourceArea.hpp" | |
32 #include "oops/methodDataOop.hpp" | |
33 #include "oops/methodOop.hpp" | |
34 #include "runtime/mutexLocker.hpp" | |
35 #include "runtime/timer.hpp" | |
0 | 36 |
37 | |
38 #ifndef PRODUCT | |
39 | |
40 // Standard closure for BytecodeTracer: prints the current bytecode | |
41 // and its attributes using bytecode-specific information. | |
42 | |
43 class BytecodePrinter: public BytecodeClosure { | |
44 private: | |
45 // %%% This field is not GC-ed, and so can contain garbage | |
46 // between critical sections. Use only pointer-comparison | |
47 // operations on the pointer, except within a critical section. | |
48 // (Also, ensure that occasional false positives are benign.) | |
49 methodOop _current_method; | |
50 bool _is_wide; | |
1565 | 51 Bytecodes::Code _code; |
0 | 52 address _next_pc; // current decoding position |
53 | |
54 void align() { _next_pc = (address)round_to((intptr_t)_next_pc, sizeof(jint)); } | |
55 int get_byte() { return *(jbyte*) _next_pc++; } // signed | |
56 short get_short() { short i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; } | |
57 int get_int() { int i=Bytes::get_Java_u4(_next_pc); _next_pc+=4; return i; } | |
58 | |
1565 | 59 int get_index_u1() { return *(address)_next_pc++; } |
60 int get_index_u2() { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; } | |
1602 | 61 int get_index_u1_cpcache() { return get_index_u1() + constantPoolOopDesc::CPCACHE_INDEX_TAG; } |
1565 | 62 int get_index_u2_cpcache() { int i=Bytes::get_native_u2(_next_pc); _next_pc+=2; return i + constantPoolOopDesc::CPCACHE_INDEX_TAG; } |
63 int get_index_u4() { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; } | |
64 int get_index_special() { return (is_wide()) ? get_index_u2() : get_index_u1(); } | |
0 | 65 methodOop method() { return _current_method; } |
66 bool is_wide() { return _is_wide; } | |
1565 | 67 Bytecodes::Code raw_code() { return Bytecodes::Code(_code); } |
0 | 68 |
69 | |
1565 | 70 bool check_index(int i, int& cp_index, outputStream* st = tty); |
0 | 71 void print_constant(int i, outputStream* st = tty); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
72 void print_field_or_method(int i, outputStream* st = tty); |
1602 | 73 void print_field_or_method(int orig_i, int i, outputStream* st = tty); |
1565 | 74 void print_attributes(int bci, outputStream* st = tty); |
0 | 75 void bytecode_epilog(int bci, outputStream* st = tty); |
76 | |
77 public: | |
78 BytecodePrinter() { | |
79 _is_wide = false; | |
1565 | 80 _code = Bytecodes::_illegal; |
0 | 81 } |
82 | |
83 // This method is called while executing the raw bytecodes, so none of | |
84 // the adjustments that BytecodeStream performs applies. | |
85 void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { | |
86 ResourceMark rm; | |
87 if (_current_method != method()) { | |
88 // Note 1: This code will not work as expected with true MT/MP. | |
89 // Need an explicit lock or a different solution. | |
90 // It is possible for this block to be skipped, if a garbage | |
91 // _current_method pointer happens to have the same bits as | |
92 // the incoming method. We could lose a line of trace output. | |
93 // This is acceptable in a debug-only feature. | |
94 st->cr(); | |
3960 | 95 st->print("[%ld] ", (long) Thread::current()->osthread()->thread_id()); |
0 | 96 method->print_name(st); |
97 st->cr(); | |
98 _current_method = method(); | |
99 } | |
100 Bytecodes::Code code; | |
101 if (is_wide()) { | |
102 // bcp wasn't advanced if previous bytecode was _wide. | |
2142 | 103 code = Bytecodes::code_at(method(), bcp+1); |
0 | 104 } else { |
2142 | 105 code = Bytecodes::code_at(method(), bcp); |
0 | 106 } |
1565 | 107 _code = code; |
108 int bci = bcp - method->code_base(); | |
3960 | 109 st->print("[%ld] ", (long) Thread::current()->osthread()->thread_id()); |
0 | 110 if (Verbose) { |
111 st->print("%8d %4d " INTPTR_FORMAT " " INTPTR_FORMAT " %s", | |
112 BytecodeCounter::counter_value(), bci, tos, tos2, Bytecodes::name(code)); | |
113 } else { | |
114 st->print("%8d %4d %s", | |
115 BytecodeCounter::counter_value(), bci, Bytecodes::name(code)); | |
116 } | |
117 _next_pc = is_wide() ? bcp+2 : bcp+1; | |
1565 | 118 print_attributes(bci); |
0 | 119 // Set is_wide for the next one, since the caller of this doesn't skip |
120 // the next bytecode. | |
121 _is_wide = (code == Bytecodes::_wide); | |
1565 | 122 _code = Bytecodes::_illegal; |
0 | 123 } |
124 | |
125 // Used for methodOop::print_codes(). The input bcp comes from | |
126 // BytecodeStream, which will skip wide bytecodes. | |
127 void trace(methodHandle method, address bcp, outputStream* st) { | |
128 _current_method = method(); | |
129 ResourceMark rm; | |
2142 | 130 Bytecodes::Code code = Bytecodes::code_at(method(), bcp); |
0 | 131 // Set is_wide |
132 _is_wide = (code == Bytecodes::_wide); | |
133 if (is_wide()) { | |
2142 | 134 code = Bytecodes::code_at(method(), bcp+1); |
0 | 135 } |
1565 | 136 _code = code; |
0 | 137 int bci = bcp - method->code_base(); |
138 // Print bytecode index and name | |
139 if (is_wide()) { | |
140 st->print("%d %s_w", bci, Bytecodes::name(code)); | |
141 } else { | |
142 st->print("%d %s", bci, Bytecodes::name(code)); | |
143 } | |
144 _next_pc = is_wide() ? bcp+2 : bcp+1; | |
1565 | 145 print_attributes(bci, st); |
0 | 146 bytecode_epilog(bci, st); |
147 } | |
148 }; | |
149 | |
150 | |
151 // Implementation of BytecodeTracer | |
152 | |
153 // %%% This set_closure thing seems overly general, given that | |
154 // nobody uses it. Also, if BytecodePrinter weren't hidden | |
155 // then methodOop could use instances of it directly and it | |
156 // would be easier to remove races on _current_method and bcp. | |
157 // Since this is not product functionality, we can defer cleanup. | |
158 | |
159 BytecodeClosure* BytecodeTracer::_closure = NULL; | |
160 | |
161 static BytecodePrinter std_closure; | |
162 BytecodeClosure* BytecodeTracer::std_closure() { | |
163 return &::std_closure; | |
164 } | |
165 | |
166 | |
167 void BytecodeTracer::trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { | |
168 if (TraceBytecodes && BytecodeCounter::counter_value() >= TraceBytecodesAt) { | |
169 ttyLocker ttyl; // 5065316: keep the following output coherent | |
170 // The ttyLocker also prevents races between two threads | |
171 // trying to use the single instance of BytecodePrinter. | |
172 // Using the ttyLocker prevents the system from coming to | |
173 // a safepoint within this code, which is sensitive to methodOop | |
174 // movement. | |
175 // | |
176 // There used to be a leaf mutex here, but the ttyLocker will | |
177 // work just as well, as long as the printing operations never block. | |
178 // | |
179 // We put the locker on the static trace method, not the | |
180 // virtual one, because the clients of this module go through | |
181 // the static method. | |
182 _closure->trace(method, bcp, tos, tos2, st); | |
183 } | |
184 } | |
185 | |
186 void BytecodeTracer::trace(methodHandle method, address bcp, outputStream* st) { | |
187 ttyLocker ttyl; // 5065316: keep the following output coherent | |
188 _closure->trace(method, bcp, st); | |
189 } | |
190 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
191 void print_symbol(Symbol* sym, outputStream* st) { |
1602 | 192 char buf[40]; |
193 int len = sym->utf8_length(); | |
194 if (len >= (int)sizeof(buf)) { | |
195 st->print_cr(" %s...[%d]", sym->as_C_string(buf, sizeof(buf)), len); | |
196 } else { | |
197 st->print(" "); | |
198 sym->print_on(st); st->cr(); | |
199 } | |
200 } | |
201 | |
0 | 202 void print_oop(oop value, outputStream* st) { |
203 if (value == NULL) { | |
204 st->print_cr(" NULL"); | |
1602 | 205 } else if (java_lang_String::is_instance(value)) { |
3388
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2460
diff
changeset
|
206 char buf[40]; |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2460
diff
changeset
|
207 int len = java_lang_String::utf8_length(value); |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2460
diff
changeset
|
208 java_lang_String::as_utf8_string(value, buf, sizeof(buf)); |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2460
diff
changeset
|
209 if (len >= (int)sizeof(buf)) { |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2460
diff
changeset
|
210 st->print_cr(" %s...[%d]", buf, len); |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2460
diff
changeset
|
211 } else { |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2460
diff
changeset
|
212 st->print_cr(" %s", buf); |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2460
diff
changeset
|
213 } |
1602 | 214 } else { |
215 st->print_cr(" " PTR_FORMAT, (intptr_t) value); | |
0 | 216 } |
217 } | |
218 | |
1565 | 219 bool BytecodePrinter::check_index(int i, int& cp_index, outputStream* st) { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
220 constantPoolOop constants = method()->constants(); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
221 int ilimit = constants->length(), climit = 0; |
1565 | 222 Bytecodes::Code code = raw_code(); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
223 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
224 constantPoolCacheOop cache = NULL; |
1565 | 225 if (Bytecodes::uses_cp_cache(code)) { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
226 cache = constants->cache(); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
227 if (cache != NULL) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
228 //climit = cache->length(); // %%% private! |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
229 size_t size = cache->size() * HeapWordSize; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
230 size -= sizeof(constantPoolCacheOopDesc); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
231 size /= sizeof(ConstantPoolCacheEntry); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
232 climit = (int) size; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
233 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
234 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
235 |
1565 | 236 if (cache != NULL && constantPoolCacheOopDesc::is_secondary_index(i)) { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
237 i = constantPoolCacheOopDesc::decode_secondary_index(i); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
238 st->print(" secondary cache[%d] of", i); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
239 if (i >= 0 && i < climit) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
240 if (!cache->entry_at(i)->is_secondary_entry()) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
241 st->print_cr(" not secondary entry?", i); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
242 return false; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
243 } |
4042
b20d64f83668
7090904: JSR 292: JRuby junit test crashes in PSScavengeRootsClosure::do_oop
twisti
parents:
3960
diff
changeset
|
244 i = cache->entry_at(i)->main_entry_index() + constantPoolOopDesc::CPCACHE_INDEX_TAG; |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
245 goto check_cache_index; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
246 } else { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
247 st->print_cr(" not in cache[*]?", i); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
248 return false; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
249 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
250 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
251 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
252 if (cache != NULL) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
253 goto check_cache_index; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
254 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
255 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
256 check_cp_index: |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
257 if (i >= 0 && i < ilimit) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
258 if (WizardMode) st->print(" cp[%d]", i); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
259 cp_index = i; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
260 return true; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
261 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
262 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
263 st->print_cr(" CP[%d] not in CP", i); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
264 return false; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
265 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
266 check_cache_index: |
1565 | 267 #ifdef ASSERT |
268 { | |
269 const int CPCACHE_INDEX_TAG = constantPoolOopDesc::CPCACHE_INDEX_TAG; | |
270 if (i >= CPCACHE_INDEX_TAG && i < climit + CPCACHE_INDEX_TAG) { | |
271 i -= CPCACHE_INDEX_TAG; | |
272 } else { | |
273 st->print_cr(" CP[%d] missing bias?", i); | |
274 return false; | |
275 } | |
276 } | |
277 #endif //ASSERT | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
278 if (i >= 0 && i < climit) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
279 if (cache->entry_at(i)->is_secondary_entry()) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
280 st->print_cr(" secondary entry?"); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
281 return false; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
282 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
283 i = cache->entry_at(i)->constant_pool_index(); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
284 goto check_cp_index; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
285 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
286 st->print_cr(" not in CP[*]?", i); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
287 return false; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
288 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
289 |
0 | 290 void BytecodePrinter::print_constant(int i, outputStream* st) { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
291 int orig_i = i; |
1565 | 292 if (!check_index(orig_i, i, st)) return; |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
293 |
0 | 294 constantPoolOop constants = method()->constants(); |
295 constantTag tag = constants->tag_at(i); | |
296 | |
297 if (tag.is_int()) { | |
298 st->print_cr(" " INT32_FORMAT, constants->int_at(i)); | |
299 } else if (tag.is_long()) { | |
300 st->print_cr(" " INT64_FORMAT, constants->long_at(i)); | |
301 } else if (tag.is_float()) { | |
302 st->print_cr(" %f", constants->float_at(i)); | |
303 } else if (tag.is_double()) { | |
304 st->print_cr(" %f", constants->double_at(i)); | |
305 } else if (tag.is_string()) { | |
1602 | 306 oop string = constants->pseudo_string_at(i); |
0 | 307 print_oop(string, st); |
308 } else if (tag.is_unresolved_string()) { | |
1602 | 309 const char* string = constants->string_at_noresolve(i); |
310 st->print_cr(" %s", string); | |
0 | 311 } else if (tag.is_klass()) { |
312 st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name()); | |
313 } else if (tag.is_unresolved_klass()) { | |
314 st->print_cr(" <unresolved klass at %d>", i); | |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
315 } else if (tag.is_object()) { |
1602 | 316 st->print(" <Object>"); |
317 print_oop(constants->object_at(i), st); | |
318 } else if (tag.is_method_type()) { | |
319 int i2 = constants->method_type_index_at(i); | |
320 st->print(" <MethodType> %d", i2); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
321 print_symbol(constants->symbol_at(i2), st); |
1602 | 322 } else if (tag.is_method_handle()) { |
323 int kind = constants->method_handle_ref_kind_at(i); | |
324 int i2 = constants->method_handle_index_at(i); | |
325 st->print(" <MethodHandle of kind %d>", kind, i2); | |
326 print_field_or_method(-i, i2, st); | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
327 } else { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
328 st->print_cr(" bad tag=%d at %d", tag.value(), i); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
329 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
330 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
331 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
332 void BytecodePrinter::print_field_or_method(int i, outputStream* st) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
333 int orig_i = i; |
1565 | 334 if (!check_index(orig_i, i, st)) return; |
1602 | 335 print_field_or_method(orig_i, i, st); |
336 } | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
337 |
1602 | 338 void BytecodePrinter::print_field_or_method(int orig_i, int i, outputStream* st) { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
339 constantPoolOop constants = method()->constants(); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
340 constantTag tag = constants->tag_at(i); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
341 |
1660
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
342 bool has_klass = true; |
1059
389049f3f393
6858164: invokedynamic code needs some cleanup (post-6655638)
jrose
parents:
844
diff
changeset
|
343 |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
344 switch (tag.value()) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
345 case JVM_CONSTANT_InterfaceMethodref: |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
346 case JVM_CONSTANT_Methodref: |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
347 case JVM_CONSTANT_Fieldref: |
1660
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
348 break; |
1059
389049f3f393
6858164: invokedynamic code needs some cleanup (post-6655638)
jrose
parents:
844
diff
changeset
|
349 case JVM_CONSTANT_NameAndType: |
1660
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
350 case JVM_CONSTANT_InvokeDynamic: |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
351 has_klass = false; |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
352 break; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
353 default: |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
354 st->print_cr(" bad tag=%d at %d", tag.value(), i); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
355 return; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
356 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
357 |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
358 Symbol* name = constants->uncached_name_ref_at(i); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
359 Symbol* signature = constants->uncached_signature_ref_at(i); |
1602 | 360 const char* sep = (tag.is_field() ? "/" : ""); |
1660
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
361 if (has_klass) { |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
362 Symbol* klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i)); |
1660
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
363 st->print_cr(" %d <%s.%s%s%s> ", i, klass->as_C_string(), name->as_C_string(), sep, signature->as_C_string()); |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
364 } else { |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
365 if (tag.is_invoke_dynamic()) { |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
366 int bsm = constants->invoke_dynamic_bootstrap_method_ref_index_at(i); |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
367 st->print(" bsm=%d", bsm); |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
368 } |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
369 st->print_cr(" %d <%s%s%s>", i, name->as_C_string(), sep, signature->as_C_string()); |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1602
diff
changeset
|
370 } |
0 | 371 } |
372 | |
373 | |
1565 | 374 void BytecodePrinter::print_attributes(int bci, outputStream* st) { |
0 | 375 // Show attributes of pre-rewritten codes |
1565 | 376 Bytecodes::Code code = Bytecodes::java_code(raw_code()); |
0 | 377 // If the code doesn't have any fields there's nothing to print. |
378 // note this is ==1 because the tableswitch and lookupswitch are | |
379 // zero size (for some reason) and we want to print stuff out for them. | |
380 if (Bytecodes::length_for(code) == 1) { | |
381 st->cr(); | |
382 return; | |
383 } | |
384 | |
385 switch(code) { | |
386 // Java specific bytecodes only matter. | |
387 case Bytecodes::_bipush: | |
388 st->print_cr(" " INT32_FORMAT, get_byte()); | |
389 break; | |
390 case Bytecodes::_sipush: | |
391 st->print_cr(" " INT32_FORMAT, get_short()); | |
392 break; | |
393 case Bytecodes::_ldc: | |
1602 | 394 if (Bytecodes::uses_cp_cache(raw_code())) { |
395 print_constant(get_index_u1_cpcache(), st); | |
396 } else { | |
397 print_constant(get_index_u1(), st); | |
398 } | |
0 | 399 break; |
400 | |
401 case Bytecodes::_ldc_w: | |
402 case Bytecodes::_ldc2_w: | |
1602 | 403 if (Bytecodes::uses_cp_cache(raw_code())) { |
404 print_constant(get_index_u2_cpcache(), st); | |
405 } else { | |
406 print_constant(get_index_u2(), st); | |
407 } | |
0 | 408 break; |
409 | |
410 case Bytecodes::_iload: | |
411 case Bytecodes::_lload: | |
412 case Bytecodes::_fload: | |
413 case Bytecodes::_dload: | |
414 case Bytecodes::_aload: | |
415 case Bytecodes::_istore: | |
416 case Bytecodes::_lstore: | |
417 case Bytecodes::_fstore: | |
418 case Bytecodes::_dstore: | |
419 case Bytecodes::_astore: | |
420 st->print_cr(" #%d", get_index_special()); | |
421 break; | |
422 | |
423 case Bytecodes::_iinc: | |
424 { int index = get_index_special(); | |
425 jint offset = is_wide() ? get_short(): get_byte(); | |
426 st->print_cr(" #%d " INT32_FORMAT, index, offset); | |
427 } | |
428 break; | |
429 | |
430 case Bytecodes::_newarray: { | |
1565 | 431 BasicType atype = (BasicType)get_index_u1(); |
0 | 432 const char* str = type2name(atype); |
433 if (str == NULL || atype == T_OBJECT || atype == T_ARRAY) { | |
434 assert(false, "Unidentified basic type"); | |
435 } | |
436 st->print_cr(" %s", str); | |
437 } | |
438 break; | |
439 case Bytecodes::_anewarray: { | |
1565 | 440 int klass_index = get_index_u2(); |
0 | 441 constantPoolOop constants = method()->constants(); |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
442 Symbol* name = constants->klass_name_at(klass_index); |
0 | 443 st->print_cr(" %s ", name->as_C_string()); |
444 } | |
445 break; | |
446 case Bytecodes::_multianewarray: { | |
1565 | 447 int klass_index = get_index_u2(); |
448 int nof_dims = get_index_u1(); | |
0 | 449 constantPoolOop constants = method()->constants(); |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
450 Symbol* name = constants->klass_name_at(klass_index); |
0 | 451 st->print_cr(" %s %d", name->as_C_string(), nof_dims); |
452 } | |
453 break; | |
454 | |
455 case Bytecodes::_ifeq: | |
456 case Bytecodes::_ifnull: | |
457 case Bytecodes::_iflt: | |
458 case Bytecodes::_ifle: | |
459 case Bytecodes::_ifne: | |
460 case Bytecodes::_ifnonnull: | |
461 case Bytecodes::_ifgt: | |
462 case Bytecodes::_ifge: | |
463 case Bytecodes::_if_icmpeq: | |
464 case Bytecodes::_if_icmpne: | |
465 case Bytecodes::_if_icmplt: | |
466 case Bytecodes::_if_icmpgt: | |
467 case Bytecodes::_if_icmple: | |
468 case Bytecodes::_if_icmpge: | |
469 case Bytecodes::_if_acmpeq: | |
470 case Bytecodes::_if_acmpne: | |
471 case Bytecodes::_goto: | |
472 case Bytecodes::_jsr: | |
473 st->print_cr(" %d", bci + get_short()); | |
474 break; | |
475 | |
476 case Bytecodes::_goto_w: | |
477 case Bytecodes::_jsr_w: | |
478 st->print_cr(" %d", bci + get_int()); | |
479 break; | |
480 | |
481 case Bytecodes::_ret: st->print_cr(" %d", get_index_special()); break; | |
482 | |
483 case Bytecodes::_tableswitch: | |
484 { align(); | |
485 int default_dest = bci + get_int(); | |
486 int lo = get_int(); | |
487 int hi = get_int(); | |
488 int len = hi - lo + 1; | |
489 jint* dest = NEW_RESOURCE_ARRAY(jint, len); | |
490 for (int i = 0; i < len; i++) { | |
491 dest[i] = bci + get_int(); | |
492 } | |
493 st->print(" %d " INT32_FORMAT " " INT32_FORMAT " ", | |
494 default_dest, lo, hi); | |
495 int first = true; | |
496 for (int ll = lo; ll <= hi; ll++, first = false) { | |
497 int idx = ll - lo; | |
498 const char *format = first ? " %d:" INT32_FORMAT " (delta: %d)" : | |
499 ", %d:" INT32_FORMAT " (delta: %d)"; | |
500 st->print(format, ll, dest[idx], dest[idx]-bci); | |
501 } | |
502 st->cr(); | |
503 } | |
504 break; | |
505 case Bytecodes::_lookupswitch: | |
506 { align(); | |
507 int default_dest = bci + get_int(); | |
508 int len = get_int(); | |
509 jint* key = NEW_RESOURCE_ARRAY(jint, len); | |
510 jint* dest = NEW_RESOURCE_ARRAY(jint, len); | |
511 for (int i = 0; i < len; i++) { | |
512 key [i] = get_int(); | |
513 dest[i] = bci + get_int(); | |
514 }; | |
515 st->print(" %d %d ", default_dest, len); | |
516 bool first = true; | |
517 for (int ll = 0; ll < len; ll++, first = false) { | |
518 const char *format = first ? " " INT32_FORMAT ":" INT32_FORMAT : | |
519 ", " INT32_FORMAT ":" INT32_FORMAT ; | |
520 st->print(format, key[ll], dest[ll]); | |
521 } | |
522 st->cr(); | |
523 } | |
524 break; | |
525 | |
526 case Bytecodes::_putstatic: | |
527 case Bytecodes::_getstatic: | |
528 case Bytecodes::_putfield: | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
529 case Bytecodes::_getfield: |
1565 | 530 print_field_or_method(get_index_u2_cpcache(), st); |
0 | 531 break; |
532 | |
533 case Bytecodes::_invokevirtual: | |
534 case Bytecodes::_invokespecial: | |
535 case Bytecodes::_invokestatic: | |
1565 | 536 print_field_or_method(get_index_u2_cpcache(), st); |
0 | 537 break; |
538 | |
539 case Bytecodes::_invokeinterface: | |
1565 | 540 { int i = get_index_u2_cpcache(); |
541 int n = get_index_u1(); | |
542 get_byte(); // ignore zero byte | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
543 print_field_or_method(i, st); |
0 | 544 } |
545 break; | |
546 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
547 case Bytecodes::_invokedynamic: |
1565 | 548 print_field_or_method(get_index_u4(), st); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
549 break; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
550 |
0 | 551 case Bytecodes::_new: |
552 case Bytecodes::_checkcast: | |
553 case Bytecodes::_instanceof: | |
1565 | 554 { int i = get_index_u2(); |
0 | 555 constantPoolOop constants = method()->constants(); |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
556 Symbol* name = constants->klass_name_at(i); |
0 | 557 st->print_cr(" %d <%s>", i, name->as_C_string()); |
558 } | |
559 break; | |
560 | |
561 case Bytecodes::_wide: | |
562 // length is zero not one, but printed with no more info. | |
563 break; | |
564 | |
565 default: | |
566 ShouldNotReachHere(); | |
567 break; | |
568 } | |
569 } | |
570 | |
571 | |
572 void BytecodePrinter::bytecode_epilog(int bci, outputStream* st) { | |
573 methodDataOop mdo = method()->method_data(); | |
574 if (mdo != NULL) { | |
575 ProfileData* data = mdo->bci_to_data(bci); | |
576 if (data != NULL) { | |
577 st->print(" %d", mdo->dp_to_di(data->dp())); | |
578 st->fill_to(6); | |
579 data->print_data_on(st); | |
580 } | |
581 } | |
582 } | |
583 #endif // PRODUCT |