Mercurial > hg > truffle
comparison src/share/vm/ci/ciStreams.hpp @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | be93aad57795 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a61af66fc99e |
---|---|
1 /* | |
2 * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved. | |
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 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
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: | |
34 // Handling for the weird bytecodes | |
35 Bytecodes::Code wide(); // Handle wide bytecode | |
36 Bytecodes::Code table(Bytecodes::Code); // Handle complicated inline table | |
37 | |
38 static Bytecodes::Code check_java(Bytecodes::Code c) { | |
39 assert(Bytecodes::is_java_code(c), "should not return _fast bytecodes"); | |
40 return c; | |
41 } | |
42 | |
43 ciMethod* _method; // the method | |
44 ciInstanceKlass* _holder; | |
45 address _bc_start; // Start of current bytecode for table | |
46 address _was_wide; // Address past last wide bytecode | |
47 jint* _table_base; // Aligned start of last table or switch | |
48 | |
49 address _start; // Start of bytecodes | |
50 address _end; // Past end of bytecodes | |
51 address _pc; // Current PC | |
52 Bytecodes::Code _bc; // Current bytecode | |
53 | |
54 void reset( address base, unsigned int size ) { | |
55 _bc_start =_was_wide = 0; | |
56 _start = _pc = base; _end = base + size; } | |
57 | |
58 public: | |
59 // End-Of-Bytecodes | |
60 static Bytecodes::Code EOBC() { | |
61 return Bytecodes::_illegal; | |
62 } | |
63 | |
64 ciBytecodeStream(ciMethod* m) { | |
65 reset_to_method(m); | |
66 } | |
67 | |
68 ciBytecodeStream() { | |
69 reset_to_method(NULL); | |
70 } | |
71 | |
72 ciMethod* method() const { return _method; } | |
73 | |
74 void reset_to_method(ciMethod* m) { | |
75 _method = m; | |
76 if (m == NULL) { | |
77 _holder = NULL; | |
78 reset(NULL, 0); | |
79 } else { | |
80 _holder = m->holder(); | |
81 reset(m->code(), m->code_size()); | |
82 } | |
83 } | |
84 | |
85 void reset_to_bci( int bci ); | |
86 | |
87 // Force the iterator to report a certain bci. | |
88 void force_bci(int bci); | |
89 | |
90 void set_max_bci( int max ) { | |
91 _end = _start + max; | |
92 } | |
93 | |
94 address cur_bcp() { return _bc_start; } // Returns bcp to current instruction | |
95 int next_bci() const { return _pc -_start; } | |
96 int cur_bci() const { return _bc_start - _start; } | |
97 | |
98 Bytecodes::Code cur_bc() const{ return check_java(_bc); } | |
99 Bytecodes::Code next_bc() { return Bytecodes::java_code((Bytecodes::Code)* _pc); } | |
100 | |
101 // Return current ByteCode and increment PC to next bytecode, skipping all | |
102 // intermediate constants. Returns EOBC at end. | |
103 // Expected usage: | |
104 // while( (bc = iter.next()) != EOBC() ) { ... } | |
105 Bytecodes::Code next() { | |
106 _bc_start = _pc; // Capture start of bc | |
107 if( _pc >= _end ) return EOBC(); // End-Of-Bytecodes | |
108 | |
109 // Fetch Java bytecode | |
110 // All rewritten bytecodes maintain the size of original bytecode. | |
111 _bc = Bytecodes::java_code((Bytecodes::Code)*_pc); | |
112 int csize = Bytecodes::length_for(_bc); // Expected size | |
113 | |
114 if( _bc == Bytecodes::_wide ) { | |
115 _bc=wide(); // Handle wide bytecode | |
116 } else if( csize == 0 ) { | |
117 _bc=table(_bc); // Handle inline tables | |
118 } else { | |
119 _pc += csize; // Bump PC past bytecode | |
120 } | |
121 return check_java(_bc); | |
122 } | |
123 | |
124 bool is_wide() { return ( _pc == _was_wide ); } | |
125 | |
126 // Get a byte index following this bytecode. | |
127 // If prefixed with a wide bytecode, get a wide index. | |
128 int get_index() const { | |
129 return (_pc == _was_wide) // was widened? | |
130 ? Bytes::get_Java_u2(_bc_start+2) // yes, return wide index | |
131 : _bc_start[1]; // no, return narrow index | |
132 } | |
133 | |
134 // Set a byte index following this bytecode. | |
135 // If prefixed with a wide bytecode, get a wide index. | |
136 void put_index(int idx) { | |
137 if (_pc == _was_wide) // was widened? | |
138 Bytes::put_Java_u2(_bc_start+2,idx); // yes, set wide index | |
139 else | |
140 _bc_start[1]=idx; // no, set narrow index | |
141 } | |
142 | |
143 // Get 2-byte index (getfield/putstatic/etc) | |
144 int get_index_big() const { return Bytes::get_Java_u2(_bc_start+1); } | |
145 | |
146 // Get dimensions byte (multinewarray) | |
147 int get_dimensions() const { return *(unsigned char*)(_pc-1); } | |
148 | |
149 // Get unsigned index fast | |
150 int get_index_fast() const { return Bytes::get_native_u2(_pc-2); } | |
151 | |
152 // Sign-extended index byte/short, no widening | |
153 int get_byte() const { return (int8_t)(_pc[-1]); } | |
154 int get_short() const { return (int16_t)Bytes::get_Java_u2(_pc-2); } | |
155 int get_long() const { return (int32_t)Bytes::get_Java_u4(_pc-4); } | |
156 | |
157 // Get a byte signed constant for "iinc". Invalid for other bytecodes. | |
158 // If prefixed with a wide bytecode, get a wide constant | |
159 int get_iinc_con() const {return (_pc==_was_wide) ? get_short() :get_byte();} | |
160 | |
161 // 2-byte branch offset from current pc | |
162 int get_dest( ) const { | |
163 assert( Bytecodes::length_at(_bc_start) == sizeof(jshort)+1, "get_dest called with bad bytecode" ); | |
164 return _bc_start-_start + (short)Bytes::get_Java_u2(_pc-2); | |
165 } | |
166 | |
167 // 2-byte branch offset from next pc | |
168 int next_get_dest( ) const { | |
169 address next_bc_start = _pc; | |
170 assert( _pc < _end, "" ); | |
171 Bytecodes::Code next_bc = (Bytecodes::Code)*_pc; | |
172 assert( next_bc != Bytecodes::_wide, ""); | |
173 int next_csize = Bytecodes::length_for(next_bc); | |
174 assert( next_csize != 0, "" ); | |
175 assert( next_bc <= Bytecodes::_jsr_w, ""); | |
176 address next_pc = _pc + next_csize; | |
177 assert( Bytecodes::length_at(next_bc_start) == sizeof(jshort)+1, "next_get_dest called with bad bytecode" ); | |
178 return next_bc_start-_start + (short)Bytes::get_Java_u2(next_pc-2); | |
179 } | |
180 | |
181 // 4-byte branch offset from current pc | |
182 int get_far_dest( ) const { | |
183 assert( Bytecodes::length_at(_bc_start) == sizeof(jint)+1, "dest4 called with bad bytecode" ); | |
184 return _bc_start-_start + (int)Bytes::get_Java_u4(_pc-4); | |
185 } | |
186 | |
187 // For a lookup or switch table, return target destination | |
188 int get_int_table( int index ) const { | |
189 return Bytes::get_Java_u4((address)&_table_base[index]); } | |
190 | |
191 // For tableswitch - get length of offset part | |
192 int get_tableswitch_length() { return get_int_table(2)-get_int_table(1)+1; } | |
193 | |
194 int get_dest_table( int index ) const { | |
195 return cur_bci() + get_int_table(index); } | |
196 | |
197 // --- Constant pool access --- | |
198 int get_constant_index() const; | |
199 int get_field_index(); | |
200 int get_method_index(); | |
201 | |
202 // If this bytecode is a new, newarray, multianewarray, instanceof, | |
203 // or checkcast, get the referenced klass. | |
204 ciKlass* get_klass(bool& will_link); | |
205 int get_klass_index() const; | |
206 | |
207 // If this bytecode is one of the ldc variants, get the referenced | |
208 // constant | |
209 ciConstant get_constant(); | |
210 // True if the ldc variant points to an unresolved string | |
211 bool is_unresolved_string() const; | |
212 // True if the ldc variant points to an unresolved klass | |
213 bool is_unresolved_klass() const; | |
214 | |
215 // If this bytecode is one of get_field, get_static, put_field, | |
216 // or put_static, get the referenced field. | |
217 ciField* get_field(bool& will_link); | |
218 | |
219 ciInstanceKlass* get_declared_field_holder(); | |
220 int get_field_holder_index(); | |
221 int get_field_signature_index(); | |
222 | |
223 // If this is a method invocation bytecode, get the invoked method. | |
224 ciMethod* get_method(bool& will_link); | |
225 ciKlass* get_declared_method_holder(); | |
226 int get_method_holder_index(); | |
227 int get_method_signature_index(); | |
228 }; | |
229 | |
230 | |
231 // ciSignatureStream | |
232 // | |
233 // The class is used to iterate over the elements of a method signature. | |
234 class ciSignatureStream : public StackObj { | |
235 private: | |
236 ciSignature* _sig; | |
237 int _pos; | |
238 public: | |
239 ciSignatureStream(ciSignature* signature) { | |
240 _sig = signature; | |
241 _pos = 0; | |
242 } | |
243 | |
244 bool at_return_type() { return _pos == _sig->count(); } | |
245 | |
246 bool is_done() { return _pos > _sig->count(); } | |
247 | |
248 void next() { | |
249 if (_pos <= _sig->count()) { | |
250 _pos++; | |
251 } | |
252 } | |
253 | |
254 ciType* type() { | |
255 if (at_return_type()) { | |
256 return _sig->return_type(); | |
257 } else { | |
258 return _sig->type_at(_pos); | |
259 } | |
260 } | |
261 }; | |
262 | |
263 | |
264 // ciExceptionHandlerStream | |
265 // | |
266 // The class is used to iterate over the exception handlers of | |
267 // a method. | |
268 class ciExceptionHandlerStream : public StackObj { | |
269 private: | |
270 // The method whose handlers we are traversing | |
271 ciMethod* _method; | |
272 | |
273 // Our current position in the list of handlers | |
274 int _pos; | |
275 int _end; | |
276 | |
277 ciInstanceKlass* _exception_klass; | |
278 int _bci; | |
279 bool _is_exact; | |
280 | |
281 public: | |
282 ciExceptionHandlerStream(ciMethod* method) { | |
283 _method = method; | |
284 | |
285 // Force loading of method code and handlers. | |
286 _method->code(); | |
287 | |
288 _pos = 0; | |
289 _end = _method->_handler_count; | |
290 _exception_klass = NULL; | |
291 _bci = -1; | |
292 _is_exact = false; | |
293 } | |
294 | |
295 ciExceptionHandlerStream(ciMethod* method, int bci, | |
296 ciInstanceKlass* exception_klass = NULL, | |
297 bool is_exact = false) { | |
298 _method = method; | |
299 | |
300 // Force loading of method code and handlers. | |
301 _method->code(); | |
302 | |
303 _pos = -1; | |
304 _end = _method->_handler_count + 1; // include the rethrow handler | |
305 _exception_klass = (exception_klass != NULL && exception_klass->is_loaded() | |
306 ? exception_klass | |
307 : NULL); | |
308 _bci = bci; | |
309 assert(_bci >= 0, "bci out of range"); | |
310 _is_exact = is_exact; | |
311 next(); | |
312 } | |
313 | |
314 // These methods are currently implemented in an odd way. | |
315 // Count the number of handlers the iterator has ever produced | |
316 // or will ever produce. Do not include the final rethrow handler. | |
317 // That is, a trivial exception handler stream will have a count | |
318 // of zero and produce just the rethrow handler. | |
319 int count(); | |
320 | |
321 // Count the number of handlers this stream will produce from now on. | |
322 // Include the current handler, and the final rethrow handler. | |
323 // The remaining count will be zero iff is_done() is true, | |
324 int count_remaining(); | |
325 | |
326 bool is_done() { | |
327 return (_pos >= _end); | |
328 } | |
329 | |
330 void next() { | |
331 _pos++; | |
332 if (_bci != -1) { | |
333 // We are not iterating over all handlers... | |
334 while (!is_done()) { | |
335 ciExceptionHandler* handler = _method->_exception_handlers[_pos]; | |
336 if (handler->is_in_range(_bci)) { | |
337 if (handler->is_catch_all()) { | |
338 // Found final active catch block. | |
339 _end = _pos+1; | |
340 return; | |
341 } else if (_exception_klass == NULL || !handler->catch_klass()->is_loaded()) { | |
342 // We cannot do any type analysis here. Must conservatively assume | |
343 // catch block is reachable. | |
344 return; | |
345 } else if (_exception_klass->is_subtype_of(handler->catch_klass())) { | |
346 // This catch clause will definitely catch the exception. | |
347 // Final candidate. | |
348 _end = _pos+1; | |
349 return; | |
350 } else if (!_is_exact && | |
351 handler->catch_klass()->is_subtype_of(_exception_klass)) { | |
352 // This catch block may be reachable. | |
353 return; | |
354 } | |
355 } | |
356 | |
357 // The catch block was not pertinent. Go on. | |
358 _pos++; | |
359 } | |
360 } else { | |
361 // This is an iteration over all handlers. | |
362 return; | |
363 } | |
364 } | |
365 | |
366 ciExceptionHandler* handler() { | |
367 return _method->_exception_handlers[_pos]; | |
368 } | |
369 }; |