Mercurial > hg > graal-jvmci-8
comparison src/share/vm/prims/methodHandles.hpp @ 1039:987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
Summary: correctly raise exceptions, support safe bitwise "raw" conversions, fix bugs revealed by VerifyMethodHandles, remove dead code, improve debugging support
Reviewed-by: never, twisti
author | jrose |
---|---|
date | Sat, 17 Oct 2009 19:51:05 -0700 |
parents | e5b0439ef4ae |
children | 9eba43136cb5 |
comparison
equal
deleted
inserted
replaced
1038:71fdc5052e49 | 1039:987e948ebbc8 |
---|---|
30 // JVM support for MethodHandle, MethodType, and related types | 30 // JVM support for MethodHandle, MethodType, and related types |
31 // in java.dyn and java.dyn.hotspot. | 31 // in java.dyn and java.dyn.hotspot. |
32 // See also javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}. | 32 // See also javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}. |
33 public: | 33 public: |
34 enum EntryKind { | 34 enum EntryKind { |
35 _check_mtype, // how a caller calls a MH | 35 _raise_exception, // stub for error generation from other stubs |
36 _wrong_method_type, // what happens when there is a type mismatch | |
37 _invokestatic_mh, // how a MH emulates invokestatic | 36 _invokestatic_mh, // how a MH emulates invokestatic |
38 _invokespecial_mh, // ditto for the other invokes... | 37 _invokespecial_mh, // ditto for the other invokes... |
39 _invokevirtual_mh, | 38 _invokevirtual_mh, |
40 _invokeinterface_mh, | 39 _invokeinterface_mh, |
41 _bound_ref_mh, // reference argument is bound | 40 _bound_ref_mh, // reference argument is bound |
45 _bound_int_direct_mh, | 44 _bound_int_direct_mh, |
46 _bound_long_direct_mh, | 45 _bound_long_direct_mh, |
47 | 46 |
48 _adapter_mh_first, // adapter sequence goes here... | 47 _adapter_mh_first, // adapter sequence goes here... |
49 _adapter_retype_only = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY, | 48 _adapter_retype_only = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY, |
49 _adapter_retype_raw = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW, | |
50 _adapter_check_cast = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST, | 50 _adapter_check_cast = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST, |
51 _adapter_prim_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM, | 51 _adapter_prim_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM, |
52 _adapter_ref_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM, | 52 _adapter_ref_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM, |
53 _adapter_prim_to_ref = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF, | 53 _adapter_prim_to_ref = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF, |
54 _adapter_swap_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS, | 54 _adapter_swap_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS, |
111 }; | 111 }; |
112 | 112 |
113 static bool _enabled; | 113 static bool _enabled; |
114 static MethodHandleEntry* _entries[_EK_LIMIT]; | 114 static MethodHandleEntry* _entries[_EK_LIMIT]; |
115 static const char* _entry_names[_EK_LIMIT+1]; | 115 static const char* _entry_names[_EK_LIMIT+1]; |
116 static jobject _raise_exception_method; | |
117 | |
116 static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; } | 118 static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; } |
117 static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; } | 119 static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; } |
118 | 120 |
119 public: | 121 public: |
120 static bool have_entry(EntryKind ek) { return ek_valid(ek) && _entries[ek] != NULL; } | 122 static bool have_entry(EntryKind ek) { return ek_valid(ek) && _entries[ek] != NULL; } |
127 | 129 |
128 static void init_entry(EntryKind ek, MethodHandleEntry* me) { | 130 static void init_entry(EntryKind ek, MethodHandleEntry* me) { |
129 assert(ek_valid(ek), "oob"); | 131 assert(ek_valid(ek), "oob"); |
130 assert(_entries[ek] == NULL, "no double initialization"); | 132 assert(_entries[ek] == NULL, "no double initialization"); |
131 _entries[ek] = me; | 133 _entries[ek] = me; |
134 } | |
135 | |
136 static methodOop raise_exception_method() { | |
137 oop rem = JNIHandles::resolve(_raise_exception_method); | |
138 assert(rem == NULL || rem->is_method(), ""); | |
139 return (methodOop) rem; | |
140 } | |
141 static void set_raise_exception_method(methodOop rem) { | |
142 assert(_raise_exception_method == NULL, ""); | |
143 _raise_exception_method = JNIHandles::make_global(Handle(rem)); | |
132 } | 144 } |
133 | 145 |
134 static jint adapter_conversion(int conv_op, BasicType src, BasicType dest, | 146 static jint adapter_conversion(int conv_op, BasicType src, BasicType dest, |
135 int stack_move = 0, int vminfo = 0) { | 147 int stack_move = 0, int vminfo = 0) { |
136 assert(conv_op_valid(conv_op), "oob"); | 148 assert(conv_op_valid(conv_op), "oob"); |
241 }; | 253 }; |
242 static methodOop decode_method(oop x, klassOop& receiver_limit_result, int& decode_flags_result); | 254 static methodOop decode_method(oop x, klassOop& receiver_limit_result, int& decode_flags_result); |
243 enum { | 255 enum { |
244 // format of query to getConstant: | 256 // format of query to getConstant: |
245 GC_JVM_PUSH_LIMIT = 0, | 257 GC_JVM_PUSH_LIMIT = 0, |
246 GC_JVM_STACK_MOVE_LIMIT = 1, | 258 GC_JVM_STACK_MOVE_UNIT = 1, |
247 | 259 |
248 // format of result from getTarget / encode_target: | 260 // format of result from getTarget / encode_target: |
249 ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) | 261 ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) |
250 ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self) | 262 ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self) |
251 ETF_METHOD_NAME = 2, // ultimate method as MemberName | 263 ETF_METHOD_NAME = 2, // ultimate method as MemberName |
259 // These checkers operate on a pair of whole MethodTypes: | 271 // These checkers operate on a pair of whole MethodTypes: |
260 static const char* check_method_type_change(oop src_mtype, int src_beg, int src_end, | 272 static const char* check_method_type_change(oop src_mtype, int src_beg, int src_end, |
261 int insert_argnum, oop insert_type, | 273 int insert_argnum, oop insert_type, |
262 int change_argnum, oop change_type, | 274 int change_argnum, oop change_type, |
263 int delete_argnum, | 275 int delete_argnum, |
264 oop dst_mtype, int dst_beg, int dst_end); | 276 oop dst_mtype, int dst_beg, int dst_end, |
277 bool raw = false); | |
265 static const char* check_method_type_insertion(oop src_mtype, | 278 static const char* check_method_type_insertion(oop src_mtype, |
266 int insert_argnum, oop insert_type, | 279 int insert_argnum, oop insert_type, |
267 oop dst_mtype) { | 280 oop dst_mtype) { |
268 oop no_ref = NULL; | 281 oop no_ref = NULL; |
269 return check_method_type_change(src_mtype, 0, -1, | 282 return check_method_type_change(src_mtype, 0, -1, |
276 oop no_ref = NULL; | 289 oop no_ref = NULL; |
277 return check_method_type_change(src_mtype, 0, -1, -1, no_ref, | 290 return check_method_type_change(src_mtype, 0, -1, -1, no_ref, |
278 change_argnum, change_type, | 291 change_argnum, change_type, |
279 -1, dst_mtype, 0, -1); | 292 -1, dst_mtype, 0, -1); |
280 } | 293 } |
281 static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype) { | 294 static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype, bool raw) { |
282 oop no_ref = NULL; | 295 oop no_ref = NULL; |
283 return check_method_type_change(src_mtype, 0, -1, | 296 return check_method_type_change(src_mtype, 0, -1, |
284 -1, no_ref, -1, no_ref, -1, | 297 -1, no_ref, -1, no_ref, -1, |
285 dst_mtype, 0, -1); | 298 dst_mtype, 0, -1, raw); |
286 } | 299 } |
287 | 300 |
288 // These checkers operate on pairs of argument or return types: | 301 // These checkers operate on pairs of argument or return types: |
289 static const char* check_argument_type_change(BasicType src_type, klassOop src_klass, | 302 static const char* check_argument_type_change(BasicType src_type, klassOop src_klass, |
290 BasicType dst_type, klassOop dst_klass, | 303 BasicType dst_type, klassOop dst_klass, |
291 int argnum); | 304 int argnum, bool raw = false); |
292 | 305 |
293 static const char* check_argument_type_change(oop src_type, oop dst_type, | 306 static const char* check_argument_type_change(oop src_type, oop dst_type, |
294 int argnum) { | 307 int argnum, bool raw = false) { |
295 klassOop src_klass = NULL, dst_klass = NULL; | 308 klassOop src_klass = NULL, dst_klass = NULL; |
296 BasicType src_bt = java_lang_Class::as_BasicType(src_type, &src_klass); | 309 BasicType src_bt = java_lang_Class::as_BasicType(src_type, &src_klass); |
297 BasicType dst_bt = java_lang_Class::as_BasicType(dst_type, &dst_klass); | 310 BasicType dst_bt = java_lang_Class::as_BasicType(dst_type, &dst_klass); |
298 return check_argument_type_change(src_bt, src_klass, | 311 return check_argument_type_change(src_bt, src_klass, |
299 dst_bt, dst_klass, argnum); | 312 dst_bt, dst_klass, argnum, raw); |
300 } | 313 } |
301 | 314 |
302 static const char* check_return_type_change(oop src_type, oop dst_type) { | 315 static const char* check_return_type_change(oop src_type, oop dst_type, bool raw = false) { |
303 return check_argument_type_change(src_type, dst_type, -1); | 316 return check_argument_type_change(src_type, dst_type, -1, raw); |
304 } | 317 } |
305 | 318 |
306 static const char* check_return_type_change(BasicType src_type, klassOop src_klass, | 319 static const char* check_return_type_change(BasicType src_type, klassOop src_klass, |
307 BasicType dst_type, klassOop dst_klass) { | 320 BasicType dst_type, klassOop dst_klass) { |
308 return check_argument_type_change(src_type, src_klass, dst_type, dst_klass, -1); | 321 return check_argument_type_change(src_type, src_klass, dst_type, dst_klass, -1); |
355 int decode_flags, | 368 int decode_flags, |
356 KlassHandle receiver_klass, | 369 KlassHandle receiver_klass, |
357 TRAPS); | 370 TRAPS); |
358 | 371 |
359 static bool same_basic_type_for_arguments(BasicType src, BasicType dst, | 372 static bool same_basic_type_for_arguments(BasicType src, BasicType dst, |
373 bool raw = false, | |
360 bool for_return = false); | 374 bool for_return = false); |
361 static bool same_basic_type_for_returns(BasicType src, BasicType dst) { | 375 static bool same_basic_type_for_returns(BasicType src, BasicType dst, bool raw = false) { |
362 return same_basic_type_for_arguments(src, dst, true); | 376 return same_basic_type_for_arguments(src, dst, raw, true); |
363 } | 377 } |
364 | 378 |
365 enum { // arg_mask values | 379 enum { // arg_mask values |
366 _INSERT_NO_MASK = -1, | 380 _INSERT_NO_MASK = -1, |
367 _INSERT_REF_MASK = 0, | 381 _INSERT_REF_MASK = 0, |