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