comparison src/share/vm/prims/methodHandleWalk.cpp @ 1133:aa62b9388fce

6894206: JVM needs a way to traverse method handle structures Summary: We need a way to walk chained method handles in the JVM to call the right methods and to generate required bytecode adapters for the compilers. Reviewed-by: kvn
author twisti
date Mon, 04 Jan 2010 15:52:40 +0100
parents
children dd57230ba8fe
comparison
equal deleted inserted replaced
1131:40e7c1d24e4a 1133:aa62b9388fce
1 /*
2 * Copyright 2008-2010 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 /*
26 * JSR 292 reference implementation: method handle structure analysis
27 */
28
29 #include "incls/_precompiled.incl"
30 #include "incls/_methodHandleWalk.cpp.incl"
31
32 void MethodHandleChain::set_method_handle(Handle mh, TRAPS) {
33 if (!java_dyn_MethodHandle::is_instance(mh())) lose("bad method handle", CHECK);
34
35 // set current method handle and unpack partially
36 _method_handle = mh;
37 _is_last = false;
38 _is_bound = false;
39 _arg_slot = -1;
40 _arg_type = T_VOID;
41 _conversion = -1;
42 _last_invoke = Bytecodes::_nop; //arbitrary non-garbage
43
44 if (sun_dyn_DirectMethodHandle::is_instance(mh())) {
45 set_last_method(mh(), THREAD);
46 return;
47 }
48 if (sun_dyn_AdapterMethodHandle::is_instance(mh())) {
49 _conversion = AdapterMethodHandle_conversion();
50 assert(_conversion != -1, "bad conv value");
51 assert(sun_dyn_BoundMethodHandle::is_instance(mh()), "also BMH");
52 }
53 if (sun_dyn_BoundMethodHandle::is_instance(mh())) {
54 if (!is_adapter()) // keep AMH and BMH separate in this model
55 _is_bound = true;
56 _arg_slot = BoundMethodHandle_vmargslot();
57 oop target = MethodHandle_vmtarget_oop();
58 if (!is_bound() || java_dyn_MethodHandle::is_instance(target)) {
59 _arg_type = compute_bound_arg_type(target, NULL, _arg_slot, CHECK);
60 } else if (target != NULL && target->is_method()) {
61 _arg_type = compute_bound_arg_type(NULL, (methodOop)target, _arg_slot, CHECK);
62 set_last_method(mh(), CHECK);
63 } else {
64 _is_bound = false; // lose!
65 }
66 }
67 if (is_bound() && _arg_type == T_VOID) {
68 lose("bad vmargslot", CHECK);
69 }
70 if (!is_bound() && !is_adapter()) {
71 lose("unrecognized MH type", CHECK);
72 }
73 }
74
75 void MethodHandleChain::set_last_method(oop target, TRAPS) {
76 _is_last = true;
77 klassOop receiver_limit_oop = NULL;
78 int flags = 0;
79 methodOop m = MethodHandles::decode_method(target, receiver_limit_oop, flags);
80 _last_method = methodHandle(THREAD, m);
81 if ((flags & MethodHandles::_dmf_has_receiver) == 0)
82 _last_invoke = Bytecodes::_invokestatic;
83 else if ((flags & MethodHandles::_dmf_does_dispatch) == 0)
84 _last_invoke = Bytecodes::_invokespecial;
85 else if ((flags & MethodHandles::_dmf_from_interface) != 0)
86 _last_invoke = Bytecodes::_invokeinterface;
87 else
88 _last_invoke = Bytecodes::_invokevirtual;
89 }
90
91 BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS) {
92 // There is no direct indication of whether the argument is primitive or not.
93 // It is implied by the _vmentry code, and by the MethodType of the target.
94 // FIXME: Make it explicit MethodHandleImpl refactors out from MethodHandle
95 BasicType arg_type = T_VOID;
96 if (target != NULL) {
97 oop mtype = java_dyn_MethodHandle::type(target);
98 int arg_num = MethodHandles::argument_slot_to_argnum(mtype, arg_slot);
99 if (arg_num >= 0) {
100 oop ptype = java_dyn_MethodType::ptype(mtype, arg_num);
101 arg_type = java_lang_Class::as_BasicType(ptype);
102 }
103 } else if (m != NULL) {
104 // figure out the argument type from the slot
105 // FIXME: make this explicit in the MH
106 int cur_slot = m->size_of_parameters();
107 if (arg_slot >= cur_slot)
108 return T_VOID;
109 if (!m->is_static()) {
110 cur_slot -= type2size[T_OBJECT];
111 if (cur_slot == arg_slot)
112 return T_OBJECT;
113 }
114 for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) {
115 BasicType bt = ss.type();
116 cur_slot -= type2size[bt];
117 if (cur_slot <= arg_slot) {
118 if (cur_slot == arg_slot)
119 arg_type = bt;
120 break;
121 }
122 }
123 }
124 if (arg_type == T_ARRAY)
125 arg_type = T_OBJECT;
126 return arg_type;
127 }
128
129 void MethodHandleChain::lose(const char* msg, TRAPS) {
130 _lose_message = msg;
131 if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) {
132 // throw a preallocated exception
133 THROW_OOP(Universe::virtual_machine_error_instance());
134 }
135 THROW_MSG(vmSymbols::java_lang_InternalError(), msg);
136 }
137
138 Bytecodes::Code MethodHandleWalker::conversion_code(BasicType src, BasicType dest) {
139 if (is_subword_type(src)) {
140 src = T_INT; // all subword src types act like int
141 }
142 if (src == dest) {
143 return Bytecodes::_nop;
144 }
145
146 #define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d))
147 switch (SRC_DEST(src, dest)) {
148 case SRC_DEST(T_INT, T_LONG): return Bytecodes::_i2l;
149 case SRC_DEST(T_INT, T_FLOAT): return Bytecodes::_i2f;
150 case SRC_DEST(T_INT, T_DOUBLE): return Bytecodes::_i2d;
151 case SRC_DEST(T_INT, T_BYTE): return Bytecodes::_i2b;
152 case SRC_DEST(T_INT, T_CHAR): return Bytecodes::_i2c;
153 case SRC_DEST(T_INT, T_SHORT): return Bytecodes::_i2s;
154
155 case SRC_DEST(T_LONG, T_INT): return Bytecodes::_l2i;
156 case SRC_DEST(T_LONG, T_FLOAT): return Bytecodes::_l2f;
157 case SRC_DEST(T_LONG, T_DOUBLE): return Bytecodes::_l2d;
158
159 case SRC_DEST(T_FLOAT, T_INT): return Bytecodes::_f2i;
160 case SRC_DEST(T_FLOAT, T_LONG): return Bytecodes::_f2l;
161 case SRC_DEST(T_FLOAT, T_DOUBLE): return Bytecodes::_f2d;
162
163 case SRC_DEST(T_DOUBLE, T_INT): return Bytecodes::_d2i;
164 case SRC_DEST(T_DOUBLE, T_LONG): return Bytecodes::_d2l;
165 case SRC_DEST(T_DOUBLE, T_FLOAT): return Bytecodes::_d2f;
166 }
167 #undef SRC_DEST
168
169 // cannot do it in one step, or at all
170 return Bytecodes::_illegal;
171 }
172
173 MethodHandleWalker::ArgToken
174 MethodHandleWalker::walk(TRAPS) {
175 walk_incoming_state(CHECK_NULL);
176
177 for (;;) {
178 set_method_handle(chain().method_handle_oop());
179
180 assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
181
182 if (chain().is_adapter()) {
183 int conv_op = chain().adapter_conversion_op();
184 int arg_slot = chain().adapter_arg_slot();
185 SlotState* arg_state = slot_state(arg_slot);
186 if (arg_state == NULL
187 && conv_op > sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW) {
188 lose("bad argument index", CHECK_NULL);
189 }
190
191 // perform the adapter action
192 switch (chain().adapter_conversion_op()) {
193 case sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY:
194 case sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW:
195 // No changes to arguments; pass the bits through.
196 // The only difference between the two ops is that the "only" version
197 // is fully compatible with the verifier, while the "raw" version
198 // performs a few extra bitwise conversions (like long <-> double).
199 break;
200
201 case sun_dyn_AdapterMethodHandle::OP_CHECK_CAST: {
202 // checkcast the Nth outgoing argument in place
203 klassOop dest_klass = NULL;
204 BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass);
205 assert(dest == T_OBJECT, "");
206 assert(dest == arg_state->_type, "");
207 arg_state->_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg_state->_arg, CHECK_NULL);
208 debug_only(dest_klass = (klassOop)badOop);
209 break;
210 }
211
212 case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM: {
213 // i2l, etc., on the Nth outgoing argument in place
214 BasicType src = chain().adapter_conversion_src_type(),
215 dest = chain().adapter_conversion_dest_type();
216 Bytecodes::Code bc = conversion_code(src, dest);
217 ArgToken arg = arg_state->_arg;
218 if (bc == Bytecodes::_nop) {
219 break;
220 } else if (bc != Bytecodes::_illegal) {
221 arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL);
222 } else if (is_subword_type(dest)) {
223 bc = conversion_code(src, T_INT);
224 if (bc != Bytecodes::_illegal) {
225 arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL);
226 bc = conversion_code(T_INT, dest);
227 arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL);
228 }
229 }
230 if (bc == Bytecodes::_illegal) {
231 lose("bad primitive conversion", CHECK_NULL);
232 }
233 change_argument(src, arg_slot, dest, arg);
234 break;
235 }
236
237 case sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM: {
238 // checkcast to wrapper type & call intValue, etc.
239 BasicType dest = chain().adapter_conversion_dest_type();
240 ArgToken arg = arg_state->_arg;
241 arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest),
242 Bytecodes::_checkcast, arg, CHECK_NULL);
243 vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest);
244 if (unboxer == vmIntrinsics::_none) {
245 lose("no unboxing method", CHECK_NULL);
246 }
247 ArgToken arglist[2];
248 arglist[0] = arg; // outgoing 'this'
249 arglist[1] = NULL; // sentinel
250 arg = make_invoke(NULL, unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_NULL);
251 change_argument(T_OBJECT, arg_slot, dest, arg);
252 break;
253 }
254
255 case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF: {
256 // call wrapper type.valueOf
257 BasicType src = chain().adapter_conversion_src_type();
258 ArgToken arg = arg_state->_arg;
259 vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src);
260 if (boxer == vmIntrinsics::_none) {
261 lose("no boxing method", CHECK_NULL);
262 }
263 ArgToken arglist[2];
264 arglist[0] = arg; // outgoing value
265 arglist[1] = NULL; // sentinel
266 arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_NULL);
267 change_argument(src, arg_slot, T_OBJECT, arg);
268 break;
269 }
270
271 case sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS: {
272 int dest_arg_slot = chain().adapter_conversion_vminfo();
273 if (!slot_has_argument(dest_arg_slot)) {
274 lose("bad swap index", CHECK_NULL);
275 }
276 // a simple swap between two arguments
277 SlotState* dest_arg_state = slot_state(dest_arg_slot);
278 SlotState temp = (*dest_arg_state);
279 (*dest_arg_state) = (*arg_state);
280 (*arg_state) = temp;
281 break;
282 }
283
284 case sun_dyn_AdapterMethodHandle::OP_ROT_ARGS: {
285 int dest_arg_slot = chain().adapter_conversion_vminfo();
286 if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) {
287 lose("bad rotate index", CHECK_NULL);
288 }
289 SlotState* dest_arg_state = slot_state(dest_arg_slot);
290 // Rotate the source argument (plus following N slots) into the
291 // position occupied by the dest argument (plus following N slots).
292 int rotate_count = type2size[dest_arg_state->_type];
293 // (no other rotate counts are currently supported)
294 if (arg_slot < dest_arg_slot) {
295 for (int i = 0; i < rotate_count; i++) {
296 SlotState temp = _outgoing.at(arg_slot);
297 _outgoing.remove_at(arg_slot);
298 _outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp);
299 }
300 } else { // arg_slot > dest_arg_slot
301 for (int i = 0; i < rotate_count; i++) {
302 SlotState temp = _outgoing.at(arg_slot + rotate_count - 1);
303 _outgoing.remove_at(arg_slot + rotate_count - 1);
304 _outgoing.insert_before(dest_arg_slot, temp);
305 }
306 }
307 break;
308 }
309
310 case sun_dyn_AdapterMethodHandle::OP_DUP_ARGS: {
311 int dup_slots = chain().adapter_conversion_stack_pushes();
312 if (dup_slots <= 0) {
313 lose("bad dup count", CHECK_NULL);
314 }
315 for (int i = 0; i < dup_slots; i++) {
316 SlotState* dup = slot_state(arg_slot + 2*i);
317 if (dup == NULL) break; // safety net
318 if (dup->_type != T_VOID) _outgoing_argc += 1;
319 _outgoing.insert_before(i, (*dup));
320 }
321 break;
322 }
323
324 case sun_dyn_AdapterMethodHandle::OP_DROP_ARGS: {
325 int drop_slots = -chain().adapter_conversion_stack_pushes();
326 if (drop_slots <= 0) {
327 lose("bad drop count", CHECK_NULL);
328 }
329 for (int i = 0; i < drop_slots; i++) {
330 SlotState* drop = slot_state(arg_slot);
331 if (drop == NULL) break; // safety net
332 if (drop->_type != T_VOID) _outgoing_argc -= 1;
333 _outgoing.remove_at(arg_slot);
334 }
335 break;
336 }
337
338 case sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC
339 lose("unimplemented", CHECK_NULL);
340 break;
341 }
342
343 case sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS: {
344 klassOop array_klass_oop = NULL;
345 BasicType array_type = java_lang_Class::as_BasicType(chain().adapter_arg_oop(),
346 &array_klass_oop);
347 assert(array_type == T_OBJECT, "");
348 assert(Klass::cast(array_klass_oop)->oop_is_array(), "");
349 arrayKlassHandle array_klass(THREAD, array_klass_oop);
350 debug_only(array_klass_oop = (klassOop)badOop);
351
352 klassOop element_klass_oop = NULL;
353 BasicType element_type = java_lang_Class::as_BasicType(array_klass->component_mirror(),
354 &element_klass_oop);
355 KlassHandle element_klass(THREAD, element_klass_oop);
356 debug_only(element_klass_oop = (klassOop)badOop);
357
358 // Fetch the argument, which we will cast to the required array type.
359 assert(arg_state->_type == T_OBJECT, "");
360 ArgToken array_arg = arg_state->_arg;
361 array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_NULL);
362 change_argument(T_OBJECT, arg_slot, T_VOID, NULL);
363
364 // Check the required length.
365 int spread_slots = 1 + chain().adapter_conversion_stack_pushes();
366 int spread_length = spread_slots;
367 if (type2size[element_type] == 2) {
368 if (spread_slots % 2 != 0) spread_slots = -1; // force error
369 spread_length = spread_slots / 2;
370 }
371 if (spread_slots < 0) {
372 lose("bad spread length", CHECK_NULL);
373 }
374
375 jvalue length_jvalue; length_jvalue.i = spread_length;
376 ArgToken length_arg = make_prim_constant(T_INT, &length_jvalue, CHECK_NULL);
377 // Call a built-in method known to the JVM to validate the length.
378 ArgToken arglist[3];
379 arglist[0] = array_arg; // value to check
380 arglist[1] = length_arg; // length to check
381 arglist[2] = NULL; // sentinel
382 make_invoke(NULL, vmIntrinsics::_checkSpreadArgument,
383 Bytecodes::_invokestatic, false, 3, &arglist[0], CHECK_NULL);
384
385 // Spread out the array elements.
386 Bytecodes::Code aload_op = Bytecodes::_aaload;
387 if (element_type != T_OBJECT) {
388 lose("primitive array NYI", CHECK_NULL);
389 }
390 int ap = arg_slot;
391 for (int i = 0; i < spread_length; i++) {
392 jvalue offset_jvalue; offset_jvalue.i = i;
393 ArgToken offset_arg = make_prim_constant(T_INT, &offset_jvalue, CHECK_NULL);
394 ArgToken element_arg = make_fetch(element_type, element_klass(), aload_op, array_arg, offset_arg, CHECK_NULL);
395 change_argument(T_VOID, ap, element_type, element_arg);
396 ap += type2size[element_type];
397 }
398 break;
399 }
400
401 case sun_dyn_AdapterMethodHandle::OP_FLYBY: //NYI, runs Java code
402 case sun_dyn_AdapterMethodHandle::OP_RICOCHET: //NYI, runs Java code
403 lose("unimplemented", CHECK_NULL);
404 break;
405
406 default:
407 lose("bad adapter conversion", CHECK_NULL);
408 break;
409 }
410 }
411
412 if (chain().is_bound()) {
413 // push a new argument
414 BasicType arg_type = chain().bound_arg_type();
415 jint arg_slot = chain().bound_arg_slot();
416 oop arg_oop = chain().bound_arg_oop();
417 ArgToken arg = NULL;
418 if (arg_type == T_OBJECT) {
419 arg = make_oop_constant(arg_oop, CHECK_NULL);
420 } else {
421 jvalue arg_value;
422 BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value);
423 if (bt == arg_type) {
424 arg = make_prim_constant(arg_type, &arg_value, CHECK_NULL);
425 } else {
426 lose("bad bound value", CHECK_NULL);
427 }
428 }
429 debug_only(arg_oop = badOop);
430 change_argument(T_VOID, arg_slot, arg_type, arg);
431 }
432
433 // this test must come after the body of the loop
434 if (!chain().is_last()) {
435 chain().next(CHECK_NULL);
436 } else {
437 break;
438 }
439 }
440
441 // finish the sequence with a tail-call to the ultimate target
442 // parameters are passed in logical order (recv 1st), not slot order
443 ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1);
444 int ap = 0;
445 for (int i = _outgoing.length() - 1; i >= 0; i--) {
446 SlotState* arg_state = slot_state(i);
447 if (arg_state->_type == T_VOID) continue;
448 arglist[ap++] = _outgoing.at(i)._arg;
449 }
450 assert(ap == _outgoing_argc, "");
451 arglist[ap] = NULL; // add a sentinel, for the sake of asserts
452 return make_invoke(chain().last_method_oop(),
453 vmIntrinsics::_none,
454 chain().last_invoke_code(), true,
455 ap, arglist, THREAD);
456 }
457
458 void MethodHandleWalker::walk_incoming_state(TRAPS) {
459 Handle mtype(THREAD, chain().method_type_oop());
460 int nptypes = java_dyn_MethodType::ptype_count(mtype());
461 _outgoing_argc = nptypes;
462 int argp = nptypes - 1;
463 if (argp >= 0) {
464 _outgoing.at_grow(argp, make_state(T_VOID, NULL)); // presize
465 }
466 for (int i = 0; i < nptypes; i++) {
467 klassOop arg_type_klass = NULL;
468 BasicType arg_type = java_lang_Class::as_BasicType(
469 java_dyn_MethodType::ptype(mtype(), i), &arg_type_klass);
470 ArgToken arg = make_parameter(arg_type, arg_type_klass, i, CHECK);
471 debug_only(arg_type_klass = (klassOop)NULL);
472 _outgoing.at_put(argp, make_state(arg_type, arg));
473 if (type2size[arg_type] == 2) {
474 // add the extra slot, so we can model the JVM stack
475 _outgoing.insert_before(argp+1, make_state(T_VOID, NULL));
476 }
477 --argp;
478 }
479 // call make_parameter at the end of the list for the return type
480 klassOop ret_type_klass = NULL;
481 BasicType ret_type = java_lang_Class::as_BasicType(
482 java_dyn_MethodType::rtype(mtype()), &ret_type_klass);
483 ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK);
484 // ignore ret; client can catch it if needed
485 }
486
487 // this is messy because some kinds of arguments are paired with
488 // companion slots containing an empty value
489 void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType new_type,
490 MethodHandleWalker::ArgToken new_arg) {
491 int old_size = type2size[old_type];
492 int new_size = type2size[new_type];
493 if (old_size == new_size) {
494 // simple case first
495 _outgoing.at_put(slot, make_state(new_type, new_arg));
496 } else if (old_size > new_size) {
497 for (int i = old_size-1; i >= new_size; i++) {
498 assert((i != 0) == (_outgoing.at(slot + i)._type == T_VOID), "");
499 _outgoing.remove_at(slot + i);
500 }
501 if (new_size > 0)
502 _outgoing.at_put(slot, make_state(new_type, new_arg));
503 else
504 _outgoing_argc -= 1; // deleted a real argument
505 } else {
506 for (int i = old_size; i < new_size; i++) {
507 _outgoing.insert_before(slot+i, make_state(T_VOID, NULL));
508 }
509 _outgoing.at_put(slot, make_state(new_type, new_arg));
510 if (old_size == 0)
511 _outgoing_argc += 1; // inserted a real argument
512 }
513 }
514
515
516 #ifdef ASSERT
517 int MethodHandleWalker::argument_count_slow() {
518 int args_seen = 0;
519 for (int i = _outgoing.length() - 1; i >= 0; i--) {
520 if (_outgoing.at(i)._type != T_VOID) {
521 ++args_seen;
522 }
523 }
524 return args_seen;
525 }
526 #endif
527
528
529 void MethodHandleCompiler::compile(TRAPS) {
530 assert(_thread == THREAD, "must be same thread");
531
532 _constant_oops.append(Handle()); // element zero is always the null constant
533 _constant_prims.append(NULL);
534 {
535 symbolOop sig
536 = java_dyn_MethodType::as_signature(chain().method_type_oop(), true, CHECK);
537 _signature_index = find_oop_constant(sig);
538 assert(signature() == sig, "");
539 }
540
541 walk(CHECK);
542 }
543
544 MethodHandleWalker::ArgToken
545 MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Code op,
546 MethodHandleWalker::ArgToken src, TRAPS) {
547 Unimplemented();
548 return NULL;
549 }
550
551 MethodHandleWalker::ArgToken
552 MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
553 Bytecodes::Code op, bool tailcall,
554 int argc, MethodHandleWalker::ArgToken* argv,
555 TRAPS) {
556 // If tailcall, we have walked all the way to a direct method handle.
557 // Otherwise, make a recursive call to some helper routine.
558 #ifdef ASSERT
559 switch (op) {
560 case Bytecodes::_invokevirtual:
561 case Bytecodes::_invokespecial:
562 case Bytecodes::_invokestatic:
563 case Bytecodes::_invokeinterface:
564 break;
565 default:
566 ShouldNotReachHere();
567 }
568 #endif //ASSERT
569 _bytes.put((char) op);
570
571 Unimplemented();
572 return NULL;
573 }
574
575 MethodHandleWalker::ArgToken
576 MethodHandleCompiler::make_fetch(BasicType type, klassOop tk, Bytecodes::Code op,
577 MethodHandleWalker::ArgToken base,
578 MethodHandleWalker::ArgToken offset,
579 TRAPS) {
580 Unimplemented();
581 return NULL;
582 }
583
584 int MethodHandleCompiler::find_oop_constant(oop con) {
585 if (con == NULL) return 0;
586 for (int i = 1, imax = _constant_oops.length(); i < imax; i++) {
587 if (_constant_oops.at(i) == con)
588 return i;
589 }
590 _constant_prims.append(NULL);
591 return _constant_oops.append(con);
592 }
593
594 int MethodHandleCompiler::find_prim_constant(BasicType bt, jvalue* con) {
595 jvalue con_copy;
596 assert(bt < T_OBJECT, "");
597 if (type2aelembytes(bt) < jintSize) {
598 // widen to int
599 con_copy = (*con);
600 con = &con_copy;
601 switch (bt) {
602 case T_BOOLEAN: con->i = (con->z ? 1 : 0); break;
603 case T_BYTE: con->i = con->b; break;
604 case T_CHAR: con->i = con->c; break;
605 case T_SHORT: con->i = con->s; break;
606 default: ShouldNotReachHere();
607 }
608 bt = T_INT;
609 }
610 for (int i = 1, imax = _constant_prims.length(); i < imax; i++) {
611 PrimCon* pcon = _constant_prims.at(i);
612 if (pcon != NULL && pcon->_type == bt) {
613 bool match = false;
614 switch (type2size[bt]) {
615 case 1: if (pcon->_value.i == con->i) match = true; break;
616 case 2: if (pcon->_value.j == con->j) match = true; break;
617 }
618 if (match)
619 return i;
620 }
621 }
622 PrimCon* pcon = new PrimCon();
623 pcon->_type = bt;
624 pcon->_value = (*con);
625 _constant_oops.append(Handle());
626 return _constant_prims.append(pcon);
627 }
628
629
630 #ifndef PRODUCT
631
632 // MH printer for debugging.
633
634 class MethodHandlePrinter : public MethodHandleWalker {
635 private:
636 outputStream* _out;
637 bool _verbose;
638 int _temp_num;
639 stringStream _strbuf;
640 const char* strbuf() {
641 const char* s = _strbuf.as_string();
642 _strbuf.reset();
643 return s;
644 }
645 ArgToken token(const char* str) {
646 return (ArgToken) str;
647 }
648 void start_params() {
649 _out->print("(");
650 }
651 void end_params() {
652 if (_verbose) _out->print("\n");
653 _out->print(") => {");
654 }
655 void put_type_name(BasicType type, klassOop tk, outputStream* s) {
656 const char* kname = NULL;
657 if (tk != NULL)
658 kname = Klass::cast(tk)->external_name();
659 s->print("%s", (kname != NULL) ? kname : type2name(type));
660 }
661 ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) {
662 const char* value = strbuf();
663 if (!_verbose) return token(value);
664 // make an explicit binding for each separate value
665 _strbuf.print("%s%d", temp_name, ++_temp_num);
666 const char* temp = strbuf();
667 _out->print("\n %s %s %s = %s;", statement_op, type2name(type), temp, value);
668 return token(temp);
669 }
670
671 public:
672 MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS)
673 : MethodHandleWalker(root, THREAD),
674 _out(out),
675 _verbose(verbose),
676 _temp_num(0)
677 {
678 start_params();
679 }
680 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
681 if (argnum < 0) {
682 end_params();
683 return NULL;
684 }
685 if (argnum == 0) {
686 _out->print(_verbose ? "\n " : "");
687 } else {
688 _out->print(_verbose ? ",\n " : ", ");
689 }
690 if (argnum >= _temp_num)
691 _temp_num = argnum;
692 // generate an argument name
693 _strbuf.print("a%d", argnum);
694 const char* arg = strbuf();
695 put_type_name(type, tk, _out);
696 _out->print(" %s", arg);
697 return token(arg);
698 }
699 virtual ArgToken make_oop_constant(oop con, TRAPS) {
700 if (con == NULL)
701 _strbuf.print("null");
702 else
703 con->print_value_on(&_strbuf);
704 if (_strbuf.size() == 0) { // yuck
705 _strbuf.print("(a ");
706 put_type_name(T_OBJECT, con->klass(), &_strbuf);
707 _strbuf.print(")");
708 }
709 return maybe_make_temp("constant", T_OBJECT, "k");
710 }
711 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
712 java_lang_boxing_object::print(type, con, &_strbuf);
713 return maybe_make_temp("constant", type, "k");
714 }
715 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS) {
716 _strbuf.print("%s(%s", Bytecodes::name(op), (const char*)src);
717 if (tk != NULL) {
718 _strbuf.print(", ");
719 put_type_name(type, tk, &_strbuf);
720 }
721 _strbuf.print(")");
722 return maybe_make_temp("convert", type, "v");
723 }
724 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS) {
725 _strbuf.print("%s(%s, %s", Bytecodes::name(op), (const char*)base, (const char*)offset);
726 if (tk != NULL) {
727 _strbuf.print(", ");
728 put_type_name(type, tk, &_strbuf);
729 }
730 _strbuf.print(")");
731 return maybe_make_temp("fetch", type, "x");
732 }
733 virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid,
734 Bytecodes::Code op, bool tailcall,
735 int argc, ArgToken* argv, TRAPS) {
736 symbolOop name, sig;
737 if (m != NULL) {
738 name = m->name();
739 sig = m->signature();
740 } else {
741 name = vmSymbols::symbol_at(vmIntrinsics::name_for(iid));
742 sig = vmSymbols::symbol_at(vmIntrinsics::signature_for(iid));
743 }
744 _strbuf.print("%s %s%s(", Bytecodes::name(op), name->as_C_string(), sig->as_C_string());
745 for (int i = 0; i < argc; i++) {
746 _strbuf.print("%s%s", (i > 0 ? ", " : ""), (const char*)argv[i]);
747 }
748 _strbuf.print(")");
749 if (!tailcall) {
750 BasicType rt = char2type(sig->byte_at(sig->utf8_length()-1));
751 if (rt == T_ILLEGAL) rt = T_OBJECT; // ';' at the end of '(...)L...;'
752 return maybe_make_temp("invoke", rt, "x");
753 } else {
754 const char* ret = strbuf();
755 _out->print(_verbose ? "\n return " : " ");
756 _out->print("%s", ret);
757 _out->print(_verbose ? "\n}\n" : " }");
758 }
759 return ArgToken();
760 }
761
762 virtual void set_method_handle(oop mh) {
763 if (WizardMode && Verbose) {
764 tty->print("\n--- next target: ");
765 mh->print();
766 }
767 }
768
769 static void print(Handle root, bool verbose, outputStream* out, TRAPS) {
770 ResourceMark rm;
771 MethodHandlePrinter printer(root, verbose, out, CHECK);
772 printer.walk(CHECK);
773 out->print("\n");
774 }
775 static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) {
776 EXCEPTION_MARK;
777 ResourceMark rm;
778 MethodHandlePrinter printer(root, verbose, out, THREAD);
779 if (!HAS_PENDING_EXCEPTION)
780 printer.walk(THREAD);
781 if (HAS_PENDING_EXCEPTION) {
782 oop ex = PENDING_EXCEPTION;
783 CLEAR_PENDING_EXCEPTION;
784 out->print("\n*** ");
785 if (ex != Universe::virtual_machine_error_instance())
786 ex->print_on(out);
787 else
788 out->print("lose: %s", printer.lose_message());
789 out->print("\n}\n");
790 }
791 out->print("\n");
792 }
793 };
794
795 extern "C"
796 void print_method_handle(oop mh) {
797 if (java_dyn_MethodHandle::is_instance(mh)) {
798 MethodHandlePrinter::print(mh);
799 } else {
800 tty->print("*** not a method handle: ");
801 mh->print();
802 }
803 }
804
805 #endif // PRODUCT