Mercurial > hg > truffle
annotate src/share/vm/prims/methodHandles.cpp @ 1716:be3f9c242c9d
6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
Summary: GC workers now recognize an intermediate transient state of blocks which are allocated but have not yet completed initialization. blk_start() calls do not attempt to determine the size of a block in the transient state, rather waiting for the block to become initialized so that it is safe to query its size. Audited and ensured the order of initialization of object fields (klass, free bit and size) to respect block state transition protocol. Also included some new assertion checking code enabled in debug mode.
Reviewed-by: chrisphi, johnc, poonam
author | ysr |
---|---|
date | Mon, 16 Aug 2010 15:58:42 -0700 |
parents | 083fde3b838e |
children | 3e8fbc61cee8 |
rev | line source |
---|---|
710 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1508
diff
changeset
|
2 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
710 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1508
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1508
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1508
diff
changeset
|
21 * questions. |
710 | 22 * |
23 */ | |
24 | |
25 /* | |
26 * JSR 292 reference implementation: method handles | |
27 */ | |
28 | |
29 #include "incls/_precompiled.incl" | |
30 #include "incls/_methodHandles.cpp.incl" | |
31 | |
32 bool MethodHandles::_enabled = false; // set true after successful native linkage | |
33 | |
34 MethodHandleEntry* MethodHandles::_entries[MethodHandles::_EK_LIMIT] = {NULL}; | |
35 const char* MethodHandles::_entry_names[_EK_LIMIT+1] = { | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
36 "raise_exception", |
710 | 37 "invokestatic", // how a MH emulates invokestatic |
38 "invokespecial", // ditto for the other invokes... | |
39 "invokevirtual", | |
40 "invokeinterface", | |
41 "bound_ref", // these are for BMH... | |
42 "bound_int", | |
43 "bound_long", | |
44 "bound_ref_direct", // (direct versions have a direct methodOop) | |
45 "bound_int_direct", | |
46 "bound_long_direct", | |
47 | |
48 // starting at _adapter_mh_first: | |
49 "adapter_retype_only", // these are for AMH... | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
50 "adapter_retype_raw", |
710 | 51 "adapter_check_cast", |
52 "adapter_prim_to_prim", | |
53 "adapter_ref_to_prim", | |
54 "adapter_prim_to_ref", | |
55 "adapter_swap_args", | |
56 "adapter_rot_args", | |
57 "adapter_dup_args", | |
58 "adapter_drop_args", | |
59 "adapter_collect_args", | |
60 "adapter_spread_args", | |
61 "adapter_flyby", | |
62 "adapter_ricochet", | |
63 | |
64 // optimized adapter types: | |
65 "adapter_swap_args/1", | |
66 "adapter_swap_args/2", | |
67 "adapter_rot_args/1,up", | |
68 "adapter_rot_args/1,down", | |
69 "adapter_rot_args/2,up", | |
70 "adapter_rot_args/2,down", | |
71 "adapter_prim_to_prim/i2i", | |
72 "adapter_prim_to_prim/l2i", | |
73 "adapter_prim_to_prim/d2f", | |
74 "adapter_prim_to_prim/i2l", | |
75 "adapter_prim_to_prim/f2d", | |
76 "adapter_ref_to_prim/unboxi", | |
77 "adapter_ref_to_prim/unboxl", | |
78 "adapter_spread_args/0", | |
79 "adapter_spread_args/1", | |
80 "adapter_spread_args/more", | |
81 | |
82 NULL | |
83 }; | |
84 | |
1299
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
85 // Adapters. |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
86 MethodHandlesAdapterBlob* MethodHandles::_adapter_code = NULL; |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
87 int MethodHandles::_adapter_code_size = StubRoutines::method_handles_adapters_code_size; |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
88 |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
89 jobject MethodHandles::_raise_exception_method; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
90 |
710 | 91 #ifdef ASSERT |
92 bool MethodHandles::spot_check_entry_names() { | |
93 assert(!strcmp(entry_name(_invokestatic_mh), "invokestatic"), ""); | |
94 assert(!strcmp(entry_name(_bound_ref_mh), "bound_ref"), ""); | |
95 assert(!strcmp(entry_name(_adapter_retype_only), "adapter_retype_only"), ""); | |
96 assert(!strcmp(entry_name(_adapter_ricochet), "adapter_ricochet"), ""); | |
97 assert(!strcmp(entry_name(_adapter_opt_unboxi), "adapter_ref_to_prim/unboxi"), ""); | |
98 return true; | |
99 } | |
100 #endif | |
101 | |
1299
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
102 |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
103 //------------------------------------------------------------------------------ |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
104 // MethodHandles::generate_adapters |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
105 // |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
106 void MethodHandles::generate_adapters() { |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
107 if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return; |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
108 |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
109 assert(_adapter_code == NULL, "generate only once"); |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
110 |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
111 ResourceMark rm; |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
112 TraceTime timer("MethodHandles adapters generation", TraceStartupTime); |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
113 _adapter_code = MethodHandlesAdapterBlob::create(_adapter_code_size); |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
114 if (_adapter_code == NULL) |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
115 vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters"); |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
116 CodeBuffer code(_adapter_code->instructions_begin(), _adapter_code->instructions_size()); |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
117 |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
118 MethodHandlesAdapterGenerator g(&code); |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
119 g.generate(); |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
120 } |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
121 |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
122 |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
123 //------------------------------------------------------------------------------ |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
124 // MethodHandlesAdapterGenerator::generate |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
125 // |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
126 void MethodHandlesAdapterGenerator::generate() { |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
127 // Generate generic method handle adapters. |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
128 for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
129 ek < MethodHandles::_EK_LIMIT; |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
130 ek = MethodHandles::EntryKind(1 + (int)ek)) { |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
131 StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
132 MethodHandles::generate_method_handle_stub(_masm, ek); |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
133 } |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
134 } |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
135 |
9eba43136cb5
6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob
twisti
parents:
1142
diff
changeset
|
136 |
710 | 137 void MethodHandles::set_enabled(bool z) { |
138 if (_enabled != z) { | |
139 guarantee(z && EnableMethodHandles, "can only enable once, and only if -XX:+EnableMethodHandles"); | |
140 _enabled = z; | |
141 } | |
142 } | |
143 | |
144 // Note: A method which does not have a TRAPS argument cannot block in the GC | |
145 // or throw exceptions. Such methods are used in this file to do something quick | |
146 // and local, like parse a data structure. For speed, such methods work on plain | |
147 // oops, not handles. Trapping methods uniformly operate on handles. | |
148 | |
149 methodOop MethodHandles::decode_vmtarget(oop vmtarget, int vmindex, oop mtype, | |
150 klassOop& receiver_limit_result, int& decode_flags_result) { | |
151 if (vmtarget == NULL) return NULL; | |
152 assert(methodOopDesc::nonvirtual_vtable_index < 0, "encoding"); | |
153 if (vmindex < 0) { | |
154 // this DMH performs no dispatch; it is directly bound to a methodOop | |
155 // A MemberName may either be directly bound to a methodOop, | |
156 // or it may use the klass/index form; both forms mean the same thing. | |
157 methodOop m = decode_methodOop(methodOop(vmtarget), decode_flags_result); | |
158 if ((decode_flags_result & _dmf_has_receiver) != 0 | |
159 && java_dyn_MethodType::is_instance(mtype)) { | |
160 // Extract receiver type restriction from mtype.ptypes[0]. | |
161 objArrayOop ptypes = java_dyn_MethodType::ptypes(mtype); | |
162 oop ptype0 = (ptypes == NULL || ptypes->length() < 1) ? oop(NULL) : ptypes->obj_at(0); | |
163 if (java_lang_Class::is_instance(ptype0)) | |
164 receiver_limit_result = java_lang_Class::as_klassOop(ptype0); | |
165 } | |
166 if (vmindex == methodOopDesc::nonvirtual_vtable_index) { | |
167 // this DMH can be an "invokespecial" version | |
168 decode_flags_result &= ~_dmf_does_dispatch; | |
169 } else { | |
170 assert(vmindex == methodOopDesc::invalid_vtable_index, "random vmindex?"); | |
171 } | |
172 return m; | |
173 } else { | |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
174 assert(vmtarget->is_klass(), "must be class or interface"); |
710 | 175 decode_flags_result |= MethodHandles::_dmf_does_dispatch; |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
176 decode_flags_result |= MethodHandles::_dmf_has_receiver; |
710 | 177 receiver_limit_result = (klassOop)vmtarget; |
178 Klass* tk = Klass::cast((klassOop)vmtarget); | |
179 if (tk->is_interface()) { | |
180 // an itable linkage is <interface, itable index> | |
181 decode_flags_result |= MethodHandles::_dmf_from_interface; | |
182 return klassItable::method_for_itable_index((klassOop)vmtarget, vmindex); | |
183 } else { | |
184 if (!tk->oop_is_instance()) | |
1142 | 185 tk = instanceKlass::cast(SystemDictionary::Object_klass()); |
710 | 186 return ((instanceKlass*)tk)->method_at_vtable(vmindex); |
187 } | |
188 } | |
189 } | |
190 | |
191 // MemberName and DirectMethodHandle have the same linkage to the JVM internals. | |
192 // (MemberName is the non-operational name used for queries and setup.) | |
193 | |
194 methodOop MethodHandles::decode_DirectMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { | |
195 oop vmtarget = sun_dyn_DirectMethodHandle::vmtarget(mh); | |
196 int vmindex = sun_dyn_DirectMethodHandle::vmindex(mh); | |
197 oop mtype = sun_dyn_DirectMethodHandle::type(mh); | |
198 return decode_vmtarget(vmtarget, vmindex, mtype, receiver_limit_result, decode_flags_result); | |
199 } | |
200 | |
201 methodOop MethodHandles::decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
202 assert(sun_dyn_BoundMethodHandle::is_instance(mh), ""); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
203 assert(mh->klass() != SystemDictionary::AdapterMethodHandle_klass(), ""); |
710 | 204 for (oop bmh = mh;;) { |
205 // Bound MHs can be stacked to bind several arguments. | |
206 oop target = java_dyn_MethodHandle::vmtarget(bmh); | |
207 if (target == NULL) return NULL; | |
208 decode_flags_result |= MethodHandles::_dmf_binds_argument; | |
209 klassOop tk = target->klass(); | |
210 if (tk == SystemDictionary::BoundMethodHandle_klass()) { | |
211 bmh = target; | |
212 continue; | |
213 } else { | |
214 if (java_dyn_MethodHandle::is_subclass(tk)) { | |
215 //assert(tk == SystemDictionary::DirectMethodHandle_klass(), "end of BMH chain must be DMH"); | |
216 return decode_MethodHandle(target, receiver_limit_result, decode_flags_result); | |
217 } else { | |
218 // Optimized case: binding a receiver to a non-dispatched DMH | |
219 // short-circuits directly to the methodOop. | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
220 // (It might be another argument besides a receiver also.) |
710 | 221 assert(target->is_method(), "must be a simple method"); |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
222 decode_flags_result |= MethodHandles::_dmf_binds_method; |
710 | 223 methodOop m = (methodOop) target; |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
224 if (!m->is_static()) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
225 decode_flags_result |= MethodHandles::_dmf_has_receiver; |
710 | 226 return m; |
227 } | |
228 } | |
229 } | |
230 } | |
231 | |
232 methodOop MethodHandles::decode_AdapterMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { | |
233 assert(mh->klass() == SystemDictionary::AdapterMethodHandle_klass(), ""); | |
234 for (oop amh = mh;;) { | |
235 // Adapter MHs can be stacked to convert several arguments. | |
236 int conv_op = adapter_conversion_op(sun_dyn_AdapterMethodHandle::conversion(amh)); | |
237 decode_flags_result |= (_dmf_adapter_lsb << conv_op) & _DMF_ADAPTER_MASK; | |
238 oop target = java_dyn_MethodHandle::vmtarget(amh); | |
239 if (target == NULL) return NULL; | |
240 klassOop tk = target->klass(); | |
241 if (tk == SystemDictionary::AdapterMethodHandle_klass()) { | |
242 amh = target; | |
243 continue; | |
244 } else { | |
245 // must be a BMH (which will bind some more arguments) or a DMH (for the final call) | |
246 return MethodHandles::decode_MethodHandle(target, receiver_limit_result, decode_flags_result); | |
247 } | |
248 } | |
249 } | |
250 | |
251 methodOop MethodHandles::decode_MethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { | |
252 if (mh == NULL) return NULL; | |
253 klassOop mhk = mh->klass(); | |
254 assert(java_dyn_MethodHandle::is_subclass(mhk), "must be a MethodHandle"); | |
255 if (mhk == SystemDictionary::DirectMethodHandle_klass()) { | |
256 return decode_DirectMethodHandle(mh, receiver_limit_result, decode_flags_result); | |
257 } else if (mhk == SystemDictionary::BoundMethodHandle_klass()) { | |
258 return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result); | |
259 } else if (mhk == SystemDictionary::AdapterMethodHandle_klass()) { | |
260 return decode_AdapterMethodHandle(mh, receiver_limit_result, decode_flags_result); | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
261 } else if (sun_dyn_BoundMethodHandle::is_subclass(mhk)) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
262 // could be a JavaMethodHandle (but not an adapter MH) |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
263 return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result); |
710 | 264 } else { |
265 assert(false, "cannot parse this MH"); | |
266 return NULL; // random MH? | |
267 } | |
268 } | |
269 | |
270 methodOop MethodHandles::decode_methodOop(methodOop m, int& decode_flags_result) { | |
271 assert(m->is_method(), ""); | |
272 if (m->is_static()) { | |
273 // check that signature begins '(L' or '([' (not '(I', '()', etc.) | |
274 symbolOop sig = m->signature(); | |
275 BasicType recv_bt = char2type(sig->byte_at(1)); | |
276 // Note: recv_bt might be T_ILLEGAL if byte_at(2) is ')' | |
277 assert(sig->byte_at(0) == '(', "must be method sig"); | |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
278 // if (recv_bt == T_OBJECT || recv_bt == T_ARRAY) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
279 // decode_flags_result |= _dmf_has_receiver; |
710 | 280 } else { |
281 // non-static method | |
282 decode_flags_result |= _dmf_has_receiver; | |
283 if (!m->can_be_statically_bound() && !m->is_initializer()) { | |
284 decode_flags_result |= _dmf_does_dispatch; | |
285 if (Klass::cast(m->method_holder())->is_interface()) | |
286 decode_flags_result |= _dmf_from_interface; | |
287 } | |
288 } | |
289 return m; | |
290 } | |
291 | |
292 | |
293 // A trusted party is handing us a cookie to determine a method. | |
294 // Let's boil it down to the method oop they really want. | |
295 methodOop MethodHandles::decode_method(oop x, klassOop& receiver_limit_result, int& decode_flags_result) { | |
296 decode_flags_result = 0; | |
297 receiver_limit_result = NULL; | |
298 klassOop xk = x->klass(); | |
299 if (xk == Universe::methodKlassObj()) { | |
300 return decode_methodOop((methodOop) x, decode_flags_result); | |
301 } else if (xk == SystemDictionary::MemberName_klass()) { | |
302 // Note: This only works if the MemberName has already been resolved. | |
303 return decode_MemberName(x, receiver_limit_result, decode_flags_result); | |
304 } else if (java_dyn_MethodHandle::is_subclass(xk)) { | |
305 return decode_MethodHandle(x, receiver_limit_result, decode_flags_result); | |
1142 | 306 } else if (xk == SystemDictionary::reflect_Method_klass()) { |
710 | 307 oop clazz = java_lang_reflect_Method::clazz(x); |
308 int slot = java_lang_reflect_Method::slot(x); | |
309 klassOop k = java_lang_Class::as_klassOop(clazz); | |
310 if (k != NULL && Klass::cast(k)->oop_is_instance()) | |
311 return decode_methodOop(instanceKlass::cast(k)->method_with_idnum(slot), | |
312 decode_flags_result); | |
1142 | 313 } else if (xk == SystemDictionary::reflect_Constructor_klass()) { |
710 | 314 oop clazz = java_lang_reflect_Constructor::clazz(x); |
315 int slot = java_lang_reflect_Constructor::slot(x); | |
316 klassOop k = java_lang_Class::as_klassOop(clazz); | |
317 if (k != NULL && Klass::cast(k)->oop_is_instance()) | |
318 return decode_methodOop(instanceKlass::cast(k)->method_with_idnum(slot), | |
319 decode_flags_result); | |
320 } else { | |
321 // unrecognized object | |
322 assert(!x->is_method(), "already checked"); | |
323 assert(!sun_dyn_MemberName::is_instance(x), "already checked"); | |
324 } | |
325 return NULL; | |
326 } | |
327 | |
328 | |
329 int MethodHandles::decode_MethodHandle_stack_pushes(oop mh) { | |
330 if (mh->klass() == SystemDictionary::DirectMethodHandle_klass()) | |
331 return 0; // no push/pop | |
332 int this_vmslots = java_dyn_MethodHandle::vmslots(mh); | |
333 int last_vmslots = 0; | |
334 oop last_mh = mh; | |
335 for (;;) { | |
336 oop target = java_dyn_MethodHandle::vmtarget(last_mh); | |
337 if (target->klass() == SystemDictionary::DirectMethodHandle_klass()) { | |
338 last_vmslots = java_dyn_MethodHandle::vmslots(target); | |
339 break; | |
340 } else if (!java_dyn_MethodHandle::is_instance(target)) { | |
341 // might be klass or method | |
342 assert(target->is_method(), "must get here with a direct ref to method"); | |
343 last_vmslots = methodOop(target)->size_of_parameters(); | |
344 break; | |
345 } | |
346 last_mh = target; | |
347 } | |
348 // If I am called with fewer VM slots than my ultimate callee, | |
349 // it must be that I push the additionally needed slots. | |
350 // Likewise if am called with more VM slots, I will pop them. | |
351 return (last_vmslots - this_vmslots); | |
352 } | |
353 | |
354 | |
355 // MemberName support | |
356 | |
357 // import sun_dyn_MemberName.* | |
358 enum { | |
359 IS_METHOD = sun_dyn_MemberName::MN_IS_METHOD, | |
360 IS_CONSTRUCTOR = sun_dyn_MemberName::MN_IS_CONSTRUCTOR, | |
361 IS_FIELD = sun_dyn_MemberName::MN_IS_FIELD, | |
362 IS_TYPE = sun_dyn_MemberName::MN_IS_TYPE, | |
363 SEARCH_SUPERCLASSES = sun_dyn_MemberName::MN_SEARCH_SUPERCLASSES, | |
364 SEARCH_INTERFACES = sun_dyn_MemberName::MN_SEARCH_INTERFACES, | |
365 ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE, | |
366 VM_INDEX_UNINITIALIZED = sun_dyn_MemberName::VM_INDEX_UNINITIALIZED | |
367 }; | |
368 | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
369 Handle MethodHandles::new_MemberName(TRAPS) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
370 Handle empty; |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
371 instanceKlassHandle k(THREAD, SystemDictionary::MemberName_klass()); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
372 if (!k->is_initialized()) k->initialize(CHECK_(empty)); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
373 return Handle(THREAD, k->allocate_instance(THREAD)); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
374 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
375 |
710 | 376 void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { |
1142 | 377 if (target_oop->klass() == SystemDictionary::reflect_Field_klass()) { |
710 | 378 oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() |
379 int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() | |
380 int mods = java_lang_reflect_Field::modifiers(target_oop); | |
381 klassOop k = java_lang_Class::as_klassOop(clazz); | |
382 int offset = instanceKlass::cast(k)->offset_from_fields(slot); | |
383 init_MemberName(mname_oop, k, accessFlags_from(mods), offset); | |
384 } else { | |
385 int decode_flags = 0; klassOop receiver_limit = NULL; | |
386 methodOop m = MethodHandles::decode_method(target_oop, | |
387 receiver_limit, decode_flags); | |
388 bool do_dispatch = ((decode_flags & MethodHandles::_dmf_does_dispatch) != 0); | |
389 init_MemberName(mname_oop, m, do_dispatch); | |
390 } | |
391 } | |
392 | |
393 void MethodHandles::init_MemberName(oop mname_oop, methodOop m, bool do_dispatch) { | |
394 int flags = ((m->is_initializer() ? IS_CONSTRUCTOR : IS_METHOD) | |
395 | (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS )); | |
396 oop vmtarget = m; | |
397 int vmindex = methodOopDesc::invalid_vtable_index; // implies no info yet | |
398 if (!do_dispatch || (flags & IS_CONSTRUCTOR) || m->can_be_statically_bound()) | |
399 vmindex = methodOopDesc::nonvirtual_vtable_index; // implies never any dispatch | |
400 assert(vmindex != VM_INDEX_UNINITIALIZED, "Java sentinel value"); | |
401 sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); | |
402 sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); | |
403 sun_dyn_MemberName::set_flags(mname_oop, flags); | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
404 sun_dyn_MemberName::set_clazz(mname_oop, Klass::cast(m->method_holder())->java_mirror()); |
710 | 405 } |
406 | |
407 void MethodHandles::init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset) { | |
408 int flags = (IS_FIELD | (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS )); | |
409 oop vmtarget = field_holder; | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
410 int vmindex = offset; // determines the field uniquely when combined with static bit |
710 | 411 assert(vmindex != VM_INDEX_UNINITIALIZED, "bad alias on vmindex"); |
412 sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); | |
413 sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); | |
414 sun_dyn_MemberName::set_flags(mname_oop, flags); | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
415 sun_dyn_MemberName::set_clazz(mname_oop, Klass::cast(field_holder)->java_mirror()); |
710 | 416 } |
417 | |
418 | |
419 methodOop MethodHandles::decode_MemberName(oop mname, klassOop& receiver_limit_result, int& decode_flags_result) { | |
420 int flags = sun_dyn_MemberName::flags(mname); | |
421 if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) == 0) return NULL; // not invocable | |
422 oop vmtarget = sun_dyn_MemberName::vmtarget(mname); | |
423 int vmindex = sun_dyn_MemberName::vmindex(mname); | |
424 if (vmindex == VM_INDEX_UNINITIALIZED) return NULL; // not resolved | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
425 methodOop m = decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
426 oop clazz = sun_dyn_MemberName::clazz(mname); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
427 if (clazz != NULL && java_lang_Class::is_instance(clazz)) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
428 klassOop klass = java_lang_Class::as_klassOop(clazz); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
429 if (klass != NULL) receiver_limit_result = klass; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
430 } |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
431 return m; |
710 | 432 } |
433 | |
434 // An unresolved member name is a mere symbolic reference. | |
435 // Resolving it plants a vmtarget/vmindex in it, | |
436 // which refers dirctly to JVM internals. | |
437 void MethodHandles::resolve_MemberName(Handle mname, TRAPS) { | |
438 assert(sun_dyn_MemberName::is_instance(mname()), ""); | |
439 #ifdef ASSERT | |
440 // If this assert throws, renegotiate the sentinel value used by the Java code, | |
441 // so that it is distinct from any valid vtable index value, and any special | |
442 // values defined in methodOopDesc::VtableIndexFlag. | |
443 // The point of the slop is to give the Java code and the JVM some room | |
444 // to independently specify sentinel values. | |
445 const int sentinel_slop = 10; | |
446 const int sentinel_limit = methodOopDesc::highest_unused_vtable_index_value - sentinel_slop; | |
447 assert(VM_INDEX_UNINITIALIZED < sentinel_limit, "Java sentinel != JVM sentinels"); | |
448 #endif | |
449 if (sun_dyn_MemberName::vmindex(mname()) != VM_INDEX_UNINITIALIZED) | |
450 return; // already resolved | |
451 oop defc_oop = sun_dyn_MemberName::clazz(mname()); | |
452 oop name_str = sun_dyn_MemberName::name(mname()); | |
453 oop type_str = sun_dyn_MemberName::type(mname()); | |
454 int flags = sun_dyn_MemberName::flags(mname()); | |
455 | |
456 if (defc_oop == NULL || name_str == NULL || type_str == NULL) { | |
457 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to resolve"); | |
458 } | |
459 klassOop defc_klassOop = java_lang_Class::as_klassOop(defc_oop); | |
460 defc_oop = NULL; // safety | |
461 if (defc_klassOop == NULL) return; // a primitive; no resolution possible | |
462 if (!Klass::cast(defc_klassOop)->oop_is_instance()) { | |
463 if (!Klass::cast(defc_klassOop)->oop_is_array()) return; | |
1142 | 464 defc_klassOop = SystemDictionary::Object_klass(); |
710 | 465 } |
466 instanceKlassHandle defc(THREAD, defc_klassOop); | |
467 defc_klassOop = NULL; // safety | |
468 if (defc.is_null()) { | |
469 THROW_MSG(vmSymbols::java_lang_InternalError(), "primitive class"); | |
470 } | |
471 defc->link_class(CHECK); | |
472 | |
473 // convert the external string name to an internal symbol | |
474 symbolHandle name(THREAD, java_lang_String::as_symbol_or_null(name_str)); | |
475 if (name.is_null()) return; // no such name | |
476 name_str = NULL; // safety | |
477 | |
1508
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
478 Handle polymorphic_method_type; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
479 bool polymorphic_signature = false; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
480 if ((flags & ALL_KINDS) == IS_METHOD && |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
481 (defc() == SystemDictionary::InvokeDynamic_klass() || |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
482 (defc() == SystemDictionary::MethodHandle_klass() && |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
483 methodOopDesc::is_method_handle_invoke_name(name())))) |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
484 polymorphic_signature = true; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
485 |
710 | 486 // convert the external string or reflective type to an internal signature |
487 symbolHandle type; { | |
488 symbolOop type_sym = NULL; | |
489 if (java_dyn_MethodType::is_instance(type_str)) { | |
1508
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
490 type_sym = java_dyn_MethodType::as_signature(type_str, polymorphic_signature, CHECK); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
491 if (polymorphic_signature) |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
492 polymorphic_method_type = Handle(THREAD, type_str); //preserve exactly |
710 | 493 } else if (java_lang_Class::is_instance(type_str)) { |
1508
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
494 type_sym = java_lang_Class::as_signature(type_str, false, CHECK); |
710 | 495 } else if (java_lang_String::is_instance(type_str)) { |
1508
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
496 if (polymorphic_signature) { |
710 | 497 type = java_lang_String::as_symbol(type_str, CHECK); |
498 } else { | |
499 type_sym = java_lang_String::as_symbol_or_null(type_str); | |
500 } | |
501 } else { | |
502 THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized type"); | |
503 } | |
504 if (type_sym != NULL) | |
505 type = symbolHandle(THREAD, type_sym); | |
506 } | |
507 if (type.is_null()) return; // no such signature exists in the VM | |
508 type_str = NULL; // safety | |
509 | |
510 // Time to do the lookup. | |
511 switch (flags & ALL_KINDS) { | |
512 case IS_METHOD: | |
513 { | |
514 CallInfo result; | |
515 { | |
516 EXCEPTION_MARK; | |
517 if ((flags & JVM_ACC_STATIC) != 0) { | |
518 LinkResolver::resolve_static_call(result, | |
519 defc, name, type, KlassHandle(), false, false, THREAD); | |
520 } else if (defc->is_interface()) { | |
521 LinkResolver::resolve_interface_call(result, Handle(), defc, | |
522 defc, name, type, KlassHandle(), false, false, THREAD); | |
523 } else { | |
524 LinkResolver::resolve_virtual_call(result, Handle(), defc, | |
525 defc, name, type, KlassHandle(), false, false, THREAD); | |
526 } | |
527 if (HAS_PENDING_EXCEPTION) { | |
528 CLEAR_PENDING_EXCEPTION; | |
1508
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
529 break; // go to second chance |
710 | 530 } |
531 } | |
532 methodHandle m = result.resolved_method(); | |
533 oop vmtarget = NULL; | |
534 int vmindex = methodOopDesc::nonvirtual_vtable_index; | |
535 if (defc->is_interface()) { | |
536 vmindex = klassItable::compute_itable_index(m()); | |
537 assert(vmindex >= 0, ""); | |
538 } else if (result.has_vtable_index()) { | |
539 vmindex = result.vtable_index(); | |
540 assert(vmindex >= 0, ""); | |
541 } | |
542 assert(vmindex != VM_INDEX_UNINITIALIZED, ""); | |
543 if (vmindex < 0) { | |
544 assert(result.is_statically_bound(), ""); | |
545 vmtarget = m(); | |
546 } else { | |
547 vmtarget = result.resolved_klass()->as_klassOop(); | |
548 } | |
549 int mods = (m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS); | |
550 sun_dyn_MemberName::set_vmtarget(mname(), vmtarget); | |
551 sun_dyn_MemberName::set_vmindex(mname(), vmindex); | |
552 sun_dyn_MemberName::set_modifiers(mname(), mods); | |
553 DEBUG_ONLY(int junk; klassOop junk2); | |
554 assert(decode_MemberName(mname(), junk2, junk) == result.resolved_method()(), | |
555 "properly stored for later decoding"); | |
556 return; | |
557 } | |
558 case IS_CONSTRUCTOR: | |
559 { | |
560 CallInfo result; | |
561 { | |
562 EXCEPTION_MARK; | |
563 if (name() == vmSymbols::object_initializer_name()) { | |
564 LinkResolver::resolve_special_call(result, | |
565 defc, name, type, KlassHandle(), false, THREAD); | |
566 } else { | |
567 break; // will throw after end of switch | |
568 } | |
569 if (HAS_PENDING_EXCEPTION) { | |
570 CLEAR_PENDING_EXCEPTION; | |
571 return; | |
572 } | |
573 } | |
574 assert(result.is_statically_bound(), ""); | |
575 methodHandle m = result.resolved_method(); | |
576 oop vmtarget = m(); | |
577 int vmindex = methodOopDesc::nonvirtual_vtable_index; | |
578 int mods = (m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS); | |
579 sun_dyn_MemberName::set_vmtarget(mname(), vmtarget); | |
580 sun_dyn_MemberName::set_vmindex(mname(), vmindex); | |
581 sun_dyn_MemberName::set_modifiers(mname(), mods); | |
582 DEBUG_ONLY(int junk; klassOop junk2); | |
583 assert(decode_MemberName(mname(), junk2, junk) == result.resolved_method()(), | |
584 "properly stored for later decoding"); | |
585 return; | |
586 } | |
587 case IS_FIELD: | |
588 { | |
589 // This is taken from LinkResolver::resolve_field, sans access checks. | |
590 fieldDescriptor fd; // find_field initializes fd if found | |
591 KlassHandle sel_klass(THREAD, instanceKlass::cast(defc())->find_field(name(), type(), &fd)); | |
592 // check if field exists; i.e., if a klass containing the field def has been selected | |
593 if (sel_klass.is_null()) return; | |
594 oop vmtarget = sel_klass->as_klassOop(); | |
595 int vmindex = fd.offset(); | |
596 int mods = (fd.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS); | |
597 if (vmindex == VM_INDEX_UNINITIALIZED) break; // should not happen | |
598 sun_dyn_MemberName::set_vmtarget(mname(), vmtarget); | |
599 sun_dyn_MemberName::set_vmindex(mname(), vmindex); | |
600 sun_dyn_MemberName::set_modifiers(mname(), mods); | |
601 return; | |
602 } | |
1508
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
603 default: |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
604 THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format"); |
710 | 605 } |
1508
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
606 |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
607 // Second chance. |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
608 if (polymorphic_method_type.not_null()) { |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
609 // Look on a non-null class loader. |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
610 Handle cur_class_loader; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
611 const int nptypes = java_dyn_MethodType::ptype_count(polymorphic_method_type()); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
612 for (int i = 0; i <= nptypes; i++) { |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
613 oop type_mirror; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
614 if (i < nptypes) type_mirror = java_dyn_MethodType::ptype(polymorphic_method_type(), i); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
615 else type_mirror = java_dyn_MethodType::rtype(polymorphic_method_type()); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
616 klassOop example_type = java_lang_Class::as_klassOop(type_mirror); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
617 if (example_type == NULL) continue; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
618 oop class_loader = Klass::cast(example_type)->class_loader(); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
619 if (class_loader == NULL || class_loader == cur_class_loader()) continue; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
620 cur_class_loader = Handle(THREAD, class_loader); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
621 methodOop m = SystemDictionary::find_method_handle_invoke(name, |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
622 type, |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
623 KlassHandle(THREAD, example_type), |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
624 THREAD); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
625 if (HAS_PENDING_EXCEPTION) { |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
626 CLEAR_PENDING_EXCEPTION; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
627 m = NULL; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
628 // try again with a different class loader... |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
629 } |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
630 if (m != NULL) { |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
631 int mods = (m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
632 sun_dyn_MemberName::set_vmtarget(mname(), m); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
633 sun_dyn_MemberName::set_vmindex(mname(), m->vtable_index()); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
634 sun_dyn_MemberName::set_modifiers(mname(), mods); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
635 return; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
636 } |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
637 } |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
638 } |
710 | 639 } |
640 | |
641 // Conversely, a member name which is only initialized from JVM internals | |
642 // may have null defc, name, and type fields. | |
643 // Resolving it plants a vmtarget/vmindex in it, | |
644 // which refers directly to JVM internals. | |
645 void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) { | |
646 assert(sun_dyn_MemberName::is_instance(mname()), ""); | |
647 oop vmtarget = sun_dyn_MemberName::vmtarget(mname()); | |
648 int vmindex = sun_dyn_MemberName::vmindex(mname()); | |
649 if (vmtarget == NULL || vmindex == VM_INDEX_UNINITIALIZED) { | |
650 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to expand"); | |
651 } | |
652 | |
653 bool have_defc = (sun_dyn_MemberName::clazz(mname()) != NULL); | |
654 bool have_name = (sun_dyn_MemberName::name(mname()) != NULL); | |
655 bool have_type = (sun_dyn_MemberName::type(mname()) != NULL); | |
656 int flags = sun_dyn_MemberName::flags(mname()); | |
657 | |
658 if (suppress != 0) { | |
659 if (suppress & _suppress_defc) have_defc = true; | |
660 if (suppress & _suppress_name) have_name = true; | |
661 if (suppress & _suppress_type) have_type = true; | |
662 } | |
663 | |
664 if (have_defc && have_name && have_type) return; // nothing needed | |
665 | |
666 switch (flags & ALL_KINDS) { | |
667 case IS_METHOD: | |
668 case IS_CONSTRUCTOR: | |
669 { | |
670 klassOop receiver_limit = NULL; | |
671 int decode_flags = 0; | |
672 methodHandle m(THREAD, decode_vmtarget(vmtarget, vmindex, NULL, | |
673 receiver_limit, decode_flags)); | |
674 if (m.is_null()) break; | |
675 if (!have_defc) { | |
676 klassOop defc = m->method_holder(); | |
677 if (receiver_limit != NULL && receiver_limit != defc | |
678 && Klass::cast(receiver_limit)->is_subtype_of(defc)) | |
679 defc = receiver_limit; | |
680 sun_dyn_MemberName::set_clazz(mname(), Klass::cast(defc)->java_mirror()); | |
681 } | |
682 if (!have_name) { | |
683 //not java_lang_String::create_from_symbol; let's intern member names | |
684 Handle name = StringTable::intern(m->name(), CHECK); | |
685 sun_dyn_MemberName::set_name(mname(), name()); | |
686 } | |
687 if (!have_type) { | |
688 Handle type = java_lang_String::create_from_symbol(m->signature(), CHECK); | |
689 sun_dyn_MemberName::set_type(mname(), type()); | |
690 } | |
691 return; | |
692 } | |
693 case IS_FIELD: | |
694 { | |
695 // This is taken from LinkResolver::resolve_field, sans access checks. | |
696 if (!vmtarget->is_klass()) break; | |
697 if (!Klass::cast((klassOop) vmtarget)->oop_is_instance()) break; | |
698 instanceKlassHandle defc(THREAD, (klassOop) vmtarget); | |
699 bool is_static = ((flags & JVM_ACC_STATIC) != 0); | |
700 fieldDescriptor fd; // find_field initializes fd if found | |
701 if (!defc->find_field_from_offset(vmindex, is_static, &fd)) | |
702 break; // cannot expand | |
703 if (!have_defc) { | |
704 sun_dyn_MemberName::set_clazz(mname(), defc->java_mirror()); | |
705 } | |
706 if (!have_name) { | |
707 //not java_lang_String::create_from_symbol; let's intern member names | |
708 Handle name = StringTable::intern(fd.name(), CHECK); | |
709 sun_dyn_MemberName::set_name(mname(), name()); | |
710 } | |
711 if (!have_type) { | |
712 Handle type = java_lang_String::create_from_symbol(fd.signature(), CHECK); | |
713 sun_dyn_MemberName::set_type(mname(), type()); | |
714 } | |
715 return; | |
716 } | |
717 } | |
718 THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format"); | |
719 } | |
720 | |
721 int MethodHandles::find_MemberNames(klassOop k, | |
722 symbolOop name, symbolOop sig, | |
723 int mflags, klassOop caller, | |
724 int skip, objArrayOop results) { | |
725 DEBUG_ONLY(No_Safepoint_Verifier nsv); | |
726 // this code contains no safepoints! | |
727 | |
728 // %%% take caller into account! | |
729 | |
730 if (k == NULL || !Klass::cast(k)->oop_is_instance()) return -1; | |
731 | |
732 int rfill = 0, rlimit = results->length(), rskip = skip; | |
733 // overflow measurement: | |
734 int overflow = 0, overflow_limit = MAX2(1000, rlimit); | |
735 | |
736 int match_flags = mflags; | |
737 bool search_superc = ((match_flags & SEARCH_SUPERCLASSES) != 0); | |
738 bool search_intfc = ((match_flags & SEARCH_INTERFACES) != 0); | |
739 bool local_only = !(search_superc | search_intfc); | |
740 bool classes_only = false; | |
741 | |
742 if (name != NULL) { | |
743 if (name->utf8_length() == 0) return 0; // a match is not possible | |
744 } | |
745 if (sig != NULL) { | |
746 if (sig->utf8_length() == 0) return 0; // a match is not possible | |
747 if (sig->byte_at(0) == '(') | |
748 match_flags &= ~(IS_FIELD | IS_TYPE); | |
749 else | |
750 match_flags &= ~(IS_CONSTRUCTOR | IS_METHOD); | |
751 } | |
752 | |
753 if ((match_flags & IS_TYPE) != 0) { | |
754 // NYI, and Core Reflection works quite well for this query | |
755 } | |
756 | |
757 if ((match_flags & IS_FIELD) != 0) { | |
758 for (FieldStream st(k, local_only, !search_intfc); !st.eos(); st.next()) { | |
759 if (name != NULL && st.name() != name) | |
760 continue; | |
761 if (sig != NULL && st.signature() != sig) | |
762 continue; | |
763 // passed the filters | |
764 if (rskip > 0) { | |
765 --rskip; | |
766 } else if (rfill < rlimit) { | |
767 oop result = results->obj_at(rfill++); | |
768 if (!sun_dyn_MemberName::is_instance(result)) | |
769 return -99; // caller bug! | |
770 MethodHandles::init_MemberName(result, st.klass()->as_klassOop(), st.access_flags(), st.offset()); | |
771 } else if (++overflow >= overflow_limit) { | |
772 match_flags = 0; break; // got tired of looking at overflow | |
773 } | |
774 } | |
775 } | |
776 | |
777 if ((match_flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) { | |
778 // watch out for these guys: | |
779 symbolOop init_name = vmSymbols::object_initializer_name(); | |
780 symbolOop clinit_name = vmSymbols::class_initializer_name(); | |
781 if (name == clinit_name) clinit_name = NULL; // hack for exposing <clinit> | |
782 bool negate_name_test = false; | |
783 // fix name so that it captures the intention of IS_CONSTRUCTOR | |
784 if (!(match_flags & IS_METHOD)) { | |
785 // constructors only | |
786 if (name == NULL) { | |
787 name = init_name; | |
788 } else if (name != init_name) { | |
789 return 0; // no constructors of this method name | |
790 } | |
791 } else if (!(match_flags & IS_CONSTRUCTOR)) { | |
792 // methods only | |
793 if (name == NULL) { | |
794 name = init_name; | |
795 negate_name_test = true; // if we see the name, we *omit* the entry | |
796 } else if (name == init_name) { | |
797 return 0; // no methods of this constructor name | |
798 } | |
799 } else { | |
800 // caller will accept either sort; no need to adjust name | |
801 } | |
802 for (MethodStream st(k, local_only, !search_intfc); !st.eos(); st.next()) { | |
803 methodOop m = st.method(); | |
804 symbolOop m_name = m->name(); | |
805 if (m_name == clinit_name) | |
806 continue; | |
807 if (name != NULL && ((m_name != name) ^ negate_name_test)) | |
808 continue; | |
809 if (sig != NULL && m->signature() != sig) | |
810 continue; | |
811 // passed the filters | |
812 if (rskip > 0) { | |
813 --rskip; | |
814 } else if (rfill < rlimit) { | |
815 oop result = results->obj_at(rfill++); | |
816 if (!sun_dyn_MemberName::is_instance(result)) | |
817 return -99; // caller bug! | |
818 MethodHandles::init_MemberName(result, m, true); | |
819 } else if (++overflow >= overflow_limit) { | |
820 match_flags = 0; break; // got tired of looking at overflow | |
821 } | |
822 } | |
823 } | |
824 | |
825 // return number of elements we at leasted wanted to initialize | |
826 return rfill + overflow; | |
827 } | |
828 | |
829 | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
830 // Decode this java.lang.Class object into an instanceKlass, if possible. |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
831 // Throw IAE if not |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
832 instanceKlassHandle MethodHandles::resolve_instance_klass(oop java_mirror_oop, TRAPS) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
833 instanceKlassHandle empty; |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
834 klassOop caller = NULL; |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
835 if (java_lang_Class::is_instance(java_mirror_oop)) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
836 caller = java_lang_Class::as_klassOop(java_mirror_oop); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
837 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
838 if (caller == NULL || !Klass::cast(caller)->oop_is_instance()) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
839 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not a class", empty); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
840 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
841 return instanceKlassHandle(THREAD, caller); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
842 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
843 |
710 | 844 |
845 | |
846 // Decode the vmtarget field of a method handle. | |
847 // Sanitize out methodOops, klassOops, and any other non-Java data. | |
848 // This is for debugging and reflection. | |
849 oop MethodHandles::encode_target(Handle mh, int format, TRAPS) { | |
850 assert(java_dyn_MethodHandle::is_instance(mh()), "must be a MH"); | |
851 if (format == ETF_HANDLE_OR_METHOD_NAME) { | |
852 oop target = java_dyn_MethodHandle::vmtarget(mh()); | |
853 if (target == NULL) { | |
854 return NULL; // unformed MH | |
855 } | |
856 klassOop tklass = target->klass(); | |
1142 | 857 if (Klass::cast(tklass)->is_subclass_of(SystemDictionary::Object_klass())) { |
710 | 858 return target; // target is another MH (or something else?) |
859 } | |
860 } | |
861 if (format == ETF_DIRECT_HANDLE) { | |
862 oop target = mh(); | |
863 for (;;) { | |
864 if (target->klass() == SystemDictionary::DirectMethodHandle_klass()) { | |
865 return target; | |
866 } | |
867 if (!java_dyn_MethodHandle::is_instance(target)){ | |
868 return NULL; // unformed MH | |
869 } | |
870 target = java_dyn_MethodHandle::vmtarget(target); | |
871 } | |
872 } | |
873 // cases of metadata in MH.vmtarget: | |
874 // - AMH can have methodOop for static invoke with bound receiver | |
875 // - DMH can have methodOop for static invoke (on variable receiver) | |
876 // - DMH can have klassOop for dispatched (non-static) invoke | |
877 klassOop receiver_limit = NULL; | |
878 int decode_flags = 0; | |
879 methodOop m = decode_MethodHandle(mh(), receiver_limit, decode_flags); | |
880 if (m == NULL) return NULL; | |
881 switch (format) { | |
882 case ETF_REFLECT_METHOD: | |
883 // same as jni_ToReflectedMethod: | |
884 if (m->is_initializer()) { | |
885 return Reflection::new_constructor(m, THREAD); | |
886 } else { | |
887 return Reflection::new_method(m, UseNewReflection, false, THREAD); | |
888 } | |
889 | |
890 case ETF_HANDLE_OR_METHOD_NAME: // method, not handle | |
891 case ETF_METHOD_NAME: | |
892 { | |
893 if (SystemDictionary::MemberName_klass() == NULL) break; | |
894 instanceKlassHandle mname_klass(THREAD, SystemDictionary::MemberName_klass()); | |
895 mname_klass->initialize(CHECK_NULL); | |
896 Handle mname = mname_klass->allocate_instance_handle(CHECK_NULL); | |
897 sun_dyn_MemberName::set_vmindex(mname(), VM_INDEX_UNINITIALIZED); | |
898 bool do_dispatch = ((decode_flags & MethodHandles::_dmf_does_dispatch) != 0); | |
899 init_MemberName(mname(), m, do_dispatch); | |
900 expand_MemberName(mname, 0, CHECK_NULL); | |
901 return mname(); | |
902 } | |
903 } | |
904 | |
905 // Unknown format code. | |
906 char msg[50]; | |
907 jio_snprintf(msg, sizeof(msg), "unknown getTarget format=%d", format); | |
908 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), msg); | |
909 } | |
910 | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
911 static const char* always_null_names[] = { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
912 "java/lang/Void", |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
913 "java/lang/Null", |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
914 //"java/lang/Nothing", |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
915 "sun/dyn/empty/Empty", |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
916 NULL |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
917 }; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
918 |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
919 static bool is_always_null_type(klassOop klass) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
920 if (!Klass::cast(klass)->oop_is_instance()) return false; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
921 instanceKlass* ik = instanceKlass::cast(klass); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
922 // Must be on the boot class path: |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
923 if (ik->class_loader() != NULL) return false; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
924 // Check the name. |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
925 symbolOop name = ik->name(); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
926 for (int i = 0; ; i++) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
927 const char* test_name = always_null_names[i]; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
928 if (test_name == NULL) break; |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
929 if (name->equals(test_name)) |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
930 return true; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
931 } |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
932 return false; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
933 } |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
934 |
710 | 935 bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) { |
1142 | 936 if (src == dst || dst == SystemDictionary::Object_klass()) |
710 | 937 return false; // quickest checks |
938 Klass* srck = Klass::cast(src); | |
939 Klass* dstk = Klass::cast(dst); | |
940 if (dstk->is_interface()) { | |
941 // interface receivers can safely be viewed as untyped, | |
942 // because interface calls always include a dynamic check | |
1142 | 943 //dstk = Klass::cast(SystemDictionary::Object_klass()); |
710 | 944 return false; |
945 } | |
946 if (srck->is_interface()) { | |
947 // interface arguments must be viewed as untyped | |
1142 | 948 //srck = Klass::cast(SystemDictionary::Object_klass()); |
710 | 949 return true; |
950 } | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
951 if (is_always_null_type(src)) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
952 // some source types are known to be never instantiated; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
953 // they represent references which are always null |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
954 // such null references never fail to convert safely |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
955 return false; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
956 } |
710 | 957 return !srck->is_subclass_of(dstk->as_klassOop()); |
958 } | |
959 | |
960 static oop object_java_mirror() { | |
1142 | 961 return Klass::cast(SystemDictionary::Object_klass())->java_mirror(); |
710 | 962 } |
963 | |
964 bool MethodHandles::same_basic_type_for_arguments(BasicType src, | |
965 BasicType dst, | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
966 bool raw, |
710 | 967 bool for_return) { |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
968 if (for_return) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
969 // return values can always be forgotten: |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
970 if (dst == T_VOID) return true; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
971 if (src == T_VOID) return raw && (dst == T_INT); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
972 // We allow caller to receive a garbage int, which is harmless. |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
973 // This trick is pulled by trusted code (see VerifyType.canPassRaw). |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
974 } |
710 | 975 assert(src != T_VOID && dst != T_VOID, "should not be here"); |
976 if (src == dst) return true; | |
977 if (type2size[src] != type2size[dst]) return false; | |
978 // allow reinterpretation casts for integral widening | |
979 if (is_subword_type(src)) { // subwords can fit in int or other subwords | |
980 if (dst == T_INT) // any subword fits in an int | |
981 return true; | |
982 if (src == T_BOOLEAN) // boolean fits in any subword | |
983 return is_subword_type(dst); | |
984 if (src == T_BYTE && dst == T_SHORT) | |
985 return true; // remaining case: byte fits in short | |
986 } | |
987 // allow float/fixed reinterpretation casts | |
988 if (src == T_FLOAT) return dst == T_INT; | |
989 if (src == T_INT) return dst == T_FLOAT; | |
990 if (src == T_DOUBLE) return dst == T_LONG; | |
991 if (src == T_LONG) return dst == T_DOUBLE; | |
992 return false; | |
993 } | |
994 | |
995 const char* MethodHandles::check_method_receiver(methodOop m, | |
996 klassOop passed_recv_type) { | |
997 assert(!m->is_static(), "caller resp."); | |
998 if (passed_recv_type == NULL) | |
999 return "receiver type is primitive"; | |
1000 if (class_cast_needed(passed_recv_type, m->method_holder())) { | |
1001 Klass* formal = Klass::cast(m->method_holder()); | |
1002 return SharedRuntime::generate_class_cast_message("receiver type", | |
1003 formal->external_name()); | |
1004 } | |
1005 return NULL; // checks passed | |
1006 } | |
1007 | |
1008 // Verify that m's signature can be called type-safely by a method handle | |
1009 // of the given method type 'mtype'. | |
1010 // It takes a TRAPS argument because it must perform symbol lookups. | |
1011 void MethodHandles::verify_method_signature(methodHandle m, | |
1012 Handle mtype, | |
1013 int first_ptype_pos, | |
1014 KlassHandle insert_ptype, | |
1015 TRAPS) { | |
1016 objArrayHandle ptypes(THREAD, java_dyn_MethodType::ptypes(mtype())); | |
1017 int pnum = first_ptype_pos; | |
1018 int pmax = ptypes->length(); | |
1019 int mnum = 0; // method argument | |
1020 const char* err = NULL; | |
1021 for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) { | |
1022 oop ptype_oop = NULL; | |
1023 if (ss.at_return_type()) { | |
1024 if (pnum != pmax) | |
1025 { err = "too many arguments"; break; } | |
1026 ptype_oop = java_dyn_MethodType::rtype(mtype()); | |
1027 } else { | |
1028 if (pnum >= pmax) | |
1029 { err = "not enough arguments"; break; } | |
1030 if (pnum >= 0) | |
1031 ptype_oop = ptypes->obj_at(pnum); | |
1032 else if (insert_ptype.is_null()) | |
1033 ptype_oop = NULL; | |
1034 else | |
1035 ptype_oop = insert_ptype->java_mirror(); | |
1036 pnum += 1; | |
1037 mnum += 1; | |
1038 } | |
1508
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1039 klassOop pklass = NULL; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1040 BasicType ptype = T_OBJECT; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1041 if (ptype_oop != NULL) |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1042 ptype = java_lang_Class::as_BasicType(ptype_oop, &pklass); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1043 else |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1044 // null does not match any non-reference; use Object to report the error |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1045 pklass = SystemDictionary::Object_klass(); |
710 | 1046 klassOop mklass = NULL; |
1047 BasicType mtype = ss.type(); | |
1048 if (mtype == T_ARRAY) mtype = T_OBJECT; // fold all refs to T_OBJECT | |
1049 if (mtype == T_OBJECT) { | |
1050 if (ptype_oop == NULL) { | |
1051 // null matches any reference | |
1052 continue; | |
1053 } | |
1508
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1054 KlassHandle pklass_handle(THREAD, pklass); pklass = NULL; |
710 | 1055 // If we fail to resolve types at this point, we will throw an error. |
1056 symbolOop name_oop = ss.as_symbol(CHECK); | |
1057 symbolHandle name(THREAD, name_oop); | |
1058 instanceKlass* mk = instanceKlass::cast(m->method_holder()); | |
1059 Handle loader(THREAD, mk->class_loader()); | |
1060 Handle domain(THREAD, mk->protection_domain()); | |
1508
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1061 mklass = SystemDictionary::resolve_or_null(name, loader, domain, CHECK); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1062 pklass = pklass_handle(); |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1063 if (mklass == NULL && pklass != NULL && |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1064 Klass::cast(pklass)->name() == name() && |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1065 m->is_method_handle_invoke()) { |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1066 // Assume a match. We can't really decode the signature of MH.invoke*. |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1067 continue; |
2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
1507
diff
changeset
|
1068 } |
710 | 1069 } |
1070 if (!ss.at_return_type()) { | |
1071 err = check_argument_type_change(ptype, pklass, mtype, mklass, mnum); | |
1072 } else { | |
1073 err = check_return_type_change(mtype, mklass, ptype, pklass); // note reversal! | |
1074 } | |
1075 if (err != NULL) break; | |
1076 } | |
1077 | |
1078 if (err != NULL) { | |
1079 THROW_MSG(vmSymbols::java_lang_InternalError(), err); | |
1080 } | |
1081 } | |
1082 | |
1083 // Main routine for verifying the MethodHandle.type of a proposed | |
1084 // direct or bound-direct method handle. | |
1085 void MethodHandles::verify_method_type(methodHandle m, | |
1086 Handle mtype, | |
1087 bool has_bound_recv, | |
1088 KlassHandle bound_recv_type, | |
1089 TRAPS) { | |
1090 bool m_needs_receiver = !m->is_static(); | |
1091 | |
1092 const char* err = NULL; | |
1093 | |
1094 int first_ptype_pos = m_needs_receiver ? 1 : 0; | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1095 if (has_bound_recv) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1096 first_ptype_pos -= 1; // ptypes do not include the bound argument; start earlier in them |
710 | 1097 if (m_needs_receiver && bound_recv_type.is_null()) |
1098 { err = "bound receiver is not an object"; goto die; } | |
1099 } | |
1100 | |
1101 if (m_needs_receiver && err == NULL) { | |
1102 objArrayOop ptypes = java_dyn_MethodType::ptypes(mtype()); | |
1103 if (ptypes->length() < first_ptype_pos) | |
1104 { err = "receiver argument is missing"; goto die; } | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1105 if (has_bound_recv) |
710 | 1106 err = check_method_receiver(m(), bound_recv_type->as_klassOop()); |
1107 else | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1108 err = check_method_receiver(m(), java_lang_Class::as_klassOop(ptypes->obj_at(first_ptype_pos-1))); |
710 | 1109 if (err != NULL) goto die; |
1110 } | |
1111 | |
1112 // Check the other arguments for mistypes. | |
1113 verify_method_signature(m, mtype, first_ptype_pos, bound_recv_type, CHECK); | |
1114 return; | |
1115 | |
1116 die: | |
1117 THROW_MSG(vmSymbols::java_lang_InternalError(), err); | |
1118 } | |
1119 | |
1120 void MethodHandles::verify_vmslots(Handle mh, TRAPS) { | |
1121 // Verify vmslots. | |
1122 int check_slots = argument_slot_count(java_dyn_MethodHandle::type(mh())); | |
1123 if (java_dyn_MethodHandle::vmslots(mh()) != check_slots) { | |
1124 THROW_MSG(vmSymbols::java_lang_InternalError(), "bad vmslots in BMH"); | |
1125 } | |
1126 } | |
1127 | |
1128 void MethodHandles::verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS) { | |
1129 // Verify that argslot points at the given argnum. | |
1130 int check_slot = argument_slot(java_dyn_MethodHandle::type(mh()), argnum); | |
1131 if (argslot != check_slot || argslot < 0) { | |
1132 const char* fmt = "for argnum of %d, vmargslot is %d, should be %d"; | |
1133 size_t msglen = strlen(fmt) + 3*11 + 1; | |
1134 char* msg = NEW_RESOURCE_ARRAY(char, msglen); | |
1135 jio_snprintf(msg, msglen, fmt, argnum, argslot, check_slot); | |
1136 THROW_MSG(vmSymbols::java_lang_InternalError(), msg); | |
1137 } | |
1138 } | |
1139 | |
1140 // Verify the correspondence between two method types. | |
1141 // Apart from the advertised changes, caller method type X must | |
1142 // be able to invoke the callee method Y type with no violations | |
1143 // of type integrity. | |
1144 // Return NULL if all is well, else a short error message. | |
1145 const char* MethodHandles::check_method_type_change(oop src_mtype, int src_beg, int src_end, | |
1146 int insert_argnum, oop insert_type, | |
1147 int change_argnum, oop change_type, | |
1148 int delete_argnum, | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1149 oop dst_mtype, int dst_beg, int dst_end, |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1150 bool raw) { |
710 | 1151 objArrayOop src_ptypes = java_dyn_MethodType::ptypes(src_mtype); |
1152 objArrayOop dst_ptypes = java_dyn_MethodType::ptypes(dst_mtype); | |
1153 | |
1154 int src_max = src_ptypes->length(); | |
1155 int dst_max = dst_ptypes->length(); | |
1156 | |
1157 if (src_end == -1) src_end = src_max; | |
1158 if (dst_end == -1) dst_end = dst_max; | |
1159 | |
1160 assert(0 <= src_beg && src_beg <= src_end && src_end <= src_max, "oob"); | |
1161 assert(0 <= dst_beg && dst_beg <= dst_end && dst_end <= dst_max, "oob"); | |
1162 | |
1163 // pending actions; set to -1 when done: | |
1164 int ins_idx = insert_argnum, chg_idx = change_argnum, del_idx = delete_argnum; | |
1165 | |
1166 const char* err = NULL; | |
1167 | |
1168 // Walk along each array of parameter types, including a virtual | |
1169 // NULL end marker at the end of each. | |
1170 for (int src_idx = src_beg, dst_idx = dst_beg; | |
1171 (src_idx <= src_end && dst_idx <= dst_end); | |
1172 src_idx++, dst_idx++) { | |
1173 oop src_type = (src_idx == src_end) ? oop(NULL) : src_ptypes->obj_at(src_idx); | |
1174 oop dst_type = (dst_idx == dst_end) ? oop(NULL) : dst_ptypes->obj_at(dst_idx); | |
1175 bool fix_null_src_type = false; | |
1176 | |
1177 // Perform requested edits. | |
1178 if (ins_idx == src_idx) { | |
1179 // note that the inserted guy is never affected by a change or deletion | |
1180 ins_idx = -1; | |
1181 src_type = insert_type; | |
1182 fix_null_src_type = true; | |
1183 --src_idx; // back up to process src type on next loop | |
1184 src_idx = src_end; | |
1185 } else { | |
1186 // note that the changed guy can be immediately deleted | |
1187 if (chg_idx == src_idx) { | |
1188 chg_idx = -1; | |
1189 assert(src_idx < src_end, "oob"); | |
1190 src_type = change_type; | |
1191 fix_null_src_type = true; | |
1192 } | |
1193 if (del_idx == src_idx) { | |
1194 del_idx = -1; | |
1195 assert(src_idx < src_end, "oob"); | |
1196 --dst_idx; | |
1197 continue; // rerun loop after skipping this position | |
1198 } | |
1199 } | |
1200 | |
1201 if (src_type == NULL && fix_null_src_type) | |
1202 // explicit null in this case matches any dest reference | |
1203 src_type = (java_lang_Class::is_primitive(dst_type) ? object_java_mirror() : dst_type); | |
1204 | |
1205 // Compare the two argument types. | |
1206 if (src_type != dst_type) { | |
1207 if (src_type == NULL) return "not enough arguments"; | |
1208 if (dst_type == NULL) return "too many arguments"; | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1209 err = check_argument_type_change(src_type, dst_type, dst_idx, raw); |
710 | 1210 if (err != NULL) return err; |
1211 } | |
1212 } | |
1213 | |
1214 // Now compare return types also. | |
1215 oop src_rtype = java_dyn_MethodType::rtype(src_mtype); | |
1216 oop dst_rtype = java_dyn_MethodType::rtype(dst_mtype); | |
1217 if (src_rtype != dst_rtype) { | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1218 err = check_return_type_change(dst_rtype, src_rtype, raw); // note reversal! |
710 | 1219 if (err != NULL) return err; |
1220 } | |
1221 | |
1222 assert(err == NULL, ""); | |
1223 return NULL; // all is well | |
1224 } | |
1225 | |
1226 | |
1227 const char* MethodHandles::check_argument_type_change(BasicType src_type, | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1228 klassOop src_klass, |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1229 BasicType dst_type, |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1230 klassOop dst_klass, |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1231 int argnum, |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1232 bool raw) { |
710 | 1233 const char* err = NULL; |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1234 bool for_return = (argnum < 0); |
710 | 1235 |
1236 // just in case: | |
1237 if (src_type == T_ARRAY) src_type = T_OBJECT; | |
1238 if (dst_type == T_ARRAY) dst_type = T_OBJECT; | |
1239 | |
1240 // Produce some nice messages if VerifyMethodHandles is turned on: | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1241 if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) { |
710 | 1242 if (src_type == T_OBJECT) { |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1243 if (raw && dst_type == T_INT && is_always_null_type(src_klass)) |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1244 return NULL; // OK to convert a null pointer to a garbage int |
710 | 1245 err = ((argnum >= 0) |
1246 ? "type mismatch: passing a %s for method argument #%d, which expects primitive %s" | |
1247 : "type mismatch: returning a %s, but caller expects primitive %s"); | |
1248 } else if (dst_type == T_OBJECT) { | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1249 err = ((argnum >= 0) |
710 | 1250 ? "type mismatch: passing a primitive %s for method argument #%d, which expects %s" |
1251 : "type mismatch: returning a primitive %s, but caller expects %s"); | |
1252 } else { | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1253 err = ((argnum >= 0) |
710 | 1254 ? "type mismatch: passing a %s for method argument #%d, which expects %s" |
1255 : "type mismatch: returning a %s, but caller expects %s"); | |
1256 } | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1257 } else if (src_type == T_OBJECT && dst_type == T_OBJECT && |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1258 class_cast_needed(src_klass, dst_klass)) { |
710 | 1259 if (!class_cast_needed(dst_klass, src_klass)) { |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1260 if (raw) |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1261 return NULL; // reverse cast is OK; the MH target is trusted to enforce it |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1262 err = ((argnum >= 0) |
710 | 1263 ? "cast required: passing a %s for method argument #%d, which expects %s" |
1264 : "cast required: returning a %s, but caller expects %s"); | |
1265 } else { | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1266 err = ((argnum >= 0) |
710 | 1267 ? "reference mismatch: passing a %s for method argument #%d, which expects %s" |
1268 : "reference mismatch: returning a %s, but caller expects %s"); | |
1269 } | |
1270 } else { | |
1271 // passed the obstacle course | |
1272 return NULL; | |
1273 } | |
1274 | |
1275 // format, format, format | |
1276 const char* src_name = type2name(src_type); | |
1277 const char* dst_name = type2name(dst_type); | |
1278 if (src_type == T_OBJECT) src_name = Klass::cast(src_klass)->external_name(); | |
1279 if (dst_type == T_OBJECT) dst_name = Klass::cast(dst_klass)->external_name(); | |
1280 if (src_name == NULL) src_name = "unknown type"; | |
1281 if (dst_name == NULL) dst_name = "unknown type"; | |
1282 | |
1283 size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11); | |
1284 char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1); | |
1285 if (argnum >= 0) { | |
1286 assert(strstr(err, "%d") != NULL, ""); | |
1287 jio_snprintf(msg, msglen, err, src_name, argnum, dst_name); | |
1288 } else { | |
1289 assert(strstr(err, "%d") == NULL, ""); | |
1290 jio_snprintf(msg, msglen, err, src_name, dst_name); | |
1291 } | |
1292 return msg; | |
1293 } | |
1294 | |
1295 // Compute the depth within the stack of the given argument, i.e., | |
1296 // the combined size of arguments to the right of the given argument. | |
1297 // For the last argument (ptypes.length-1) this will be zero. | |
1298 // For the first argument (0) this will be the size of all | |
1299 // arguments but that one. For the special number -1, this | |
1300 // will be the size of all arguments, including the first. | |
1301 // If the argument is neither -1 nor a valid argument index, | |
1302 // then return a negative number. Otherwise, the result | |
1303 // is in the range [0..vmslots] inclusive. | |
1304 int MethodHandles::argument_slot(oop method_type, int arg) { | |
1305 objArrayOop ptypes = java_dyn_MethodType::ptypes(method_type); | |
1306 int argslot = 0; | |
1307 int len = ptypes->length(); | |
1308 if (arg < -1 || arg >= len) return -99; | |
1309 for (int i = len-1; i > arg; i--) { | |
1310 BasicType bt = java_lang_Class::as_BasicType(ptypes->obj_at(i)); | |
1311 argslot += type2size[bt]; | |
1312 } | |
1313 assert(argument_slot_to_argnum(method_type, argslot) == arg, "inverse works"); | |
1314 return argslot; | |
1315 } | |
1316 | |
1317 // Given a slot number, return the argument number. | |
1318 int MethodHandles::argument_slot_to_argnum(oop method_type, int query_argslot) { | |
1319 objArrayOop ptypes = java_dyn_MethodType::ptypes(method_type); | |
1320 int argslot = 0; | |
1321 int len = ptypes->length(); | |
1322 for (int i = len-1; i >= 0; i--) { | |
1323 if (query_argslot == argslot) return i; | |
1324 BasicType bt = java_lang_Class::as_BasicType(ptypes->obj_at(i)); | |
1325 argslot += type2size[bt]; | |
1326 } | |
1327 // return pseudo-arg deepest in stack: | |
1328 if (query_argslot == argslot) return -1; | |
1329 return -99; // oob slot, or splitting a double-slot arg | |
1330 } | |
1331 | |
1332 methodHandle MethodHandles::dispatch_decoded_method(methodHandle m, | |
1333 KlassHandle receiver_limit, | |
1334 int decode_flags, | |
1335 KlassHandle receiver_klass, | |
1336 TRAPS) { | |
1337 assert((decode_flags & ~_DMF_DIRECT_MASK) == 0, "must be direct method reference"); | |
1338 assert((decode_flags & _dmf_has_receiver) != 0, "must have a receiver or first reference argument"); | |
1339 | |
1340 if (!m->is_static() && | |
1341 (receiver_klass.is_null() || !receiver_klass->is_subtype_of(m->method_holder()))) | |
1342 // given type does not match class of method, or receiver is null! | |
1343 // caller should have checked this, but let's be extra careful... | |
1344 return methodHandle(); | |
1345 | |
1346 if (receiver_limit.not_null() && | |
1347 (receiver_klass.not_null() && !receiver_klass->is_subtype_of(receiver_limit()))) | |
1348 // given type is not limited to the receiver type | |
1349 // note that a null receiver can match any reference value, for a static method | |
1350 return methodHandle(); | |
1351 | |
1352 if (!(decode_flags & MethodHandles::_dmf_does_dispatch)) { | |
1353 // pre-dispatched or static method (null receiver is OK for static) | |
1354 return m; | |
1355 | |
1356 } else if (receiver_klass.is_null()) { | |
1357 // null receiver value; cannot dispatch | |
1358 return methodHandle(); | |
1359 | |
1360 } else if (!(decode_flags & MethodHandles::_dmf_from_interface)) { | |
1361 // perform virtual dispatch | |
1362 int vtable_index = m->vtable_index(); | |
1363 guarantee(vtable_index >= 0, "valid vtable index"); | |
1364 | |
1365 // receiver_klass might be an arrayKlassOop but all vtables start at | |
1366 // the same place. The cast is to avoid virtual call and assertion. | |
1367 // See also LinkResolver::runtime_resolve_virtual_method. | |
1368 instanceKlass* inst = (instanceKlass*)Klass::cast(receiver_klass()); | |
1369 DEBUG_ONLY(inst->verify_vtable_index(vtable_index)); | |
1370 methodOop m_oop = inst->method_at_vtable(vtable_index); | |
1371 return methodHandle(THREAD, m_oop); | |
1372 | |
1373 } else { | |
1374 // perform interface dispatch | |
1375 int itable_index = klassItable::compute_itable_index(m()); | |
1376 guarantee(itable_index >= 0, "valid itable index"); | |
1377 instanceKlass* inst = instanceKlass::cast(receiver_klass()); | |
1378 methodOop m_oop = inst->method_at_itable(m->method_holder(), itable_index, THREAD); | |
1379 return methodHandle(THREAD, m_oop); | |
1380 } | |
1381 } | |
1382 | |
1383 void MethodHandles::verify_DirectMethodHandle(Handle mh, methodHandle m, TRAPS) { | |
1384 // Verify type. | |
1385 Handle mtype(THREAD, java_dyn_MethodHandle::type(mh())); | |
1386 verify_method_type(m, mtype, false, KlassHandle(), CHECK); | |
1387 | |
1388 // Verify vmslots. | |
1389 if (java_dyn_MethodHandle::vmslots(mh()) != m->size_of_parameters()) { | |
1390 THROW_MSG(vmSymbols::java_lang_InternalError(), "bad vmslots in DMH"); | |
1391 } | |
1392 } | |
1393 | |
1394 void MethodHandles::init_DirectMethodHandle(Handle mh, methodHandle m, bool do_dispatch, TRAPS) { | |
1395 // Check arguments. | |
1396 if (mh.is_null() || m.is_null() || | |
1397 (!do_dispatch && m->is_abstract())) { | |
1398 THROW(vmSymbols::java_lang_InternalError()); | |
1399 } | |
1400 | |
1401 java_dyn_MethodHandle::init_vmslots(mh()); | |
1402 | |
1403 if (VerifyMethodHandles) { | |
1404 // The privileged code which invokes this routine should not make | |
1405 // a mistake about types, but it's better to verify. | |
1406 verify_DirectMethodHandle(mh, m, CHECK); | |
1407 } | |
1408 | |
1409 // Finally, after safety checks are done, link to the target method. | |
1410 // We will follow the same path as the latter part of | |
1411 // InterpreterRuntime::resolve_invoke(), which first finds the method | |
1412 // and then decides how to populate the constant pool cache entry | |
1413 // that links the interpreter calls to the method. We need the same | |
1414 // bits, and will use the same calling sequence code. | |
1415 | |
1416 int vmindex = methodOopDesc::garbage_vtable_index; | |
1417 oop vmtarget = NULL; | |
1418 | |
1419 instanceKlass::cast(m->method_holder())->link_class(CHECK); | |
1420 | |
1421 MethodHandleEntry* me = NULL; | |
1422 if (do_dispatch && Klass::cast(m->method_holder())->is_interface()) { | |
1423 // We are simulating an invokeinterface instruction. | |
1424 // (We might also be simulating an invokevirtual on a miranda method, | |
1425 // but it is safe to treat it as an invokeinterface.) | |
1426 assert(!m->can_be_statically_bound(), "no final methods on interfaces"); | |
1427 vmindex = klassItable::compute_itable_index(m()); | |
1428 assert(vmindex >= 0, "(>=0) == do_dispatch"); | |
1429 // Set up same bits as ConstantPoolCacheEntry::set_interface_call(). | |
1430 vmtarget = m->method_holder(); // the interface | |
1431 me = MethodHandles::entry(MethodHandles::_invokeinterface_mh); | |
1432 } else if (!do_dispatch || m->can_be_statically_bound()) { | |
1433 // We are simulating an invokestatic or invokespecial instruction. | |
1434 // Set up the method pointer, just like ConstantPoolCacheEntry::set_method(). | |
1435 vmtarget = m(); | |
1436 // this does not help dispatch, but it will make it possible to parse this MH: | |
1437 vmindex = methodOopDesc::nonvirtual_vtable_index; | |
1438 assert(vmindex < 0, "(>=0) == do_dispatch"); | |
1439 if (!m->is_static()) { | |
1440 me = MethodHandles::entry(MethodHandles::_invokespecial_mh); | |
1441 } else { | |
1442 me = MethodHandles::entry(MethodHandles::_invokestatic_mh); | |
1443 // Part of the semantics of a static call is an initialization barrier. | |
1444 // For a DMH, it is done now, when the handle is created. | |
1445 Klass* k = Klass::cast(m->method_holder()); | |
1446 if (k->should_be_initialized()) { | |
1447 k->initialize(CHECK); | |
1448 } | |
1449 } | |
1450 } else { | |
1451 // We are simulating an invokevirtual instruction. | |
1452 // Set up the vtable index, just like ConstantPoolCacheEntry::set_method(). | |
1453 // The key logic is LinkResolver::runtime_resolve_virtual_method. | |
1454 vmindex = m->vtable_index(); | |
1455 vmtarget = m->method_holder(); | |
1456 me = MethodHandles::entry(MethodHandles::_invokevirtual_mh); | |
1457 } | |
1458 | |
1459 if (me == NULL) { THROW(vmSymbols::java_lang_InternalError()); } | |
1460 | |
1461 sun_dyn_DirectMethodHandle::set_vmtarget(mh(), vmtarget); | |
1462 sun_dyn_DirectMethodHandle::set_vmindex(mh(), vmindex); | |
1463 DEBUG_ONLY(int flags; klassOop rlimit); | |
1464 assert(MethodHandles::decode_method(mh(), rlimit, flags) == m(), | |
1465 "properly stored for later decoding"); | |
1466 DEBUG_ONLY(bool actual_do_dispatch = ((flags & _dmf_does_dispatch) != 0)); | |
1467 assert(!(actual_do_dispatch && !do_dispatch), | |
1468 "do not perform dispatch if !do_dispatch specified"); | |
1469 assert(actual_do_dispatch == (vmindex >= 0), "proper later decoding of do_dispatch"); | |
1470 assert(decode_MethodHandle_stack_pushes(mh()) == 0, "DMH does not move stack"); | |
1471 | |
1472 // Done! | |
1473 java_dyn_MethodHandle::set_vmentry(mh(), me); | |
1474 } | |
1475 | |
1476 void MethodHandles::verify_BoundMethodHandle_with_receiver(Handle mh, | |
1477 methodHandle m, | |
1478 TRAPS) { | |
1479 // Verify type. | |
1480 oop receiver = sun_dyn_BoundMethodHandle::argument(mh()); | |
1481 Handle mtype(THREAD, java_dyn_MethodHandle::type(mh())); | |
1482 KlassHandle bound_recv_type; | |
1483 if (receiver != NULL) bound_recv_type = KlassHandle(THREAD, receiver->klass()); | |
1484 verify_method_type(m, mtype, true, bound_recv_type, CHECK); | |
1485 | |
1486 int receiver_pos = m->size_of_parameters() - 1; | |
1487 | |
1488 // Verify MH.vmargslot, which should point at the bound receiver. | |
1489 verify_vmargslot(mh, -1, sun_dyn_BoundMethodHandle::vmargslot(mh()), CHECK); | |
1490 //verify_vmslots(mh, CHECK); | |
1491 | |
1492 // Verify vmslots. | |
1493 if (java_dyn_MethodHandle::vmslots(mh()) != receiver_pos) { | |
1494 THROW_MSG(vmSymbols::java_lang_InternalError(), "bad vmslots in BMH (receiver)"); | |
1495 } | |
1496 } | |
1497 | |
1498 // Initialize a BMH with a receiver bound directly to a methodOop. | |
1499 void MethodHandles::init_BoundMethodHandle_with_receiver(Handle mh, | |
1500 methodHandle original_m, | |
1501 KlassHandle receiver_limit, | |
1502 int decode_flags, | |
1503 TRAPS) { | |
1504 // Check arguments. | |
1505 if (mh.is_null() || original_m.is_null()) { | |
1506 THROW(vmSymbols::java_lang_InternalError()); | |
1507 } | |
1508 | |
1509 KlassHandle receiver_klass; | |
1510 { | |
1511 oop receiver_oop = sun_dyn_BoundMethodHandle::argument(mh()); | |
1512 if (receiver_oop != NULL) | |
1513 receiver_klass = KlassHandle(THREAD, receiver_oop->klass()); | |
1514 } | |
1515 methodHandle m = dispatch_decoded_method(original_m, | |
1516 receiver_limit, decode_flags, | |
1517 receiver_klass, | |
1518 CHECK); | |
1519 if (m.is_null()) { THROW(vmSymbols::java_lang_InternalError()); } | |
1520 if (m->is_abstract()) { THROW(vmSymbols::java_lang_AbstractMethodError()); } | |
1521 | |
1522 java_dyn_MethodHandle::init_vmslots(mh()); | |
1523 | |
1524 if (VerifyMethodHandles) { | |
1525 verify_BoundMethodHandle_with_receiver(mh, m, CHECK); | |
1526 } | |
1527 | |
1528 sun_dyn_BoundMethodHandle::set_vmtarget(mh(), m()); | |
1529 | |
1530 DEBUG_ONLY(int junk; klassOop junk2); | |
1531 assert(MethodHandles::decode_method(mh(), junk2, junk) == m(), "properly stored for later decoding"); | |
1532 assert(decode_MethodHandle_stack_pushes(mh()) == 1, "BMH pushes one stack slot"); | |
1533 | |
1534 // Done! | |
1535 java_dyn_MethodHandle::set_vmentry(mh(), MethodHandles::entry(MethodHandles::_bound_ref_direct_mh)); | |
1536 } | |
1537 | |
1538 void MethodHandles::verify_BoundMethodHandle(Handle mh, Handle target, int argnum, | |
1539 bool direct_to_method, TRAPS) { | |
1540 Handle ptype_handle(THREAD, | |
1541 java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum)); | |
1542 KlassHandle ptype_klass; | |
1543 BasicType ptype = java_lang_Class::as_BasicType(ptype_handle(), &ptype_klass); | |
1544 int slots_pushed = type2size[ptype]; | |
1545 | |
1546 oop argument = sun_dyn_BoundMethodHandle::argument(mh()); | |
1547 | |
1548 const char* err = NULL; | |
1549 | |
1550 switch (ptype) { | |
1551 case T_OBJECT: | |
1552 if (argument != NULL) | |
1553 // we must implicitly convert from the arg type to the outgoing ptype | |
1554 err = check_argument_type_change(T_OBJECT, argument->klass(), ptype, ptype_klass(), argnum); | |
1555 break; | |
1556 | |
1557 case T_ARRAY: case T_VOID: | |
1558 assert(false, "array, void do not appear here"); | |
1559 default: | |
1560 if (ptype != T_INT && !is_subword_type(ptype)) { | |
1561 err = "unexpected parameter type"; | |
1562 break; | |
1563 } | |
1564 // check subrange of Integer.value, if necessary | |
1142 | 1565 if (argument == NULL || argument->klass() != SystemDictionary::Integer_klass()) { |
710 | 1566 err = "bound integer argument must be of type java.lang.Integer"; |
1567 break; | |
1568 } | |
1569 if (ptype != T_INT) { | |
1570 int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_INT); | |
1571 jint value = argument->int_field(value_offset); | |
1572 int vminfo = adapter_subword_vminfo(ptype); | |
1573 jint subword = truncate_subword_from_vminfo(value, vminfo); | |
1574 if (value != subword) { | |
1575 err = "bound subword value does not fit into the subword type"; | |
1576 break; | |
1577 } | |
1578 } | |
1579 break; | |
1580 case T_FLOAT: | |
1581 case T_DOUBLE: | |
1582 case T_LONG: | |
1583 { | |
1584 // we must implicitly convert from the unboxed arg type to the outgoing ptype | |
1585 BasicType argbox = java_lang_boxing_object::basic_type(argument); | |
1586 if (argbox != ptype) { | |
1587 err = check_argument_type_change(T_OBJECT, (argument == NULL | |
1142 | 1588 ? SystemDictionary::Object_klass() |
710 | 1589 : argument->klass()), |
1590 ptype, ptype_klass(), argnum); | |
1591 assert(err != NULL, "this must be an error"); | |
1592 } | |
1593 break; | |
1594 } | |
1595 } | |
1596 | |
1597 if (err == NULL) { | |
1598 DEBUG_ONLY(int this_pushes = decode_MethodHandle_stack_pushes(mh())); | |
1599 if (direct_to_method) { | |
1600 assert(this_pushes == slots_pushed, "BMH pushes one or two stack slots"); | |
1601 assert(slots_pushed <= MethodHandlePushLimit, ""); | |
1602 } else { | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1603 int target_pushes = decode_MethodHandle_stack_pushes(target()); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1604 assert(this_pushes == slots_pushed + target_pushes, "BMH stack motion must be correct"); |
710 | 1605 // do not blow the stack; use a Java-based adapter if this limit is exceeded |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1606 // FIXME |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1607 // if (slots_pushed + target_pushes > MethodHandlePushLimit) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1608 // err = "too many bound parameters"; |
710 | 1609 } |
1610 } | |
1611 | |
1612 if (err == NULL) { | |
1613 // Verify the rest of the method type. | |
1614 err = check_method_type_insertion(java_dyn_MethodHandle::type(mh()), | |
1615 argnum, ptype_handle(), | |
1616 java_dyn_MethodHandle::type(target())); | |
1617 } | |
1618 | |
1619 if (err != NULL) { | |
1620 THROW_MSG(vmSymbols::java_lang_InternalError(), err); | |
1621 } | |
1622 } | |
1623 | |
1624 void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { | |
1625 // Check arguments. | |
1626 if (mh.is_null() || target.is_null() || !java_dyn_MethodHandle::is_instance(target())) { | |
1627 THROW(vmSymbols::java_lang_InternalError()); | |
1628 } | |
1629 | |
1630 java_dyn_MethodHandle::init_vmslots(mh()); | |
1631 | |
1632 if (VerifyMethodHandles) { | |
1633 int insert_after = argnum - 1; | |
1634 verify_vmargslot(mh, insert_after, sun_dyn_BoundMethodHandle::vmargslot(mh()), CHECK); | |
1635 verify_vmslots(mh, CHECK); | |
1636 } | |
1637 | |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1638 // Get bound type and required slots. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1639 oop ptype_oop = java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1640 BasicType ptype = java_lang_Class::as_BasicType(ptype_oop); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1641 int slots_pushed = type2size[ptype]; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1642 |
710 | 1643 // If (a) the target is a direct non-dispatched method handle, |
1644 // or (b) the target is a dispatched direct method handle and we | |
1645 // are binding the receiver, cut out the middle-man. | |
1646 // Do this by decoding the DMH and using its methodOop directly as vmtarget. | |
1647 bool direct_to_method = false; | |
1648 if (OptimizeMethodHandles && | |
1649 target->klass() == SystemDictionary::DirectMethodHandle_klass() && | |
1650 (argnum == 0 || sun_dyn_DirectMethodHandle::vmindex(target()) < 0)) { | |
1651 int decode_flags = 0; klassOop receiver_limit_oop = NULL; | |
1652 methodHandle m(THREAD, decode_method(target(), receiver_limit_oop, decode_flags)); | |
1653 if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "DMH failed to decode"); } | |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1654 DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - slots_pushed); // pos. of 1st arg. |
710 | 1655 assert(sun_dyn_BoundMethodHandle::vmslots(mh()) == m_vmslots, "type w/ m sig"); |
1656 if (argnum == 0 && (decode_flags & _dmf_has_receiver) != 0) { | |
1657 KlassHandle receiver_limit(THREAD, receiver_limit_oop); | |
1658 init_BoundMethodHandle_with_receiver(mh, m, | |
1659 receiver_limit, decode_flags, | |
1660 CHECK); | |
1661 return; | |
1662 } | |
1663 | |
1664 // Even if it is not a bound receiver, we still might be able | |
1665 // to bind another argument and still invoke the methodOop directly. | |
1666 if (!(decode_flags & _dmf_does_dispatch)) { | |
1667 direct_to_method = true; | |
1668 sun_dyn_BoundMethodHandle::set_vmtarget(mh(), m()); | |
1669 } | |
1670 } | |
1671 if (!direct_to_method) | |
1672 sun_dyn_BoundMethodHandle::set_vmtarget(mh(), target()); | |
1673 | |
1674 if (VerifyMethodHandles) { | |
1675 verify_BoundMethodHandle(mh, target, argnum, direct_to_method, CHECK); | |
1676 } | |
1677 | |
1678 // Next question: Is this a ref, int, or long bound value? | |
1679 MethodHandleEntry* me = NULL; | |
1680 if (ptype == T_OBJECT) { | |
1681 if (direct_to_method) me = MethodHandles::entry(_bound_ref_direct_mh); | |
1682 else me = MethodHandles::entry(_bound_ref_mh); | |
1683 } else if (slots_pushed == 2) { | |
1684 if (direct_to_method) me = MethodHandles::entry(_bound_long_direct_mh); | |
1685 else me = MethodHandles::entry(_bound_long_mh); | |
1686 } else if (slots_pushed == 1) { | |
1687 if (direct_to_method) me = MethodHandles::entry(_bound_int_direct_mh); | |
1688 else me = MethodHandles::entry(_bound_int_mh); | |
1689 } else { | |
1690 assert(false, ""); | |
1691 } | |
1692 | |
1693 // Done! | |
1694 java_dyn_MethodHandle::set_vmentry(mh(), me); | |
1695 } | |
1696 | |
1697 static void throw_InternalError_for_bad_conversion(int conversion, const char* err, TRAPS) { | |
1698 char msg[200]; | |
1699 jio_snprintf(msg, sizeof(msg), "bad adapter (conversion=0x%08x): %s", conversion, err); | |
1700 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), msg); | |
1701 } | |
1702 | |
1703 void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) { | |
1704 jint conversion = sun_dyn_AdapterMethodHandle::conversion(mh()); | |
1705 int argslot = sun_dyn_AdapterMethodHandle::vmargslot(mh()); | |
1706 | |
1707 verify_vmargslot(mh, argnum, argslot, CHECK); | |
1708 verify_vmslots(mh, CHECK); | |
1709 | |
1710 jint conv_op = adapter_conversion_op(conversion); | |
1711 if (!conv_op_valid(conv_op)) { | |
1712 throw_InternalError_for_bad_conversion(conversion, "unknown conversion op", THREAD); | |
1713 return; | |
1714 } | |
1715 EntryKind ek = adapter_entry_kind(conv_op); | |
1716 | |
1717 int stack_move = adapter_conversion_stack_move(conversion); | |
1718 BasicType src = adapter_conversion_src_type(conversion); | |
1719 BasicType dest = adapter_conversion_dest_type(conversion); | |
1720 int vminfo = adapter_conversion_vminfo(conversion); // should be zero | |
1721 | |
1722 Handle argument(THREAD, sun_dyn_AdapterMethodHandle::argument(mh())); | |
1723 Handle target(THREAD, sun_dyn_AdapterMethodHandle::vmtarget(mh())); | |
1724 Handle src_mtype(THREAD, java_dyn_MethodHandle::type(mh())); | |
1725 Handle dst_mtype(THREAD, java_dyn_MethodHandle::type(target())); | |
1726 | |
1727 const char* err = NULL; | |
1728 | |
1729 if (err == NULL) { | |
1730 // Check that the correct argument is supplied, but only if it is required. | |
1731 switch (ek) { | |
1732 case _adapter_check_cast: // target type of cast | |
1733 case _adapter_ref_to_prim: // wrapper type from which to unbox | |
1734 case _adapter_prim_to_ref: // wrapper type to box into | |
1735 case _adapter_collect_args: // array type to collect into | |
1736 case _adapter_spread_args: // array type to spread from | |
1737 if (!java_lang_Class::is_instance(argument()) | |
1738 || java_lang_Class::is_primitive(argument())) | |
1739 { err = "adapter requires argument of type java.lang.Class"; break; } | |
1740 if (ek == _adapter_collect_args || | |
1741 ek == _adapter_spread_args) { | |
1742 // Make sure it is a suitable collection type. (Array, for now.) | |
1743 Klass* ak = Klass::cast(java_lang_Class::as_klassOop(argument())); | |
1744 if (!ak->oop_is_objArray()) { | |
1745 { err = "adapter requires argument of type java.lang.Class<Object[]>"; break; } | |
1746 } | |
1747 } | |
1748 break; | |
1749 case _adapter_flyby: | |
1750 case _adapter_ricochet: | |
1751 if (!java_dyn_MethodHandle::is_instance(argument())) | |
1752 { err = "MethodHandle adapter argument required"; break; } | |
1753 break; | |
1754 default: | |
1755 if (argument.not_null()) | |
1756 { err = "adapter has spurious argument"; break; } | |
1757 break; | |
1758 } | |
1759 } | |
1760 | |
1761 if (err == NULL) { | |
1762 // Check that the src/dest types are supplied if needed. | |
1763 switch (ek) { | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1764 case _adapter_check_cast: |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1765 if (src != T_OBJECT || dest != T_OBJECT) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1766 err = "adapter requires object src/dest conversion subfields"; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1767 } |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1768 break; |
710 | 1769 case _adapter_prim_to_prim: |
1770 if (!is_java_primitive(src) || !is_java_primitive(dest) || src == dest) { | |
1771 err = "adapter requires primitive src/dest conversion subfields"; break; | |
1772 } | |
1773 if ( (src == T_FLOAT || src == T_DOUBLE) && !(dest == T_FLOAT || dest == T_DOUBLE) || | |
1774 !(src == T_FLOAT || src == T_DOUBLE) && (dest == T_FLOAT || dest == T_DOUBLE)) { | |
1775 err = "adapter cannot convert beween floating and fixed-point"; break; | |
1776 } | |
1777 break; | |
1778 case _adapter_ref_to_prim: | |
1779 if (src != T_OBJECT || !is_java_primitive(dest) | |
1780 || argument() != Klass::cast(SystemDictionary::box_klass(dest))->java_mirror()) { | |
1781 err = "adapter requires primitive dest conversion subfield"; break; | |
1782 } | |
1783 break; | |
1784 case _adapter_prim_to_ref: | |
1785 if (!is_java_primitive(src) || dest != T_OBJECT | |
1786 || argument() != Klass::cast(SystemDictionary::box_klass(src))->java_mirror()) { | |
1787 err = "adapter requires primitive src conversion subfield"; break; | |
1788 } | |
1789 break; | |
1790 case _adapter_swap_args: | |
1791 case _adapter_rot_args: | |
1792 { | |
1793 if (!src || src != dest) { | |
1794 err = "adapter requires src/dest conversion subfields for swap"; break; | |
1795 } | |
1796 int swap_size = type2size[src]; | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1797 oop src_mtype = sun_dyn_AdapterMethodHandle::type(mh()); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1798 oop dest_mtype = sun_dyn_AdapterMethodHandle::type(target()); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1799 int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(target()); |
710 | 1800 int src_slot = argslot; |
1801 int dest_slot = vminfo; | |
1802 bool rotate_up = (src_slot > dest_slot); // upward rotation | |
1803 int src_arg = argnum; | |
1804 int dest_arg = argument_slot_to_argnum(dest_mtype, dest_slot); | |
1805 verify_vmargslot(mh, dest_arg, dest_slot, CHECK); | |
1806 if (!(dest_slot >= src_slot + swap_size) && | |
1807 !(src_slot >= dest_slot + swap_size)) { | |
1808 err = "source, destination slots must be distinct"; | |
1809 } else if (ek == _adapter_swap_args && !(src_slot > dest_slot)) { | |
1810 err = "source of swap must be deeper in stack"; | |
1811 } else if (ek == _adapter_swap_args) { | |
1812 err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, dest_arg), | |
1813 java_dyn_MethodType::ptype(dest_mtype, src_arg), | |
1814 dest_arg); | |
1815 } else if (ek == _adapter_rot_args) { | |
1816 if (rotate_up) { | |
1817 assert((src_slot > dest_slot) && (src_arg < dest_arg), ""); | |
1818 // rotate up: [dest_slot..src_slot-ss] --> [dest_slot+ss..src_slot] | |
1819 // that is: [src_arg+1..dest_arg] --> [src_arg..dest_arg-1] | |
1820 for (int i = src_arg+1; i <= dest_arg && err == NULL; i++) { | |
1821 err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, i), | |
1822 java_dyn_MethodType::ptype(dest_mtype, i-1), | |
1823 i); | |
1824 } | |
1825 } else { // rotate down | |
1826 assert((src_slot < dest_slot) && (src_arg > dest_arg), ""); | |
1827 // rotate down: [src_slot+ss..dest_slot] --> [src_slot..dest_slot-ss] | |
1828 // that is: [dest_arg..src_arg-1] --> [dst_arg+1..src_arg] | |
1829 for (int i = dest_arg; i <= src_arg-1 && err == NULL; i++) { | |
1830 err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, i), | |
1831 java_dyn_MethodType::ptype(dest_mtype, i+1), | |
1832 i); | |
1833 } | |
1834 } | |
1835 } | |
1836 if (err == NULL) | |
1837 err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, src_arg), | |
1838 java_dyn_MethodType::ptype(dest_mtype, dest_arg), | |
1839 src_arg); | |
1840 } | |
1841 break; | |
1842 case _adapter_collect_args: | |
1843 case _adapter_spread_args: | |
1844 { | |
1845 BasicType coll_type = (ek == _adapter_collect_args) ? dest : src; | |
1846 BasicType elem_type = (ek == _adapter_collect_args) ? src : dest; | |
1847 if (coll_type != T_OBJECT || elem_type != T_OBJECT) { | |
1848 err = "adapter requires src/dest subfields"; break; | |
1849 // later: | |
1850 // - consider making coll be a primitive array | |
1851 // - consider making coll be a heterogeneous collection | |
1852 } | |
1853 } | |
1854 break; | |
1855 default: | |
1856 if (src != 0 || dest != 0) { | |
1857 err = "adapter has spurious src/dest conversion subfields"; break; | |
1858 } | |
1859 break; | |
1860 } | |
1861 } | |
1862 | |
1863 if (err == NULL) { | |
1864 // Check the stack_move subfield. | |
1865 // It must always report the net change in stack size, positive or negative. | |
1866 int slots_pushed = stack_move / stack_move_unit(); | |
1867 switch (ek) { | |
1868 case _adapter_prim_to_prim: | |
1869 case _adapter_ref_to_prim: | |
1870 case _adapter_prim_to_ref: | |
1871 if (slots_pushed != type2size[dest] - type2size[src]) { | |
1872 err = "wrong stack motion for primitive conversion"; | |
1873 } | |
1874 break; | |
1875 case _adapter_dup_args: | |
1876 if (slots_pushed <= 0) { | |
1877 err = "adapter requires conversion subfield slots_pushed > 0"; | |
1878 } | |
1879 break; | |
1880 case _adapter_drop_args: | |
1881 if (slots_pushed >= 0) { | |
1882 err = "adapter requires conversion subfield slots_pushed < 0"; | |
1883 } | |
1884 break; | |
1885 case _adapter_collect_args: | |
1886 if (slots_pushed > 1) { | |
1887 err = "adapter requires conversion subfield slots_pushed <= 1"; | |
1888 } | |
1889 break; | |
1890 case _adapter_spread_args: | |
1891 if (slots_pushed < -1) { | |
1892 err = "adapter requires conversion subfield slots_pushed >= -1"; | |
1893 } | |
1894 break; | |
1895 default: | |
1896 if (stack_move != 0) { | |
1897 err = "adapter has spurious stack_move conversion subfield"; | |
1898 } | |
1899 break; | |
1900 } | |
1901 if (err == NULL && stack_move != slots_pushed * stack_move_unit()) { | |
1902 err = "stack_move conversion subfield must be multiple of stack_move_unit"; | |
1903 } | |
1904 } | |
1905 | |
1906 if (err == NULL) { | |
1907 // Make sure this adapter does not push too deeply. | |
1908 int slots_pushed = stack_move / stack_move_unit(); | |
1909 int this_vmslots = java_dyn_MethodHandle::vmslots(mh()); | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1910 int target_vmslots = java_dyn_MethodHandle::vmslots(target()); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1911 if (slots_pushed != (target_vmslots - this_vmslots)) { |
710 | 1912 err = "stack_move inconsistent with previous and current MethodType vmslots"; |
1913 } else if (slots_pushed > 0) { | |
1914 // verify stack_move against MethodHandlePushLimit | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1915 int target_pushes = decode_MethodHandle_stack_pushes(target()); |
710 | 1916 // do not blow the stack; use a Java-based adapter if this limit is exceeded |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1917 if (slots_pushed + target_pushes > MethodHandlePushLimit) { |
710 | 1918 err = "adapter pushes too many parameters"; |
1919 } | |
1920 } | |
1921 | |
1922 // While we're at it, check that the stack motion decoder works: | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1923 DEBUG_ONLY(int target_pushes = decode_MethodHandle_stack_pushes(target())); |
710 | 1924 DEBUG_ONLY(int this_pushes = decode_MethodHandle_stack_pushes(mh())); |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1925 assert(this_pushes == slots_pushed + target_pushes, "AMH stack motion must be correct"); |
710 | 1926 } |
1927 | |
1928 if (err == NULL && vminfo != 0) { | |
1929 switch (ek) { | |
1930 case _adapter_swap_args: | |
1931 case _adapter_rot_args: | |
1932 break; // OK | |
1933 default: | |
1934 err = "vminfo subfield is reserved to the JVM"; | |
1935 } | |
1936 } | |
1937 | |
1938 // Do additional ad hoc checks. | |
1939 if (err == NULL) { | |
1940 switch (ek) { | |
1941 case _adapter_retype_only: | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1942 err = check_method_type_passthrough(src_mtype(), dst_mtype(), false); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1943 break; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1944 |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1945 case _adapter_retype_raw: |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
1946 err = check_method_type_passthrough(src_mtype(), dst_mtype(), true); |
710 | 1947 break; |
1948 | |
1949 case _adapter_check_cast: | |
1950 { | |
1951 // The actual value being checked must be a reference: | |
1952 err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype(), argnum), | |
1953 object_java_mirror(), argnum); | |
1954 if (err != NULL) break; | |
1955 | |
1956 // The output of the cast must fit with the destination argument: | |
1957 Handle cast_class = argument; | |
1958 err = check_method_type_conversion(src_mtype(), | |
1959 argnum, cast_class(), | |
1960 dst_mtype()); | |
1961 } | |
1962 break; | |
1963 | |
1964 // %%% TO DO: continue in remaining cases to verify src/dst_mtype if VerifyMethodHandles | |
1965 } | |
1966 } | |
1967 | |
1968 if (err != NULL) { | |
1969 throw_InternalError_for_bad_conversion(conversion, err, THREAD); | |
1970 return; | |
1971 } | |
1972 | |
1973 } | |
1974 | |
1975 void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { | |
1976 oop argument = sun_dyn_AdapterMethodHandle::argument(mh()); | |
1977 int argslot = sun_dyn_AdapterMethodHandle::vmargslot(mh()); | |
1978 jint conversion = sun_dyn_AdapterMethodHandle::conversion(mh()); | |
1979 jint conv_op = adapter_conversion_op(conversion); | |
1980 | |
1981 // adjust the adapter code to the internal EntryKind enumeration: | |
1982 EntryKind ek_orig = adapter_entry_kind(conv_op); | |
1983 EntryKind ek_opt = ek_orig; // may be optimized | |
1984 | |
1985 // Finalize the vmtarget field (Java initialized it to null). | |
1986 if (!java_dyn_MethodHandle::is_instance(target())) { | |
1987 throw_InternalError_for_bad_conversion(conversion, "bad target", THREAD); | |
1988 return; | |
1989 } | |
1990 sun_dyn_AdapterMethodHandle::set_vmtarget(mh(), target()); | |
1991 | |
1992 if (VerifyMethodHandles) { | |
1993 verify_AdapterMethodHandle(mh, argnum, CHECK); | |
1994 } | |
1995 | |
1996 int stack_move = adapter_conversion_stack_move(conversion); | |
1997 BasicType src = adapter_conversion_src_type(conversion); | |
1998 BasicType dest = adapter_conversion_dest_type(conversion); | |
1999 int vminfo = adapter_conversion_vminfo(conversion); // should be zero | |
2000 | |
2001 const char* err = NULL; | |
2002 | |
2003 // Now it's time to finish the case analysis and pick a MethodHandleEntry. | |
2004 switch (ek_orig) { | |
2005 case _adapter_retype_only: | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2006 case _adapter_retype_raw: |
710 | 2007 case _adapter_check_cast: |
2008 case _adapter_dup_args: | |
2009 case _adapter_drop_args: | |
2010 // these work fine via general case code | |
2011 break; | |
2012 | |
2013 case _adapter_prim_to_prim: | |
2014 { | |
2015 // Non-subword cases are {int,float,long,double} -> {int,float,long,double}. | |
2016 // And, the {float,double} -> {int,long} cases must be handled by Java. | |
2017 switch (type2size[src] *4+ type2size[dest]) { | |
2018 case 1 *4+ 1: | |
2019 assert(src == T_INT || is_subword_type(src), "source is not float"); | |
2020 // Subword-related cases are int -> {boolean,byte,char,short}. | |
2021 ek_opt = _adapter_opt_i2i; | |
2022 vminfo = adapter_subword_vminfo(dest); | |
2023 break; | |
2024 case 2 *4+ 1: | |
2025 if (src == T_LONG && (dest == T_INT || is_subword_type(dest))) { | |
2026 ek_opt = _adapter_opt_l2i; | |
2027 vminfo = adapter_subword_vminfo(dest); | |
2028 } else if (src == T_DOUBLE && dest == T_FLOAT) { | |
2029 ek_opt = _adapter_opt_d2f; | |
2030 } else { | |
2031 assert(false, ""); | |
2032 } | |
2033 break; | |
2034 case 1 *4+ 2: | |
2035 if (src == T_INT && dest == T_LONG) { | |
2036 ek_opt = _adapter_opt_i2l; | |
2037 } else if (src == T_FLOAT && dest == T_DOUBLE) { | |
2038 ek_opt = _adapter_opt_f2d; | |
2039 } else { | |
2040 assert(false, ""); | |
2041 } | |
2042 break; | |
2043 default: | |
2044 assert(false, ""); | |
2045 break; | |
2046 } | |
2047 } | |
2048 break; | |
2049 | |
2050 case _adapter_ref_to_prim: | |
2051 { | |
2052 switch (type2size[dest]) { | |
2053 case 1: | |
2054 ek_opt = _adapter_opt_unboxi; | |
2055 vminfo = adapter_subword_vminfo(dest); | |
2056 break; | |
2057 case 2: | |
2058 ek_opt = _adapter_opt_unboxl; | |
2059 break; | |
2060 default: | |
2061 assert(false, ""); | |
2062 break; | |
2063 } | |
2064 } | |
2065 break; | |
2066 | |
2067 case _adapter_prim_to_ref: | |
2068 goto throw_not_impl; // allocates, hence could block | |
2069 | |
2070 case _adapter_swap_args: | |
2071 case _adapter_rot_args: | |
2072 { | |
2073 int swap_slots = type2size[src]; | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2074 int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(mh()); |
710 | 2075 int src_slot = argslot; |
2076 int dest_slot = vminfo; | |
2077 int rotate = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1; | |
2078 switch (swap_slots) { | |
2079 case 1: | |
2080 ek_opt = (!rotate ? _adapter_opt_swap_1 : | |
2081 rotate > 0 ? _adapter_opt_rot_1_up : _adapter_opt_rot_1_down); | |
2082 break; | |
2083 case 2: | |
2084 ek_opt = (!rotate ? _adapter_opt_swap_2 : | |
2085 rotate > 0 ? _adapter_opt_rot_2_up : _adapter_opt_rot_2_down); | |
2086 break; | |
2087 default: | |
2088 assert(false, ""); | |
2089 break; | |
2090 } | |
2091 } | |
2092 break; | |
2093 | |
2094 case _adapter_collect_args: | |
2095 goto throw_not_impl; // allocates, hence could block | |
2096 | |
2097 case _adapter_spread_args: | |
2098 { | |
2099 // vminfo will be the required length of the array | |
2100 int slots_pushed = stack_move / stack_move_unit(); | |
2101 int array_size = slots_pushed + 1; | |
2102 assert(array_size >= 0, ""); | |
2103 vminfo = array_size; | |
2104 switch (array_size) { | |
2105 case 0: ek_opt = _adapter_opt_spread_0; break; | |
2106 case 1: ek_opt = _adapter_opt_spread_1; break; | |
2107 default: ek_opt = _adapter_opt_spread_more; break; | |
2108 } | |
2109 if ((vminfo & CONV_VMINFO_MASK) != vminfo) | |
2110 goto throw_not_impl; // overflow | |
2111 } | |
2112 break; | |
2113 | |
2114 case _adapter_flyby: | |
2115 case _adapter_ricochet: | |
2116 goto throw_not_impl; // runs Java code, hence could block | |
2117 | |
2118 default: | |
2119 // should have failed much earlier; must be a missing case here | |
2120 assert(false, "incomplete switch"); | |
2121 // and fall through: | |
2122 | |
2123 throw_not_impl: | |
2124 // FIXME: these adapters are NYI | |
2125 err = "adapter not yet implemented in the JVM"; | |
2126 break; | |
2127 } | |
2128 | |
2129 if (err != NULL) { | |
2130 throw_InternalError_for_bad_conversion(conversion, err, THREAD); | |
2131 return; | |
2132 } | |
2133 | |
2134 // Rebuild the conversion value; maybe parts of it were changed. | |
2135 jint new_conversion = adapter_conversion(conv_op, src, dest, stack_move, vminfo); | |
2136 | |
2137 // Finalize the conversion field. (Note that it is final to Java code.) | |
2138 sun_dyn_AdapterMethodHandle::set_conversion(mh(), new_conversion); | |
2139 | |
2140 // Done! | |
2141 java_dyn_MethodHandle::set_vmentry(mh(), entry(ek_opt)); | |
2142 | |
2143 // There should be enough memory barriers on exit from native methods | |
2144 // to ensure that the MH is fully initialized to all threads before | |
2145 // Java code can publish it in global data structures. | |
2146 } | |
2147 | |
2148 // | |
2149 // Here are the native methods on sun.dyn.MethodHandleImpl. | |
2150 // They are the private interface between this JVM and the HotSpot-specific | |
2151 // Java code that implements JSR 292 method handles. | |
2152 // | |
2153 // Note: We use a JVM_ENTRY macro to define each of these, for this is the way | |
2154 // that intrinsic (non-JNI) native methods are defined in HotSpot. | |
2155 // | |
2156 | |
2157 // direct method handles for invokestatic or invokespecial | |
2158 // void init(DirectMethodHandle self, MemberName ref, boolean doDispatch, Class<?> caller); | |
2159 JVM_ENTRY(void, MHI_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh, | |
2160 jobject target_jh, jboolean do_dispatch, jobject caller_jh)) { | |
2161 ResourceMark rm; // for error messages | |
2162 | |
2163 // This is the guy we are initializing: | |
2164 if (mh_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } | |
2165 Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); | |
2166 | |
2167 // Early returns out of this method leave the DMH in an unfinished state. | |
2168 assert(java_dyn_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); | |
2169 | |
2170 // which method are we really talking about? | |
2171 if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } | |
2172 oop target_oop = JNIHandles::resolve_non_null(target_jh); | |
2173 if (sun_dyn_MemberName::is_instance(target_oop) && | |
2174 sun_dyn_MemberName::vmindex(target_oop) == VM_INDEX_UNINITIALIZED) { | |
2175 Handle mname(THREAD, target_oop); | |
2176 MethodHandles::resolve_MemberName(mname, CHECK); | |
2177 target_oop = mname(); // in case of GC | |
2178 } | |
2179 | |
2180 int decode_flags = 0; klassOop receiver_limit = NULL; | |
2181 methodHandle m(THREAD, | |
2182 MethodHandles::decode_method(target_oop, | |
2183 receiver_limit, decode_flags)); | |
2184 if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "no such method"); } | |
2185 | |
2186 // The trusted Java code that calls this method should already have performed | |
2187 // access checks on behalf of the given caller. But, we can verify this. | |
2188 if (VerifyMethodHandles && caller_jh != NULL) { | |
2189 KlassHandle caller(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh))); | |
2190 // If this were a bytecode, the first access check would be against | |
2191 // the "reference class" mentioned in the CONSTANT_Methodref. | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2192 // We don't know at this point which class that was, and if we |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2193 // check against m.method_holder we might get the wrong answer. |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2194 // So we just make sure to handle this check when the resolution |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2195 // happens, when we call resolve_MemberName. |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2196 // |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2197 // (A public class can inherit public members from private supers, |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2198 // and it would be wrong to check access against the private super |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2199 // if the original symbolic reference was against the public class.) |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2200 // |
710 | 2201 // If there were a bytecode, the next step would be to lookup the method |
2202 // in the reference class, then then check the method's access bits. | |
2203 // Emulate LinkResolver::check_method_accessability. | |
2204 klassOop resolved_klass = m->method_holder(); | |
2205 if (!Reflection::verify_field_access(caller->as_klassOop(), | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2206 resolved_klass, resolved_klass, |
710 | 2207 m->access_flags(), |
2208 true)) { | |
2209 // %%% following cutout belongs in Reflection::verify_field_access? | |
2210 bool same_pm = Reflection::is_same_package_member(caller->as_klassOop(), | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2211 resolved_klass, THREAD); |
710 | 2212 if (!same_pm) { |
2213 THROW_MSG(vmSymbols::java_lang_InternalError(), m->name_and_sig_as_C_string()); | |
2214 } | |
2215 } | |
2216 } | |
2217 | |
2218 MethodHandles::init_DirectMethodHandle(mh, m, (do_dispatch != JNI_FALSE), CHECK); | |
2219 } | |
2220 JVM_END | |
2221 | |
2222 // bound method handles | |
2223 JVM_ENTRY(void, MHI_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh, | |
2224 jobject target_jh, int argnum)) { | |
2225 ResourceMark rm; // for error messages | |
2226 | |
2227 // This is the guy we are initializing: | |
2228 if (mh_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } | |
2229 Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); | |
2230 | |
2231 // Early returns out of this method leave the BMH in an unfinished state. | |
2232 assert(java_dyn_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); | |
2233 | |
2234 if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } | |
2235 Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); | |
2236 | |
2237 if (!java_dyn_MethodHandle::is_instance(target())) { | |
2238 // Target object is a reflective method. (%%% Do we need this alternate path?) | |
2239 Untested("init_BMH of non-MH"); | |
2240 if (argnum != 0) { THROW(vmSymbols::java_lang_InternalError()); } | |
2241 int decode_flags = 0; klassOop receiver_limit_oop = NULL; | |
2242 methodHandle m(THREAD, | |
2243 MethodHandles::decode_method(target(), | |
2244 receiver_limit_oop, | |
2245 decode_flags)); | |
2246 KlassHandle receiver_limit(THREAD, receiver_limit_oop); | |
2247 MethodHandles::init_BoundMethodHandle_with_receiver(mh, m, | |
2248 receiver_limit, | |
2249 decode_flags, | |
2250 CHECK); | |
2251 return; | |
2252 } | |
2253 | |
2254 // Build a BMH on top of a DMH or another BMH: | |
2255 MethodHandles::init_BoundMethodHandle(mh, target, argnum, CHECK); | |
2256 } | |
2257 JVM_END | |
2258 | |
2259 // adapter method handles | |
2260 JVM_ENTRY(void, MHI_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh, | |
2261 jobject target_jh, int argnum)) { | |
2262 // This is the guy we are initializing: | |
2263 if (mh_jh == NULL || target_jh == NULL) { | |
2264 THROW(vmSymbols::java_lang_InternalError()); | |
2265 } | |
2266 Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); | |
2267 Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); | |
2268 | |
2269 // Early returns out of this method leave the AMH in an unfinished state. | |
2270 assert(java_dyn_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); | |
2271 | |
2272 MethodHandles::init_AdapterMethodHandle(mh, target, argnum, CHECK); | |
2273 } | |
2274 JVM_END | |
2275 | |
2276 // method type forms | |
2277 JVM_ENTRY(void, MHI_init_MT(JNIEnv *env, jobject igcls, jobject erased_jh)) { | |
2278 if (erased_jh == NULL) return; | |
2279 if (TraceMethodHandles) { | |
2280 tty->print("creating MethodType form "); | |
2281 if (WizardMode || Verbose) { // Warning: this calls Java code on the MH! | |
2282 // call Object.toString() | |
2283 symbolOop name = vmSymbols::toString_name(), sig = vmSymbols::void_string_signature(); | |
2284 JavaCallArguments args(Handle(THREAD, JNIHandles::resolve_non_null(erased_jh))); | |
2285 JavaValue result(T_OBJECT); | |
1142 | 2286 JavaCalls::call_virtual(&result, SystemDictionary::Object_klass(), name, sig, |
710 | 2287 &args, CHECK); |
2288 Handle str(THREAD, (oop)result.get_jobject()); | |
2289 java_lang_String::print(str, tty); | |
2290 } | |
2291 tty->cr(); | |
2292 } | |
2293 } | |
2294 JVM_END | |
2295 | |
2296 // debugging and reflection | |
2297 JVM_ENTRY(jobject, MHI_getTarget(JNIEnv *env, jobject igcls, jobject mh_jh, jint format)) { | |
2298 Handle mh(THREAD, JNIHandles::resolve(mh_jh)); | |
2299 if (!java_dyn_MethodHandle::is_instance(mh())) { | |
2300 THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); | |
2301 } | |
2302 oop target = MethodHandles::encode_target(mh, format, CHECK_NULL); | |
2303 return JNIHandles::make_local(THREAD, target); | |
2304 } | |
2305 JVM_END | |
2306 | |
2307 JVM_ENTRY(jint, MHI_getConstant(JNIEnv *env, jobject igcls, jint which)) { | |
2308 switch (which) { | |
2309 case MethodHandles::GC_JVM_PUSH_LIMIT: | |
2310 guarantee(MethodHandlePushLimit >= 2 && MethodHandlePushLimit <= 0xFF, | |
2311 "MethodHandlePushLimit parameter must be in valid range"); | |
2312 return MethodHandlePushLimit; | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2313 case MethodHandles::GC_JVM_STACK_MOVE_UNIT: |
710 | 2314 // return number of words per slot, signed according to stack direction |
2315 return MethodHandles::stack_move_unit(); | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2316 case MethodHandles::GC_CONV_OP_IMPLEMENTED_MASK: |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2317 return MethodHandles::adapter_conversion_ops_supported_mask(); |
710 | 2318 } |
2319 return 0; | |
2320 } | |
2321 JVM_END | |
2322 | |
2323 #ifndef PRODUCT | |
2324 #define EACH_NAMED_CON(template) \ | |
2325 template(MethodHandles,GC_JVM_PUSH_LIMIT) \ | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2326 template(MethodHandles,GC_JVM_STACK_MOVE_UNIT) \ |
710 | 2327 template(MethodHandles,ETF_HANDLE_OR_METHOD_NAME) \ |
2328 template(MethodHandles,ETF_DIRECT_HANDLE) \ | |
2329 template(MethodHandles,ETF_METHOD_NAME) \ | |
2330 template(MethodHandles,ETF_REFLECT_METHOD) \ | |
2331 template(sun_dyn_MemberName,MN_IS_METHOD) \ | |
2332 template(sun_dyn_MemberName,MN_IS_CONSTRUCTOR) \ | |
2333 template(sun_dyn_MemberName,MN_IS_FIELD) \ | |
2334 template(sun_dyn_MemberName,MN_IS_TYPE) \ | |
2335 template(sun_dyn_MemberName,MN_SEARCH_SUPERCLASSES) \ | |
2336 template(sun_dyn_MemberName,MN_SEARCH_INTERFACES) \ | |
2337 template(sun_dyn_MemberName,VM_INDEX_UNINITIALIZED) \ | |
2338 template(sun_dyn_AdapterMethodHandle,OP_RETYPE_ONLY) \ | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2339 template(sun_dyn_AdapterMethodHandle,OP_RETYPE_RAW) \ |
710 | 2340 template(sun_dyn_AdapterMethodHandle,OP_CHECK_CAST) \ |
2341 template(sun_dyn_AdapterMethodHandle,OP_PRIM_TO_PRIM) \ | |
2342 template(sun_dyn_AdapterMethodHandle,OP_REF_TO_PRIM) \ | |
2343 template(sun_dyn_AdapterMethodHandle,OP_PRIM_TO_REF) \ | |
2344 template(sun_dyn_AdapterMethodHandle,OP_SWAP_ARGS) \ | |
2345 template(sun_dyn_AdapterMethodHandle,OP_ROT_ARGS) \ | |
2346 template(sun_dyn_AdapterMethodHandle,OP_DUP_ARGS) \ | |
2347 template(sun_dyn_AdapterMethodHandle,OP_DROP_ARGS) \ | |
2348 template(sun_dyn_AdapterMethodHandle,OP_COLLECT_ARGS) \ | |
2349 template(sun_dyn_AdapterMethodHandle,OP_SPREAD_ARGS) \ | |
2350 template(sun_dyn_AdapterMethodHandle,OP_FLYBY) \ | |
2351 template(sun_dyn_AdapterMethodHandle,OP_RICOCHET) \ | |
2352 template(sun_dyn_AdapterMethodHandle,CONV_OP_LIMIT) \ | |
2353 template(sun_dyn_AdapterMethodHandle,CONV_OP_MASK) \ | |
2354 template(sun_dyn_AdapterMethodHandle,CONV_VMINFO_MASK) \ | |
2355 template(sun_dyn_AdapterMethodHandle,CONV_VMINFO_SHIFT) \ | |
2356 template(sun_dyn_AdapterMethodHandle,CONV_OP_SHIFT) \ | |
2357 template(sun_dyn_AdapterMethodHandle,CONV_DEST_TYPE_SHIFT) \ | |
2358 template(sun_dyn_AdapterMethodHandle,CONV_SRC_TYPE_SHIFT) \ | |
2359 template(sun_dyn_AdapterMethodHandle,CONV_STACK_MOVE_SHIFT) \ | |
2360 template(sun_dyn_AdapterMethodHandle,CONV_STACK_MOVE_MASK) \ | |
2361 /*end*/ | |
2362 | |
2363 #define ONE_PLUS(scope,value) 1+ | |
2364 static const int con_value_count = EACH_NAMED_CON(ONE_PLUS) 0; | |
2365 #define VALUE_COMMA(scope,value) scope::value, | |
2366 static const int con_values[con_value_count+1] = { EACH_NAMED_CON(VALUE_COMMA) 0 }; | |
2367 #define STRING_NULL(scope,value) #value "\0" | |
2368 static const char con_names[] = { EACH_NAMED_CON(STRING_NULL) }; | |
2369 | |
2370 #undef ONE_PLUS | |
2371 #undef VALUE_COMMA | |
2372 #undef STRING_NULL | |
2373 #undef EACH_NAMED_CON | |
2374 #endif | |
2375 | |
2376 JVM_ENTRY(jint, MHI_getNamedCon(JNIEnv *env, jobject igcls, jint which, jobjectArray box_jh)) { | |
2377 #ifndef PRODUCT | |
2378 if (which >= 0 && which < con_value_count) { | |
2379 int con = con_values[which]; | |
2380 objArrayOop box = (objArrayOop) JNIHandles::resolve(box_jh); | |
2381 if (box != NULL && box->klass() == Universe::objectArrayKlassObj() && box->length() > 0) { | |
2382 const char* str = &con_names[0]; | |
2383 for (int i = 0; i < which; i++) | |
2384 str += strlen(str) + 1; // skip name and null | |
2385 oop name = java_lang_String::create_oop_from_str(str, CHECK_0); | |
2386 box->obj_at_put(0, name); | |
2387 } | |
2388 return con; | |
2389 } | |
2390 #endif | |
2391 return 0; | |
2392 } | |
2393 JVM_END | |
2394 | |
2395 // void init(MemberName self, AccessibleObject ref) | |
2396 JVM_ENTRY(void, MHI_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) { | |
2397 if (mname_jh == NULL || target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } | |
2398 Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); | |
2399 oop target_oop = JNIHandles::resolve_non_null(target_jh); | |
2400 MethodHandles::init_MemberName(mname(), target_oop); | |
2401 } | |
2402 JVM_END | |
2403 | |
2404 // void expand(MemberName self) | |
2405 JVM_ENTRY(void, MHI_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) { | |
2406 if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } | |
2407 Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); | |
2408 MethodHandles::expand_MemberName(mname, 0, CHECK); | |
2409 } | |
2410 JVM_END | |
2411 | |
2412 // void resolve(MemberName self, Class<?> caller) | |
2413 JVM_ENTRY(void, MHI_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { | |
2414 if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } | |
2415 Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2416 |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2417 // The trusted Java code that calls this method should already have performed |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2418 // access checks on behalf of the given caller. But, we can verify this. |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2419 if (VerifyMethodHandles && caller_jh != NULL) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2420 klassOop reference_klass = java_lang_Class::as_klassOop(sun_dyn_MemberName::clazz(mname())); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2421 if (reference_klass != NULL) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2422 // Emulate LinkResolver::check_klass_accessability. |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2423 klassOop caller = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh)); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2424 if (!Reflection::verify_class_access(caller, |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2425 reference_klass, |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2426 true)) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2427 THROW_MSG(vmSymbols::java_lang_InternalError(), Klass::cast(reference_klass)->external_name()); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2428 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2429 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2430 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2431 |
710 | 2432 MethodHandles::resolve_MemberName(mname, CHECK); |
2433 } | |
2434 JVM_END | |
2435 | |
2436 // static native int getMembers(Class<?> defc, String matchName, String matchSig, | |
2437 // int matchFlags, Class<?> caller, int skip, MemberName[] results); | |
2438 JVM_ENTRY(jint, MHI_getMembers(JNIEnv *env, jobject igcls, | |
2439 jclass clazz_jh, jstring name_jh, jstring sig_jh, | |
2440 int mflags, jclass caller_jh, jint skip, jobjectArray results_jh)) { | |
2441 if (clazz_jh == NULL || results_jh == NULL) return -1; | |
2442 klassOop k_oop = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz_jh)); | |
2443 | |
2444 objArrayOop results = (objArrayOop) JNIHandles::resolve(results_jh); | |
2445 if (results == NULL || !results->is_objArray()) return -1; | |
2446 | |
2447 symbolOop name = NULL, sig = NULL; | |
2448 if (name_jh != NULL) { | |
2449 name = java_lang_String::as_symbol_or_null(JNIHandles::resolve_non_null(name_jh)); | |
2450 if (name == NULL) return 0; // a match is not possible | |
2451 } | |
2452 if (sig_jh != NULL) { | |
2453 sig = java_lang_String::as_symbol_or_null(JNIHandles::resolve_non_null(sig_jh)); | |
2454 if (sig == NULL) return 0; // a match is not possible | |
2455 } | |
2456 | |
2457 klassOop caller = NULL; | |
2458 if (caller_jh != NULL) { | |
2459 oop caller_oop = JNIHandles::resolve_non_null(caller_jh); | |
2460 if (!java_lang_Class::is_instance(caller_oop)) return -1; | |
2461 caller = java_lang_Class::as_klassOop(caller_oop); | |
2462 } | |
2463 | |
2464 if (name != NULL && sig != NULL && results != NULL) { | |
2465 // try a direct resolve | |
2466 // %%% TO DO | |
2467 } | |
2468 | |
2469 int res = MethodHandles::find_MemberNames(k_oop, name, sig, mflags, | |
2470 caller, skip, results); | |
2471 // TO DO: expand at least some of the MemberNames, to avoid massive callbacks | |
2472 return res; | |
2473 } | |
2474 JVM_END | |
2475 | |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2476 JVM_ENTRY(void, MHI_registerBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh, jobject bsm_jh)) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2477 instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); |
1660
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1552
diff
changeset
|
2478 if (!AllowTransitionalJSR292) { |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1552
diff
changeset
|
2479 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1552
diff
changeset
|
2480 "registerBootstrapMethod is only supported in JSR 292 EDR"); |
083fde3b838e
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
1552
diff
changeset
|
2481 } |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2482 ik->link_class(CHECK); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2483 if (!java_dyn_MethodHandle::is_instance(JNIHandles::resolve(bsm_jh))) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2484 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "method handle"); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2485 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2486 const char* err = NULL; |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2487 if (ik->is_initialized() || ik->is_in_error_state()) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2488 err = "too late: class is already initialized"; |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2489 } else { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2490 ObjectLocker ol(ik, THREAD); // note: this should be a recursive lock |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2491 if (ik->is_not_initialized() || |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2492 (ik->is_being_initialized() && ik->is_reentrant_initialization(THREAD))) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2493 if (ik->bootstrap_method() != NULL) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2494 err = "class is already equipped with a bootstrap method"; |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2495 } else { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2496 ik->set_bootstrap_method(JNIHandles::resolve_non_null(bsm_jh)); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2497 err = NULL; |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2498 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2499 } else { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2500 err = "class is already initialized"; |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2501 if (ik->is_being_initialized()) |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2502 err = "class is already being initialized in a different thread"; |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2503 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2504 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2505 if (err != NULL) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2506 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), err); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2507 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2508 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2509 JVM_END |
710 | 2510 |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2511 JVM_ENTRY(jobject, MHI_getBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh)) { |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2512 instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2513 return JNIHandles::make_local(THREAD, ik->bootstrap_method()); |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2514 } |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2515 JVM_END |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2516 |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2517 JVM_ENTRY(void, MHI_setCallSiteTarget(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2518 // No special action required, yet. |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2519 oop site_oop = JNIHandles::resolve(site_jh); |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2520 if (!java_dyn_CallSite::is_instance(site_oop)) |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2521 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "not a CallSite"); |
1059
389049f3f393
6858164: invokedynamic code needs some cleanup (post-6655638)
jrose
parents:
1039
diff
changeset
|
2522 java_dyn_CallSite::set_target(site_oop, JNIHandles::resolve(target_jh)); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2523 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2524 JVM_END |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2525 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2526 |
710 | 2527 /// JVM_RegisterMethodHandleMethods |
2528 | |
2529 #define ADR "J" | |
2530 | |
2531 #define LANG "Ljava/lang/" | |
2532 #define JDYN "Ljava/dyn/" | |
2533 #define IDYN "Lsun/dyn/" | |
2534 | |
2535 #define OBJ LANG"Object;" | |
2536 #define CLS LANG"Class;" | |
2537 #define STRG LANG"String;" | |
1059
389049f3f393
6858164: invokedynamic code needs some cleanup (post-6655638)
jrose
parents:
1039
diff
changeset
|
2538 #define CST JDYN"CallSite;" |
710 | 2539 #define MT JDYN"MethodType;" |
2540 #define MH JDYN"MethodHandle;" | |
2541 #define MHI IDYN"MethodHandleImpl;" | |
2542 #define MEM IDYN"MemberName;" | |
2543 #define AMH IDYN"AdapterMethodHandle;" | |
2544 #define BMH IDYN"BoundMethodHandle;" | |
2545 #define DMH IDYN"DirectMethodHandle;" | |
2546 | |
2547 #define CC (char*) /*cast a literal from (const char*)*/ | |
2548 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) | |
2549 | |
2550 // These are the native methods on sun.dyn.MethodHandleNatives. | |
2551 static JNINativeMethod methods[] = { | |
2552 // void init(MemberName self, AccessibleObject ref) | |
2553 {CC"init", CC"("AMH""MH"I)V", FN_PTR(MHI_init_AMH)}, | |
2554 {CC"init", CC"("BMH""OBJ"I)V", FN_PTR(MHI_init_BMH)}, | |
2555 {CC"init", CC"("DMH""OBJ"Z"CLS")V", FN_PTR(MHI_init_DMH)}, | |
2556 {CC"init", CC"("MT")V", FN_PTR(MHI_init_MT)}, | |
2557 {CC"init", CC"("MEM""OBJ")V", FN_PTR(MHI_init_Mem)}, | |
2558 {CC"expand", CC"("MEM")V", FN_PTR(MHI_expand_Mem)}, | |
2559 {CC"resolve", CC"("MEM""CLS")V", FN_PTR(MHI_resolve_Mem)}, | |
2560 {CC"getTarget", CC"("MH"I)"OBJ, FN_PTR(MHI_getTarget)}, | |
2561 {CC"getConstant", CC"(I)I", FN_PTR(MHI_getConstant)}, | |
2562 // static native int getNamedCon(int which, Object[] name) | |
2563 {CC"getNamedCon", CC"(I["OBJ")I", FN_PTR(MHI_getNamedCon)}, | |
2564 // static native int getMembers(Class<?> defc, String matchName, String matchSig, | |
2565 // int matchFlags, Class<?> caller, int skip, MemberName[] results); | |
2566 {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHI_getMembers)} | |
2567 }; | |
2568 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2569 // More entry points specifically for EnableInvokeDynamic. |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2570 static JNINativeMethod methods2[] = { |
1507
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2571 {CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHI_registerBootstrap)}, |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2572 {CC"getBootstrap", CC"("CLS")"MH, FN_PTR(MHI_getBootstrap)}, |
cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
1299
diff
changeset
|
2573 {CC"setCallSiteTarget", CC"("CST MH")V", FN_PTR(MHI_setCallSiteTarget)} |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2574 }; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2575 |
710 | 2576 |
2577 // This one function is exported, used by NativeLookup. | |
2578 | |
2579 JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) { | |
2580 assert(MethodHandles::spot_check_entry_names(), "entry enum is OK"); | |
2581 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2582 // note: this explicit warning-producing stuff will be replaced by auto-detection of the JSR 292 classes |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2583 |
710 | 2584 if (!EnableMethodHandles) { |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2585 warning("JSR 292 method handles are disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles to enable."); |
710 | 2586 return; // bind nothing |
2587 } | |
2588 | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2589 bool enable_MH = true; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2590 |
710 | 2591 { |
2592 ThreadToNativeFromVM ttnfv(thread); | |
2593 | |
2594 int status = env->RegisterNatives(MHN_class, methods, sizeof(methods)/sizeof(JNINativeMethod)); | |
2595 if (env->ExceptionOccurred()) { | |
2596 MethodHandles::set_enabled(false); | |
2597 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); | |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2598 enable_MH = false; |
710 | 2599 env->ExceptionClear(); |
2600 } | |
2601 } | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2602 |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2603 if (enable_MH) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2604 KlassHandle MHI_klass = SystemDictionaryHandles::MethodHandleImpl_klass(); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2605 if (MHI_klass.not_null()) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2606 symbolHandle raiseException_name = oopFactory::new_symbol_handle("raiseException", CHECK); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2607 symbolHandle raiseException_sig = oopFactory::new_symbol_handle("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2608 methodOop raiseException_method = instanceKlass::cast(MHI_klass->as_klassOop()) |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2609 ->find_method(raiseException_name(), raiseException_sig()); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2610 if (raiseException_method != NULL && raiseException_method->is_static()) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2611 MethodHandles::set_raise_exception_method(raiseException_method); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2612 } else { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2613 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2614 enable_MH = false; |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2615 } |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2616 } |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2617 } |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2618 |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2619 if (enable_MH) { |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2620 MethodHandles::set_enabled(true); |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2621 } |
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2622 |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2623 if (!EnableInvokeDynamic) { |
1039
987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
jrose
parents:
726
diff
changeset
|
2624 warning("JSR 292 invokedynamic is disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic to enable."); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2625 return; // bind nothing |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2626 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2627 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2628 { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2629 ThreadToNativeFromVM ttnfv(thread); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2630 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2631 int status = env->RegisterNatives(MHN_class, methods2, sizeof(methods2)/sizeof(JNINativeMethod)); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2632 if (env->ExceptionOccurred()) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2633 MethodHandles::set_enabled(false); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2634 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2635 env->ExceptionClear(); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2636 } else { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2637 MethodHandles::set_enabled(true); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2638 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
2639 } |
710 | 2640 } |
2641 JVM_END |