Mercurial > hg > graal-compiler
annotate src/share/vm/ci/ciStreams.hpp @ 1507:cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
Summary: split MethodHandle.invoke into invokeExact and invokeGeneric; also clean up JVM-to-Java interfaces
Reviewed-by: twisti
author | jrose |
---|---|
date | Sat, 01 May 2010 02:42:18 -0700 |
parents | dd57230ba8fe |
children | c18cbe5936b8 ab102d5d923e |
rev | line source |
---|---|
0 | 1 /* |
844 | 2 * Copyright 1999-2009 Sun Microsystems, Inc. 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 * | |
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 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
94 address cur_bcp() const { return _bc_start; } // Returns bcp to current instruction |
0 | 95 int next_bci() const { return _pc -_start; } |
96 int cur_bci() const { return _bc_start - _start; } | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
97 int instruction_size() const { return _pc - _bc_start; } |
0 | 98 |
99 Bytecodes::Code cur_bc() const{ return check_java(_bc); } | |
100 Bytecodes::Code next_bc() { return Bytecodes::java_code((Bytecodes::Code)* _pc); } | |
101 | |
102 // Return current ByteCode and increment PC to next bytecode, skipping all | |
103 // intermediate constants. Returns EOBC at end. | |
104 // Expected usage: | |
105 // while( (bc = iter.next()) != EOBC() ) { ... } | |
106 Bytecodes::Code next() { | |
107 _bc_start = _pc; // Capture start of bc | |
108 if( _pc >= _end ) return EOBC(); // End-Of-Bytecodes | |
109 | |
110 // Fetch Java bytecode | |
111 // All rewritten bytecodes maintain the size of original bytecode. | |
112 _bc = Bytecodes::java_code((Bytecodes::Code)*_pc); | |
113 int csize = Bytecodes::length_for(_bc); // Expected size | |
114 | |
115 if( _bc == Bytecodes::_wide ) { | |
116 _bc=wide(); // Handle wide bytecode | |
117 } else if( csize == 0 ) { | |
118 _bc=table(_bc); // Handle inline tables | |
119 } else { | |
120 _pc += csize; // Bump PC past bytecode | |
121 } | |
122 return check_java(_bc); | |
123 } | |
124 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
125 bool is_wide() const { return ( _pc == _was_wide ); } |
0 | 126 |
127 // Get a byte index following this bytecode. | |
128 // If prefixed with a wide bytecode, get a wide index. | |
129 int get_index() const { | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
130 assert_index_size(is_wide() ? 2 : 1); |
0 | 131 return (_pc == _was_wide) // was widened? |
132 ? Bytes::get_Java_u2(_bc_start+2) // yes, return wide index | |
133 : _bc_start[1]; // no, return narrow index | |
134 } | |
135 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
136 // Get 2-byte index (getfield/putstatic/etc) |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
137 int get_index_big() const { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
138 assert_index_size(2); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
139 return Bytes::get_Java_u2(_bc_start+1); |
0 | 140 } |
141 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
142 // Get 2-byte index (or 4-byte, for invokedynamic) |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
143 int get_index_int() const { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
144 return has_giant_index() ? get_index_giant() : get_index_big(); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
145 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
146 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
147 // Get 4-byte index, for invokedynamic. |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
148 int get_index_giant() const { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
149 assert_index_size(4); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
150 return Bytes::get_native_u4(_bc_start+1); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
151 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
152 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
153 bool has_giant_index() const { return (cur_bc() == Bytecodes::_invokedynamic); } |
0 | 154 |
155 // Get dimensions byte (multinewarray) | |
156 int get_dimensions() const { return *(unsigned char*)(_pc-1); } | |
157 | |
158 // Sign-extended index byte/short, no widening | |
159 int get_byte() const { return (int8_t)(_pc[-1]); } | |
160 int get_short() const { return (int16_t)Bytes::get_Java_u2(_pc-2); } | |
161 int get_long() const { return (int32_t)Bytes::get_Java_u4(_pc-4); } | |
162 | |
163 // Get a byte signed constant for "iinc". Invalid for other bytecodes. | |
164 // If prefixed with a wide bytecode, get a wide constant | |
165 int get_iinc_con() const {return (_pc==_was_wide) ? get_short() :get_byte();} | |
166 | |
167 // 2-byte branch offset from current pc | |
168 int get_dest( ) const { | |
169 assert( Bytecodes::length_at(_bc_start) == sizeof(jshort)+1, "get_dest called with bad bytecode" ); | |
170 return _bc_start-_start + (short)Bytes::get_Java_u2(_pc-2); | |
171 } | |
172 | |
173 // 2-byte branch offset from next pc | |
174 int next_get_dest( ) const { | |
175 address next_bc_start = _pc; | |
176 assert( _pc < _end, "" ); | |
177 Bytecodes::Code next_bc = (Bytecodes::Code)*_pc; | |
178 assert( next_bc != Bytecodes::_wide, ""); | |
179 int next_csize = Bytecodes::length_for(next_bc); | |
180 assert( next_csize != 0, "" ); | |
181 assert( next_bc <= Bytecodes::_jsr_w, ""); | |
182 address next_pc = _pc + next_csize; | |
183 assert( Bytecodes::length_at(next_bc_start) == sizeof(jshort)+1, "next_get_dest called with bad bytecode" ); | |
184 return next_bc_start-_start + (short)Bytes::get_Java_u2(next_pc-2); | |
185 } | |
186 | |
187 // 4-byte branch offset from current pc | |
188 int get_far_dest( ) const { | |
189 assert( Bytecodes::length_at(_bc_start) == sizeof(jint)+1, "dest4 called with bad bytecode" ); | |
190 return _bc_start-_start + (int)Bytes::get_Java_u4(_pc-4); | |
191 } | |
192 | |
193 // For a lookup or switch table, return target destination | |
194 int get_int_table( int index ) const { | |
195 return Bytes::get_Java_u4((address)&_table_base[index]); } | |
196 | |
197 // For tableswitch - get length of offset part | |
198 int get_tableswitch_length() { return get_int_table(2)-get_int_table(1)+1; } | |
199 | |
200 int get_dest_table( int index ) const { | |
201 return cur_bci() + get_int_table(index); } | |
202 | |
203 // --- Constant pool access --- | |
204 int get_constant_index() const; | |
205 int get_field_index(); | |
206 int get_method_index(); | |
207 | |
208 // If this bytecode is a new, newarray, multianewarray, instanceof, | |
209 // or checkcast, get the referenced klass. | |
210 ciKlass* get_klass(bool& will_link); | |
211 int get_klass_index() const; | |
212 | |
213 // If this bytecode is one of the ldc variants, get the referenced | |
214 // constant | |
215 ciConstant get_constant(); | |
216 // True if the ldc variant points to an unresolved string | |
217 bool is_unresolved_string() const; | |
218 // True if the ldc variant points to an unresolved klass | |
219 bool is_unresolved_klass() const; | |
220 | |
221 // If this bytecode is one of get_field, get_static, put_field, | |
222 // or put_static, get the referenced field. | |
223 ciField* get_field(bool& will_link); | |
224 | |
225 ciInstanceKlass* get_declared_field_holder(); | |
226 int get_field_holder_index(); | |
227 int get_field_signature_index(); | |
228 | |
229 // If this is a method invocation bytecode, get the invoked method. | |
230 ciMethod* get_method(bool& will_link); | |
231 ciKlass* get_declared_method_holder(); | |
232 int get_method_holder_index(); | |
233 int get_method_signature_index(); | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
234 |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
235 ciCPCache* get_cpcache(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
236 ciCallSite* get_call_site(); |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
844
diff
changeset
|
237 |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
238 private: |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
239 void assert_index_size(int required_size) const { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
240 #ifdef ASSERT |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
241 int isize = instruction_size() - (is_wide() ? 1 : 0) - 1; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
242 if (isize == 2 && cur_bc() == Bytecodes::_iinc) |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
243 isize = 1; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
244 else if (isize <= 2) |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
245 ; // no change |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
246 else if (has_giant_index()) |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
247 isize = 4; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
248 else |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
249 isize = 2; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
250 assert(isize = required_size, "wrong index size"); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
251 #endif |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
252 } |
0 | 253 }; |
254 | |
255 | |
256 // ciSignatureStream | |
257 // | |
258 // The class is used to iterate over the elements of a method signature. | |
259 class ciSignatureStream : public StackObj { | |
260 private: | |
261 ciSignature* _sig; | |
262 int _pos; | |
263 public: | |
264 ciSignatureStream(ciSignature* signature) { | |
265 _sig = signature; | |
266 _pos = 0; | |
267 } | |
268 | |
269 bool at_return_type() { return _pos == _sig->count(); } | |
270 | |
271 bool is_done() { return _pos > _sig->count(); } | |
272 | |
273 void next() { | |
274 if (_pos <= _sig->count()) { | |
275 _pos++; | |
276 } | |
277 } | |
278 | |
279 ciType* type() { | |
280 if (at_return_type()) { | |
281 return _sig->return_type(); | |
282 } else { | |
283 return _sig->type_at(_pos); | |
284 } | |
285 } | |
286 }; | |
287 | |
288 | |
289 // ciExceptionHandlerStream | |
290 // | |
291 // The class is used to iterate over the exception handlers of | |
292 // a method. | |
293 class ciExceptionHandlerStream : public StackObj { | |
294 private: | |
295 // The method whose handlers we are traversing | |
296 ciMethod* _method; | |
297 | |
298 // Our current position in the list of handlers | |
299 int _pos; | |
300 int _end; | |
301 | |
302 ciInstanceKlass* _exception_klass; | |
303 int _bci; | |
304 bool _is_exact; | |
305 | |
306 public: | |
307 ciExceptionHandlerStream(ciMethod* method) { | |
308 _method = method; | |
309 | |
310 // Force loading of method code and handlers. | |
311 _method->code(); | |
312 | |
313 _pos = 0; | |
314 _end = _method->_handler_count; | |
315 _exception_klass = NULL; | |
316 _bci = -1; | |
317 _is_exact = false; | |
318 } | |
319 | |
320 ciExceptionHandlerStream(ciMethod* method, int bci, | |
321 ciInstanceKlass* exception_klass = NULL, | |
322 bool is_exact = false) { | |
323 _method = method; | |
324 | |
325 // Force loading of method code and handlers. | |
326 _method->code(); | |
327 | |
328 _pos = -1; | |
329 _end = _method->_handler_count + 1; // include the rethrow handler | |
330 _exception_klass = (exception_klass != NULL && exception_klass->is_loaded() | |
331 ? exception_klass | |
332 : NULL); | |
333 _bci = bci; | |
334 assert(_bci >= 0, "bci out of range"); | |
335 _is_exact = is_exact; | |
336 next(); | |
337 } | |
338 | |
339 // These methods are currently implemented in an odd way. | |
340 // Count the number of handlers the iterator has ever produced | |
341 // or will ever produce. Do not include the final rethrow handler. | |
342 // That is, a trivial exception handler stream will have a count | |
343 // of zero and produce just the rethrow handler. | |
344 int count(); | |
345 | |
346 // Count the number of handlers this stream will produce from now on. | |
347 // Include the current handler, and the final rethrow handler. | |
348 // The remaining count will be zero iff is_done() is true, | |
349 int count_remaining(); | |
350 | |
351 bool is_done() { | |
352 return (_pos >= _end); | |
353 } | |
354 | |
355 void next() { | |
356 _pos++; | |
357 if (_bci != -1) { | |
358 // We are not iterating over all handlers... | |
359 while (!is_done()) { | |
360 ciExceptionHandler* handler = _method->_exception_handlers[_pos]; | |
361 if (handler->is_in_range(_bci)) { | |
362 if (handler->is_catch_all()) { | |
363 // Found final active catch block. | |
364 _end = _pos+1; | |
365 return; | |
366 } else if (_exception_klass == NULL || !handler->catch_klass()->is_loaded()) { | |
367 // We cannot do any type analysis here. Must conservatively assume | |
368 // catch block is reachable. | |
369 return; | |
370 } else if (_exception_klass->is_subtype_of(handler->catch_klass())) { | |
371 // This catch clause will definitely catch the exception. | |
372 // Final candidate. | |
373 _end = _pos+1; | |
374 return; | |
375 } else if (!_is_exact && | |
376 handler->catch_klass()->is_subtype_of(_exception_klass)) { | |
377 // This catch block may be reachable. | |
378 return; | |
379 } | |
380 } | |
381 | |
382 // The catch block was not pertinent. Go on. | |
383 _pos++; | |
384 } | |
385 } else { | |
386 // This is an iteration over all handlers. | |
387 return; | |
388 } | |
389 } | |
390 | |
391 ciExceptionHandler* handler() { | |
392 return _method->_exception_handlers[_pos]; | |
393 } | |
394 }; |