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