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