Mercurial > hg > truffle
annotate src/share/vm/ci/ciStreams.hpp @ 4597:8bc6f680a88d
fixed visual studio project files
author | Christian Haeubl <christian.haeubl@oracle.com> |
---|---|
date | Tue, 14 Feb 2012 15:01:36 -0800 |
parents | de847cac9235 |
children | 1d7922586cf6 |
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: | |
3897
de847cac9235
7078382: JSR 292: don't count method handle adapters against inlining budgets
twisti
parents:
2142
diff
changeset
|
132 // ciBytecodeStream iter(m); |
de847cac9235
7078382: JSR 292: don't count method handle adapters against inlining budgets
twisti
parents:
2142
diff
changeset
|
133 // while (iter.next() != ciBytecodeStream::EOBC()) { ... } |
0 | 134 Bytecodes::Code next() { |
135 _bc_start = _pc; // Capture start of bc | |
136 if( _pc >= _end ) return EOBC(); // End-Of-Bytecodes | |
137 | |
138 // Fetch Java bytecode | |
139 // All rewritten bytecodes maintain the size of original bytecode. | |
1565 | 140 _bc = Bytecodes::java_code(_raw_bc = (Bytecodes::Code)*_pc); |
0 | 141 int csize = Bytecodes::length_for(_bc); // Expected size |
1565 | 142 _pc += csize; // Bump PC past bytecode |
143 if (csize == 0) { | |
144 _bc = next_wide_or_table(_bc); | |
0 | 145 } |
146 return check_java(_bc); | |
147 } | |
148 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
149 bool is_wide() const { return ( _pc == _was_wide ); } |
0 | 150 |
1565 | 151 // Does this instruction contain an index which refes into the CP cache? |
1602 | 152 bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); } |
1565 | 153 |
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 | |
260 // If this is a method invocation bytecode, get the invoked method. | |
261 ciMethod* get_method(bool& will_link); | |
262 ciKlass* get_declared_method_holder(); | |
263 int get_method_holder_index(); | |
264 int get_method_signature_index(); | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
265 |
1602 | 266 ciCPCache* get_cpcache() const; |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
267 ciCallSite* get_call_site(); |
0 | 268 }; |
269 | |
270 | |
271 // ciSignatureStream | |
272 // | |
273 // The class is used to iterate over the elements of a method signature. | |
274 class ciSignatureStream : public StackObj { | |
275 private: | |
276 ciSignature* _sig; | |
277 int _pos; | |
278 public: | |
279 ciSignatureStream(ciSignature* signature) { | |
280 _sig = signature; | |
281 _pos = 0; | |
282 } | |
283 | |
284 bool at_return_type() { return _pos == _sig->count(); } | |
285 | |
286 bool is_done() { return _pos > _sig->count(); } | |
287 | |
288 void next() { | |
289 if (_pos <= _sig->count()) { | |
290 _pos++; | |
291 } | |
292 } | |
293 | |
294 ciType* type() { | |
295 if (at_return_type()) { | |
296 return _sig->return_type(); | |
297 } else { | |
298 return _sig->type_at(_pos); | |
299 } | |
300 } | |
301 }; | |
302 | |
303 | |
304 // ciExceptionHandlerStream | |
305 // | |
306 // The class is used to iterate over the exception handlers of | |
307 // a method. | |
308 class ciExceptionHandlerStream : public StackObj { | |
309 private: | |
310 // The method whose handlers we are traversing | |
311 ciMethod* _method; | |
312 | |
313 // Our current position in the list of handlers | |
314 int _pos; | |
315 int _end; | |
316 | |
317 ciInstanceKlass* _exception_klass; | |
318 int _bci; | |
319 bool _is_exact; | |
320 | |
321 public: | |
322 ciExceptionHandlerStream(ciMethod* method) { | |
323 _method = method; | |
324 | |
325 // Force loading of method code and handlers. | |
326 _method->code(); | |
327 | |
328 _pos = 0; | |
329 _end = _method->_handler_count; | |
330 _exception_klass = NULL; | |
331 _bci = -1; | |
332 _is_exact = false; | |
333 } | |
334 | |
335 ciExceptionHandlerStream(ciMethod* method, int bci, | |
336 ciInstanceKlass* exception_klass = NULL, | |
337 bool is_exact = false) { | |
338 _method = method; | |
339 | |
340 // Force loading of method code and handlers. | |
341 _method->code(); | |
342 | |
343 _pos = -1; | |
344 _end = _method->_handler_count + 1; // include the rethrow handler | |
345 _exception_klass = (exception_klass != NULL && exception_klass->is_loaded() | |
346 ? exception_klass | |
347 : NULL); | |
348 _bci = bci; | |
349 assert(_bci >= 0, "bci out of range"); | |
350 _is_exact = is_exact; | |
351 next(); | |
352 } | |
353 | |
354 // These methods are currently implemented in an odd way. | |
355 // Count the number of handlers the iterator has ever produced | |
356 // or will ever produce. Do not include the final rethrow handler. | |
357 // That is, a trivial exception handler stream will have a count | |
358 // of zero and produce just the rethrow handler. | |
359 int count(); | |
360 | |
361 // Count the number of handlers this stream will produce from now on. | |
362 // Include the current handler, and the final rethrow handler. | |
363 // The remaining count will be zero iff is_done() is true, | |
364 int count_remaining(); | |
365 | |
366 bool is_done() { | |
367 return (_pos >= _end); | |
368 } | |
369 | |
370 void next() { | |
371 _pos++; | |
372 if (_bci != -1) { | |
373 // We are not iterating over all handlers... | |
374 while (!is_done()) { | |
375 ciExceptionHandler* handler = _method->_exception_handlers[_pos]; | |
376 if (handler->is_in_range(_bci)) { | |
377 if (handler->is_catch_all()) { | |
378 // Found final active catch block. | |
379 _end = _pos+1; | |
380 return; | |
381 } else if (_exception_klass == NULL || !handler->catch_klass()->is_loaded()) { | |
382 // We cannot do any type analysis here. Must conservatively assume | |
383 // catch block is reachable. | |
384 return; | |
385 } else if (_exception_klass->is_subtype_of(handler->catch_klass())) { | |
386 // This catch clause will definitely catch the exception. | |
387 // Final candidate. | |
388 _end = _pos+1; | |
389 return; | |
390 } else if (!_is_exact && | |
391 handler->catch_klass()->is_subtype_of(_exception_klass)) { | |
392 // This catch block may be reachable. | |
393 return; | |
394 } | |
395 } | |
396 | |
397 // The catch block was not pertinent. Go on. | |
398 _pos++; | |
399 } | |
400 } else { | |
401 // This is an iteration over all handlers. | |
402 return; | |
403 } | |
404 } | |
405 | |
406 ciExceptionHandler* handler() { | |
407 return _method->_exception_handlers[_pos]; | |
408 } | |
409 }; | |
1972 | 410 |
2142 | 411 |
412 | |
413 // Implementation for declarations in bytecode.hpp | |
414 Bytecode::Bytecode(const ciBytecodeStream* stream, address bcp): _bcp(bcp != NULL ? bcp : stream->cur_bcp()), _code(Bytecodes::code_at(NULL, addr_at(0))) {} | |
415 Bytecode_lookupswitch::Bytecode_lookupswitch(const ciBytecodeStream* stream): Bytecode(stream) { verify(); } | |
416 Bytecode_tableswitch::Bytecode_tableswitch(const ciBytecodeStream* stream): Bytecode(stream) { verify(); } | |
417 | |
1972 | 418 #endif // SHARE_VM_CI_CISTREAMS_HPP |