Mercurial > hg > graal-compiler
annotate src/share/vm/ci/ciStreams.hpp @ 10186:b06ac540229e
8013132: Add a flag to turn off the output of the verbose verification code
Reviewed-by: johnc, brutisso
author | stefank |
---|---|
date | Wed, 24 Apr 2013 20:13:37 +0200 |
parents | f6b0eb4e44cf |
children | d13d7aba8c12 |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
2 * Copyright (c) 1999, 2012, 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 #ifndef SHARE_VM_CI_CISTREAMS_HPP |
26 #define SHARE_VM_CI_CISTREAMS_HPP | |
27 | |
28 #include "ci/ciClassList.hpp" | |
29 #include "ci/ciExceptionHandler.hpp" | |
30 #include "ci/ciInstanceKlass.hpp" | |
31 #include "ci/ciMethod.hpp" | |
32 #include "interpreter/bytecode.hpp" | |
33 | |
0 | 34 // ciBytecodeStream |
35 // | |
36 // The class is used to iterate over the bytecodes of a method. | |
37 // It hides the details of constant pool structure/access by | |
38 // providing accessors for constant pool items. It returns only pure | |
39 // Java bytecodes; VM-internal _fast bytecodes are translated back to | |
40 // their original form during iteration. | |
41 class ciBytecodeStream : StackObj { | |
42 private: | |
1565 | 43 // Handling for the weird bytecodes |
44 Bytecodes::Code next_wide_or_table(Bytecodes::Code); // Handle _wide & complicated inline table | |
0 | 45 |
46 static Bytecodes::Code check_java(Bytecodes::Code c) { | |
47 assert(Bytecodes::is_java_code(c), "should not return _fast bytecodes"); | |
48 return c; | |
49 } | |
50 | |
1565 | 51 static Bytecodes::Code check_defined(Bytecodes::Code c) { |
52 assert(Bytecodes::is_defined(c), ""); | |
53 return c; | |
54 } | |
55 | |
0 | 56 ciMethod* _method; // the method |
57 ciInstanceKlass* _holder; | |
58 address _bc_start; // Start of current bytecode for table | |
59 address _was_wide; // Address past last wide bytecode | |
60 jint* _table_base; // Aligned start of last table or switch | |
61 | |
62 address _start; // Start of bytecodes | |
63 address _end; // Past end of bytecodes | |
64 address _pc; // Current PC | |
65 Bytecodes::Code _bc; // Current bytecode | |
1565 | 66 Bytecodes::Code _raw_bc; // Current bytecode, raw form |
0 | 67 |
68 void reset( address base, unsigned int size ) { | |
69 _bc_start =_was_wide = 0; | |
1602 | 70 _start = _pc = base; _end = base + size; |
71 } | |
0 | 72 |
1565 | 73 void assert_wide(bool require_wide) const { |
74 if (require_wide) | |
75 { assert(is_wide(), "must be a wide instruction"); } | |
76 else { assert(!is_wide(), "must not be a wide instruction"); } | |
77 } | |
78 | |
2142 | 79 Bytecode bytecode() const { return Bytecode(this, _bc_start); } |
80 Bytecode next_bytecode() const { return Bytecode(this, _pc); } | |
1565 | 81 |
0 | 82 public: |
83 // End-Of-Bytecodes | |
84 static Bytecodes::Code EOBC() { | |
85 return Bytecodes::_illegal; | |
86 } | |
87 | |
88 ciBytecodeStream(ciMethod* m) { | |
89 reset_to_method(m); | |
90 } | |
91 | |
92 ciBytecodeStream() { | |
93 reset_to_method(NULL); | |
94 } | |
95 | |
96 ciMethod* method() const { return _method; } | |
97 | |
98 void reset_to_method(ciMethod* m) { | |
99 _method = m; | |
100 if (m == NULL) { | |
101 _holder = NULL; | |
102 reset(NULL, 0); | |
103 } else { | |
104 _holder = m->holder(); | |
105 reset(m->code(), m->code_size()); | |
106 } | |
107 } | |
108 | |
109 void reset_to_bci( int bci ); | |
110 | |
111 // Force the iterator to report a certain bci. | |
112 void force_bci(int bci); | |
113 | |
114 void set_max_bci( int max ) { | |
115 _end = _start + max; | |
116 } | |
117 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
118 address cur_bcp() const { return _bc_start; } // Returns bcp to current instruction |
1565 | 119 int next_bci() const { return _pc - _start; } |
0 | 120 int cur_bci() const { return _bc_start - _start; } |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
121 int instruction_size() const { return _pc - _bc_start; } |
0 | 122 |
123 Bytecodes::Code cur_bc() const{ return check_java(_bc); } | |
1565 | 124 Bytecodes::Code cur_bc_raw() const { return check_defined(_raw_bc); } |
0 | 125 Bytecodes::Code next_bc() { return Bytecodes::java_code((Bytecodes::Code)* _pc); } |
126 | |
127 // Return current ByteCode and increment PC to next bytecode, skipping all | |
128 // intermediate constants. Returns EOBC at end. | |
129 // Expected usage: | |
3897
de847cac9235
7078382: JSR 292: don't count method handle adapters against inlining budgets
twisti
parents:
2142
diff
changeset
|
130 // ciBytecodeStream iter(m); |
de847cac9235
7078382: JSR 292: don't count method handle adapters against inlining budgets
twisti
parents:
2142
diff
changeset
|
131 // while (iter.next() != ciBytecodeStream::EOBC()) { ... } |
0 | 132 Bytecodes::Code next() { |
133 _bc_start = _pc; // Capture start of bc | |
134 if( _pc >= _end ) return EOBC(); // End-Of-Bytecodes | |
135 | |
136 // Fetch Java bytecode | |
137 // All rewritten bytecodes maintain the size of original bytecode. | |
1565 | 138 _bc = Bytecodes::java_code(_raw_bc = (Bytecodes::Code)*_pc); |
0 | 139 int csize = Bytecodes::length_for(_bc); // Expected size |
1565 | 140 _pc += csize; // Bump PC past bytecode |
141 if (csize == 0) { | |
142 _bc = next_wide_or_table(_bc); | |
0 | 143 } |
144 return check_java(_bc); | |
145 } | |
146 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
147 bool is_wide() const { return ( _pc == _was_wide ); } |
0 | 148 |
1565 | 149 // Does this instruction contain an index which refes into the CP cache? |
1602 | 150 bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); } |
1565 | 151 |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6266
diff
changeset
|
152 bool has_optional_appendix() { return Bytecodes::has_optional_appendix(cur_bc_raw()); } |
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6266
diff
changeset
|
153 |
1565 | 154 int get_index_u1() const { |
2142 | 155 return bytecode().get_index_u1(cur_bc_raw()); |
1565 | 156 } |
157 | |
1602 | 158 int get_index_u1_cpcache() const { |
2142 | 159 return bytecode().get_index_u1_cpcache(cur_bc_raw()); |
1602 | 160 } |
161 | |
0 | 162 // Get a byte index following this bytecode. |
163 // If prefixed with a wide bytecode, get a wide index. | |
164 int get_index() const { | |
1602 | 165 assert(!has_cache_index(), "else use cpcache variant"); |
0 | 166 return (_pc == _was_wide) // was widened? |
1565 | 167 ? get_index_u2(true) // yes, return wide index |
168 : get_index_u1(); // no, return narrow index | |
0 | 169 } |
170 | |
1565 | 171 // Get 2-byte index (byte swapping depending on which bytecode) |
172 int get_index_u2(bool is_wide = false) const { | |
2142 | 173 return bytecode().get_index_u2(cur_bc_raw(), is_wide); |
0 | 174 } |
175 | |
1565 | 176 // Get 2-byte index in native byte order. (Rewriter::rewrite makes these.) |
177 int get_index_u2_cpcache() const { | |
2142 | 178 return bytecode().get_index_u2_cpcache(cur_bc_raw()); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
179 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
180 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
181 // Get 4-byte index, for invokedynamic. |
1565 | 182 int get_index_u4() const { |
2142 | 183 return bytecode().get_index_u4(cur_bc_raw()); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
184 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
185 |
1565 | 186 bool has_index_u4() const { |
2142 | 187 return bytecode().has_index_u4(cur_bc_raw()); |
1565 | 188 } |
0 | 189 |
190 // Get dimensions byte (multinewarray) | |
191 int get_dimensions() const { return *(unsigned char*)(_pc-1); } | |
192 | |
193 // Sign-extended index byte/short, no widening | |
2142 | 194 int get_constant_u1() const { return bytecode().get_constant_u1(instruction_size()-1, cur_bc_raw()); } |
195 int get_constant_u2(bool is_wide = false) const { return bytecode().get_constant_u2(instruction_size()-2, cur_bc_raw(), is_wide); } | |
0 | 196 |
197 // Get a byte signed constant for "iinc". Invalid for other bytecodes. | |
198 // If prefixed with a wide bytecode, get a wide constant | |
1565 | 199 int get_iinc_con() const {return (_pc==_was_wide) ? (jshort) get_constant_u2(true) : (jbyte) get_constant_u1();} |
0 | 200 |
201 // 2-byte branch offset from current pc | |
1565 | 202 int get_dest() const { |
2142 | 203 return cur_bci() + bytecode().get_offset_s2(cur_bc_raw()); |
0 | 204 } |
205 | |
206 // 2-byte branch offset from next pc | |
1565 | 207 int next_get_dest() const { |
208 assert(_pc < _end, ""); | |
2142 | 209 return next_bci() + next_bytecode().get_offset_s2(Bytecodes::_ifeq); |
0 | 210 } |
211 | |
212 // 4-byte branch offset from current pc | |
1565 | 213 int get_far_dest() const { |
2142 | 214 return cur_bci() + bytecode().get_offset_s4(cur_bc_raw()); |
0 | 215 } |
216 | |
217 // For a lookup or switch table, return target destination | |
218 int get_int_table( int index ) const { | |
219 return Bytes::get_Java_u4((address)&_table_base[index]); } | |
220 | |
221 // For tableswitch - get length of offset part | |
222 int get_tableswitch_length() { return get_int_table(2)-get_int_table(1)+1; } | |
223 | |
224 int get_dest_table( int index ) const { | |
225 return cur_bci() + get_int_table(index); } | |
226 | |
227 // --- Constant pool access --- | |
1602 | 228 int get_constant_raw_index() const; |
229 int get_constant_pool_index() const; | |
230 int get_constant_cache_index() const; | |
0 | 231 int get_field_index(); |
232 int get_method_index(); | |
233 | |
234 // If this bytecode is a new, newarray, multianewarray, instanceof, | |
235 // or checkcast, get the referenced klass. | |
236 ciKlass* get_klass(bool& will_link); | |
237 int get_klass_index() const; | |
238 | |
239 // If this bytecode is one of the ldc variants, get the referenced | |
1602 | 240 // constant. Do not attempt to resolve it, since that would require |
241 // execution of Java code. If it is not resolved, return an unloaded | |
242 // object (ciConstant.as_object()->is_loaded() == false). | |
0 | 243 ciConstant get_constant(); |
1602 | 244 constantTag get_constant_pool_tag(int index) const; |
245 | |
246 // True if the klass-using bytecode points to an unresolved klass | |
247 bool is_unresolved_klass() const { | |
248 constantTag tag = get_constant_pool_tag(get_klass_index()); | |
249 return tag.is_unresolved_klass(); | |
250 } | |
0 | 251 |
252 // If this bytecode is one of get_field, get_static, put_field, | |
253 // or put_static, get the referenced field. | |
254 ciField* get_field(bool& will_link); | |
255 | |
256 ciInstanceKlass* get_declared_field_holder(); | |
257 int get_field_holder_index(); | |
258 int get_field_signature_index(); | |
259 | |
6822
f6b0eb4e44cf
7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path
twisti
parents:
6725
diff
changeset
|
260 ciMethod* get_method(bool& will_link, ciSignature* *declared_signature_result); |
f6b0eb4e44cf
7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path
twisti
parents:
6725
diff
changeset
|
261 bool has_appendix(); |
f6b0eb4e44cf
7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path
twisti
parents:
6725
diff
changeset
|
262 ciObject* get_appendix(); |
f6b0eb4e44cf
7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path
twisti
parents:
6725
diff
changeset
|
263 bool has_method_type(); |
f6b0eb4e44cf
7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path
twisti
parents:
6725
diff
changeset
|
264 ciMethodType* get_method_type(); |
f6b0eb4e44cf
7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path
twisti
parents:
6725
diff
changeset
|
265 ciKlass* get_declared_method_holder(); |
f6b0eb4e44cf
7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path
twisti
parents:
6725
diff
changeset
|
266 int get_method_holder_index(); |
f6b0eb4e44cf
7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path
twisti
parents:
6725
diff
changeset
|
267 int get_method_signature_index(); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
268 |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
269 // Get the resolved references arrays from the constant pool |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
270 ciObjArray* get_resolved_references(); |
0 | 271 }; |
272 | |
273 | |
274 // ciSignatureStream | |
275 // | |
276 // The class is used to iterate over the elements of a method signature. | |
277 class ciSignatureStream : public StackObj { | |
278 private: | |
279 ciSignature* _sig; | |
280 int _pos; | |
281 public: | |
282 ciSignatureStream(ciSignature* signature) { | |
283 _sig = signature; | |
284 _pos = 0; | |
285 } | |
286 | |
287 bool at_return_type() { return _pos == _sig->count(); } | |
288 | |
289 bool is_done() { return _pos > _sig->count(); } | |
290 | |
291 void next() { | |
292 if (_pos <= _sig->count()) { | |
293 _pos++; | |
294 } | |
295 } | |
296 | |
297 ciType* type() { | |
298 if (at_return_type()) { | |
299 return _sig->return_type(); | |
300 } else { | |
301 return _sig->type_at(_pos); | |
302 } | |
303 } | |
304 }; | |
305 | |
306 | |
307 // ciExceptionHandlerStream | |
308 // | |
309 // The class is used to iterate over the exception handlers of | |
310 // a method. | |
311 class ciExceptionHandlerStream : public StackObj { | |
312 private: | |
313 // The method whose handlers we are traversing | |
314 ciMethod* _method; | |
315 | |
316 // Our current position in the list of handlers | |
317 int _pos; | |
318 int _end; | |
319 | |
320 ciInstanceKlass* _exception_klass; | |
321 int _bci; | |
322 bool _is_exact; | |
323 | |
324 public: | |
325 ciExceptionHandlerStream(ciMethod* method) { | |
326 _method = method; | |
327 | |
328 // Force loading of method code and handlers. | |
329 _method->code(); | |
330 | |
331 _pos = 0; | |
332 _end = _method->_handler_count; | |
333 _exception_klass = NULL; | |
334 _bci = -1; | |
335 _is_exact = false; | |
336 } | |
337 | |
338 ciExceptionHandlerStream(ciMethod* method, int bci, | |
339 ciInstanceKlass* exception_klass = NULL, | |
340 bool is_exact = false) { | |
341 _method = method; | |
342 | |
343 // Force loading of method code and handlers. | |
344 _method->code(); | |
345 | |
346 _pos = -1; | |
347 _end = _method->_handler_count + 1; // include the rethrow handler | |
348 _exception_klass = (exception_klass != NULL && exception_klass->is_loaded() | |
349 ? exception_klass | |
350 : NULL); | |
351 _bci = bci; | |
352 assert(_bci >= 0, "bci out of range"); | |
353 _is_exact = is_exact; | |
354 next(); | |
355 } | |
356 | |
357 // These methods are currently implemented in an odd way. | |
358 // Count the number of handlers the iterator has ever produced | |
359 // or will ever produce. Do not include the final rethrow handler. | |
360 // That is, a trivial exception handler stream will have a count | |
361 // of zero and produce just the rethrow handler. | |
362 int count(); | |
363 | |
364 // Count the number of handlers this stream will produce from now on. | |
365 // Include the current handler, and the final rethrow handler. | |
366 // The remaining count will be zero iff is_done() is true, | |
367 int count_remaining(); | |
368 | |
369 bool is_done() { | |
370 return (_pos >= _end); | |
371 } | |
372 | |
373 void next() { | |
374 _pos++; | |
375 if (_bci != -1) { | |
376 // We are not iterating over all handlers... | |
377 while (!is_done()) { | |
378 ciExceptionHandler* handler = _method->_exception_handlers[_pos]; | |
379 if (handler->is_in_range(_bci)) { | |
380 if (handler->is_catch_all()) { | |
381 // Found final active catch block. | |
382 _end = _pos+1; | |
383 return; | |
384 } else if (_exception_klass == NULL || !handler->catch_klass()->is_loaded()) { | |
385 // We cannot do any type analysis here. Must conservatively assume | |
386 // catch block is reachable. | |
387 return; | |
388 } else if (_exception_klass->is_subtype_of(handler->catch_klass())) { | |
389 // This catch clause will definitely catch the exception. | |
390 // Final candidate. | |
391 _end = _pos+1; | |
392 return; | |
393 } else if (!_is_exact && | |
394 handler->catch_klass()->is_subtype_of(_exception_klass)) { | |
395 // This catch block may be reachable. | |
396 return; | |
397 } | |
398 } | |
399 | |
400 // The catch block was not pertinent. Go on. | |
401 _pos++; | |
402 } | |
403 } else { | |
404 // This is an iteration over all handlers. | |
405 return; | |
406 } | |
407 } | |
408 | |
409 ciExceptionHandler* handler() { | |
410 return _method->_exception_handlers[_pos]; | |
411 } | |
412 }; | |
1972 | 413 |
2142 | 414 |
415 | |
416 // Implementation for declarations in bytecode.hpp | |
417 Bytecode::Bytecode(const ciBytecodeStream* stream, address bcp): _bcp(bcp != NULL ? bcp : stream->cur_bcp()), _code(Bytecodes::code_at(NULL, addr_at(0))) {} | |
418 Bytecode_lookupswitch::Bytecode_lookupswitch(const ciBytecodeStream* stream): Bytecode(stream) { verify(); } | |
419 Bytecode_tableswitch::Bytecode_tableswitch(const ciBytecodeStream* stream): Bytecode(stream) { verify(); } | |
420 | |
1972 | 421 #endif // SHARE_VM_CI_CISTREAMS_HPP |