Tue, 14 Jun 2011 14:41:33 -0700
7052219: JSR 292: Crash in ~BufferBlob::MethodHandles adapters
Reviewed-by: twisti, kvn, jrose
1.1 --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp Wed Jun 08 17:04:06 2011 -0700 1.2 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp Tue Jun 14 14:41:33 2011 -0700 1.3 @@ -270,7 +270,7 @@ 1.4 // Emit code to verify that FP is pointing at a valid ricochet frame. 1.5 #ifdef ASSERT 1.6 enum { 1.7 - ARG_LIMIT = 255, SLOP = 35, 1.8 + ARG_LIMIT = 255, SLOP = 45, 1.9 // use this parameter for checking for garbage stack movements: 1.10 UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP) 1.11 // the slop defends against false alarms due to fencepost errors 1.12 @@ -1581,14 +1581,17 @@ 1.13 // argslot = src_addr + swap_bytes 1.14 // destslot = dest_addr 1.15 // while (argslot <= destslot) *(argslot - swap_bytes) = *(argslot + 0), argslot++; 1.16 - __ add(O1_destslot, wordSize, O1_destslot); 1.17 + // dest_slot denotes an exclusive upper limit 1.18 + int limit_bias = OP_ROT_ARGS_DOWN_LIMIT_BIAS; 1.19 + if (limit_bias != 0) 1.20 + __ add(O1_destslot, - limit_bias * wordSize, O1_destslot); 1.21 move_arg_slots_down(_masm, 1.22 Address(O0_argslot, swap_slots * wordSize), 1.23 O1_destslot, 1.24 -swap_slots, 1.25 O0_argslot, O2_scratch); 1.26 1.27 - __ sub(O1_destslot, wordSize, O1_destslot); 1.28 + __ sub(O1_destslot, swap_slots * wordSize, O1_destslot); 1.29 } 1.30 // pop the original first chunk into the destination slot, now free 1.31 switch (swap_slots) {
2.1 --- a/src/cpu/x86/vm/methodHandles_x86.cpp Wed Jun 08 17:04:06 2011 -0700 2.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Tue Jun 14 14:41:33 2011 -0700 2.3 @@ -1644,14 +1644,16 @@ 2.4 // rax = src_addr + swap_bytes 2.5 // rbx = dest_addr 2.6 // while (rax <= rbx) *(rax - swap_bytes) = *(rax + 0), rax++; 2.7 - __ addptr(rbx_destslot, wordSize); 2.8 + // dest_slot denotes an exclusive upper limit 2.9 + int limit_bias = OP_ROT_ARGS_DOWN_LIMIT_BIAS; 2.10 + if (limit_bias != 0) 2.11 + __ addptr(rbx_destslot, - limit_bias * wordSize); 2.12 move_arg_slots_down(_masm, 2.13 Address(rax_argslot, swap_slots * wordSize), 2.14 rbx_destslot, 2.15 -swap_slots, 2.16 rax_argslot, rdx_temp); 2.17 - 2.18 - __ subptr(rbx_destslot, wordSize); 2.19 + __ subptr(rbx_destslot, swap_slots * wordSize); 2.20 } 2.21 // pop the original first chunk into the destination slot, now free 2.22 for (int i = 0; i < swap_slots; i++) {
3.1 --- a/src/share/vm/prims/methodHandleWalk.cpp Wed Jun 08 17:04:06 2011 -0700 3.2 +++ b/src/share/vm/prims/methodHandleWalk.cpp Tue Jun 14 14:41:33 2011 -0700 3.3 @@ -236,9 +236,13 @@ 3.4 case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: 3.5 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: 3.6 case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: 3.7 - case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: 3.8 break; 3.9 3.10 + case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: { 3.11 + tty->print(" src_type = %s", type2name(chain.adapter_conversion_src_type())); 3.12 + break; 3.13 + } 3.14 + 3.15 case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: 3.16 case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: { 3.17 int dest_arg_slot = chain.adapter_conversion_vminfo(); 3.18 @@ -503,25 +507,28 @@ 3.19 } 3.20 3.21 case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: { 3.22 - int dest_arg_slot = chain().adapter_conversion_vminfo(); 3.23 - if (!has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) { 3.24 + int limit_raw = chain().adapter_conversion_vminfo(); 3.25 + bool rot_down = (arg_slot < limit_raw); 3.26 + int limit_bias = (rot_down ? MethodHandles::OP_ROT_ARGS_DOWN_LIMIT_BIAS : 0); 3.27 + int limit_slot = limit_raw - limit_bias; 3.28 + if ((uint)limit_slot > (uint)_outgoing.length()) { 3.29 lose("bad rotate index", CHECK_(empty)); 3.30 } 3.31 // Rotate the source argument (plus following N slots) into the 3.32 // position occupied by the dest argument (plus following N slots). 3.33 int rotate_count = type2size[chain().adapter_conversion_src_type()]; 3.34 // (no other rotate counts are currently supported) 3.35 - if (arg_slot < dest_arg_slot) { 3.36 + if (rot_down) { 3.37 for (int i = 0; i < rotate_count; i++) { 3.38 ArgToken temp = _outgoing.at(arg_slot); 3.39 _outgoing.remove_at(arg_slot); 3.40 - _outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp); 3.41 + _outgoing.insert_before(limit_slot - 1, temp); 3.42 } 3.43 - } else { // arg_slot > dest_arg_slot 3.44 + } else { // arg_slot > limit_slot => rotate_up 3.45 for (int i = 0; i < rotate_count; i++) { 3.46 ArgToken temp = _outgoing.at(arg_slot + rotate_count - 1); 3.47 _outgoing.remove_at(arg_slot + rotate_count - 1); 3.48 - _outgoing.insert_before(dest_arg_slot, temp); 3.49 + _outgoing.insert_before(limit_slot, temp); 3.50 } 3.51 } 3.52 assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); 3.53 @@ -1416,8 +1423,9 @@ 3.54 case T_DOUBLE: emit_bc(Bytecodes::_dreturn); break; 3.55 case T_VOID: emit_bc(Bytecodes::_return); break; 3.56 case T_OBJECT: 3.57 - if (_rklass.not_null() && _rklass() != SystemDictionary::Object_klass()) 3.58 + if (_rklass.not_null() && _rklass() != SystemDictionary::Object_klass() && !Klass::cast(_rklass())->is_interface()) { 3.59 emit_bc(Bytecodes::_checkcast, cpool_klass_put(_rklass())); 3.60 + } 3.61 emit_bc(Bytecodes::_areturn); 3.62 break; 3.63 default: ShouldNotReachHere();
4.1 --- a/src/share/vm/prims/methodHandles.cpp Wed Jun 08 17:04:06 2011 -0700 4.2 +++ b/src/share/vm/prims/methodHandles.cpp Tue Jun 14 14:41:33 2011 -0700 4.3 @@ -205,9 +205,6 @@ 4.4 CodeBuffer code(_adapter_code); 4.5 MethodHandlesAdapterGenerator g(&code); 4.6 g.generate(); 4.7 - 4.8 - // Transfer code comments 4.9 - _adapter_code->set_comments(code.comments()); 4.10 } 4.11 4.12 //------------------------------------------------------------------------------ 4.13 @@ -1980,52 +1977,77 @@ 4.14 } 4.15 break; 4.16 case _adapter_swap_args: 4.17 - case _adapter_rot_args: 4.18 { 4.19 - if (!src || src != dest) { 4.20 + if (!src || !dest) { 4.21 err = "adapter requires src/dest conversion subfields for swap"; break; 4.22 } 4.23 - int swap_size = type2size[src]; 4.24 + int src_size = type2size[src]; 4.25 + if (src_size != type2size[dest]) { 4.26 + err = "adapter requires equal sizes for src/dest"; break; 4.27 + } 4.28 int src_slot = argslot; 4.29 int dest_slot = vminfo; 4.30 - bool rotate_up = (src_slot > dest_slot); // upward rotation 4.31 int src_arg = argnum; 4.32 - int dest_arg = argument_slot_to_argnum(dst_mtype(), dest_slot); 4.33 - verify_vmargslot(target, dest_arg, dest_slot, CHECK); 4.34 - if (!(dest_slot >= src_slot + swap_size) && 4.35 - !(src_slot >= dest_slot + swap_size)) { 4.36 - err = "source, destination slots must be distinct"; 4.37 - } else if (ek == _adapter_swap_args && !(src_slot > dest_slot)) { 4.38 - err = "source of swap must be deeper in stack"; 4.39 - } else if (ek == _adapter_swap_args) { 4.40 - err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype(), dest_arg), 4.41 - java_lang_invoke_MethodType::ptype(dst_mtype(), src_arg), 4.42 - dest_arg); 4.43 - } else if (ek == _adapter_rot_args) { 4.44 - if (rotate_up) { 4.45 - assert((src_slot > dest_slot) && (src_arg < dest_arg), ""); 4.46 - // rotate up: [dest_slot..src_slot-ss] --> [dest_slot+ss..src_slot] 4.47 - // that is: [src_arg+1..dest_arg] --> [src_arg..dest_arg-1] 4.48 - for (int i = src_arg+1; i <= dest_arg && err == NULL; i++) { 4.49 - err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype(), i), 4.50 - java_lang_invoke_MethodType::ptype(dst_mtype(), i-1), 4.51 - i); 4.52 - } 4.53 - } else { // rotate down 4.54 - assert((src_slot < dest_slot) && (src_arg > dest_arg), ""); 4.55 - // rotate down: [src_slot+ss..dest_slot] --> [src_slot..dest_slot-ss] 4.56 - // that is: [dest_arg..src_arg-1] --> [dst_arg+1..src_arg] 4.57 - for (int i = dest_arg; i <= src_arg-1 && err == NULL; i++) { 4.58 - err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype(), i), 4.59 - java_lang_invoke_MethodType::ptype(dst_mtype(), i+1), 4.60 - i); 4.61 - } 4.62 - } 4.63 + int dest_arg = argument_slot_to_argnum(src_mtype(), dest_slot); 4.64 + verify_vmargslot(mh, dest_arg, dest_slot, CHECK); 4.65 + if (!(dest_slot >= src_slot + src_size) && 4.66 + !(src_slot >= dest_slot + src_size)) { 4.67 + err = "source, destination slots must be distinct"; break; 4.68 + } else if (!(src_slot > dest_slot)) { 4.69 + err = "source of swap must be deeper in stack"; break; 4.70 } 4.71 + err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype(), dest_arg), 4.72 + java_lang_invoke_MethodType::ptype(dst_mtype(), src_arg), 4.73 + dest_arg); 4.74 if (err == NULL) 4.75 err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype(), src_arg), 4.76 java_lang_invoke_MethodType::ptype(dst_mtype(), dest_arg), 4.77 src_arg); 4.78 + break; 4.79 + } 4.80 + case _adapter_rot_args: 4.81 + { 4.82 + if (!src || !dest) { 4.83 + err = "adapter requires src/dest conversion subfields for rotate"; break; 4.84 + } 4.85 + int src_slot = argslot; 4.86 + int limit_raw = vminfo; 4.87 + bool rot_down = (src_slot < limit_raw); 4.88 + int limit_bias = (rot_down ? MethodHandles::OP_ROT_ARGS_DOWN_LIMIT_BIAS : 0); 4.89 + int limit_slot = limit_raw - limit_bias; 4.90 + int src_arg = argnum; 4.91 + int limit_arg = argument_slot_to_argnum(src_mtype(), limit_slot); 4.92 + verify_vmargslot(mh, limit_arg, limit_slot, CHECK); 4.93 + if (src_slot == limit_slot) { 4.94 + err = "source, destination slots must be distinct"; break; 4.95 + } 4.96 + if (!rot_down) { // rotate slots up == shift arguments left 4.97 + // limit_slot is an inclusive lower limit 4.98 + assert((src_slot > limit_slot) && (src_arg < limit_arg), ""); 4.99 + // rotate up: [limit_slot..src_slot-ss] --> [limit_slot+ss..src_slot] 4.100 + // that is: [src_arg+1..limit_arg] --> [src_arg..limit_arg-1] 4.101 + for (int i = src_arg+1; i <= limit_arg && err == NULL; i++) { 4.102 + err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype(), i), 4.103 + java_lang_invoke_MethodType::ptype(dst_mtype(), i-1), 4.104 + i); 4.105 + } 4.106 + } else { // rotate slots down == shfit arguments right 4.107 + // limit_slot is an exclusive upper limit 4.108 + assert((src_slot < limit_slot - limit_bias) && (src_arg > limit_arg + limit_bias), ""); 4.109 + // rotate down: [src_slot+ss..limit_slot) --> [src_slot..limit_slot-ss) 4.110 + // that is: (limit_arg..src_arg-1] --> (dst_arg+1..src_arg] 4.111 + for (int i = limit_arg+1; i <= src_arg-1 && err == NULL; i++) { 4.112 + err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype(), i), 4.113 + java_lang_invoke_MethodType::ptype(dst_mtype(), i+1), 4.114 + i); 4.115 + } 4.116 + } 4.117 + if (err == NULL) { 4.118 + int dest_arg = (rot_down ? limit_arg+1 : limit_arg); 4.119 + err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype(), src_arg), 4.120 + java_lang_invoke_MethodType::ptype(dst_mtype(), dest_arg), 4.121 + src_arg); 4.122 + } 4.123 } 4.124 break; 4.125 case _adapter_spread_args: 4.126 @@ -2813,6 +2835,8 @@ 4.127 return MethodHandles::stack_move_unit(); 4.128 case MethodHandles::GC_CONV_OP_IMPLEMENTED_MASK: 4.129 return MethodHandles::adapter_conversion_ops_supported_mask(); 4.130 + case MethodHandles::GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS: 4.131 + return MethodHandles::OP_ROT_ARGS_DOWN_LIMIT_BIAS; 4.132 } 4.133 return 0; 4.134 } 4.135 @@ -2824,6 +2848,8 @@ 4.136 /* template(MethodHandles,GC_JVM_PUSH_LIMIT) */ \ 4.137 /* hold back this one until JDK stabilizes */ \ 4.138 /* template(MethodHandles,GC_JVM_STACK_MOVE_UNIT) */ \ 4.139 + /* hold back this one until JDK stabilizes */ \ 4.140 + /* template(MethodHandles,GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS) */ \ 4.141 template(MethodHandles,ETF_HANDLE_OR_METHOD_NAME) \ 4.142 template(MethodHandles,ETF_DIRECT_HANDLE) \ 4.143 template(MethodHandles,ETF_METHOD_NAME) \
5.1 --- a/src/share/vm/prims/methodHandles.hpp Wed Jun 08 17:04:06 2011 -0700 5.2 +++ b/src/share/vm/prims/methodHandles.hpp Tue Jun 14 14:41:33 2011 -0700 5.3 @@ -581,12 +581,16 @@ 5.4 GC_JVM_PUSH_LIMIT = 0, 5.5 GC_JVM_STACK_MOVE_UNIT = 1, 5.6 GC_CONV_OP_IMPLEMENTED_MASK = 2, 5.7 + GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS = 3, 5.8 5.9 // format of result from getTarget / encode_target: 5.10 ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) 5.11 ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self) 5.12 ETF_METHOD_NAME = 2, // ultimate method as MemberName 5.13 - ETF_REFLECT_METHOD = 3 // ultimate method as java.lang.reflect object (sans refClass) 5.14 + ETF_REFLECT_METHOD = 3, // ultimate method as java.lang.reflect object (sans refClass) 5.15 + 5.16 + // ad hoc constants 5.17 + OP_ROT_ARGS_DOWN_LIMIT_BIAS = -1 5.18 }; 5.19 static int get_named_constant(int which, Handle name_box, TRAPS); 5.20 static oop encode_target(Handle mh, int format, TRAPS); // report vmtarget (to Java code) 5.21 @@ -828,7 +832,7 @@ 5.22 // 5.23 class MethodHandlesAdapterGenerator : public StubCodeGenerator { 5.24 public: 5.25 - MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {} 5.26 + MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code, PrintMethodHandleStubs) {} 5.27 5.28 void generate(); 5.29 };
6.1 --- a/src/share/vm/runtime/globals.hpp Wed Jun 08 17:04:06 2011 -0700 6.2 +++ b/src/share/vm/runtime/globals.hpp Tue Jun 14 14:41:33 2011 -0700 6.3 @@ -3715,6 +3715,9 @@ 6.4 diagnostic(intx, MethodHandlePushLimit, 3, \ 6.5 "number of additional stack slots a method handle may push") \ 6.6 \ 6.7 + diagnostic(bool, PrintMethodHandleStubs, false, \ 6.8 + "Print generated stub code for method handles") \ 6.9 + \ 6.10 develop(bool, TraceMethodHandles, false, \ 6.11 "trace internal method handle operations") \ 6.12 \
7.1 --- a/src/share/vm/runtime/stubCodeGenerator.cpp Wed Jun 08 17:04:06 2011 -0700 7.2 +++ b/src/share/vm/runtime/stubCodeGenerator.cpp Tue Jun 14 14:41:33 2011 -0700 7.3 @@ -80,9 +80,10 @@ 7.4 7.5 // Implementation of StubCodeGenerator 7.6 7.7 -StubCodeGenerator::StubCodeGenerator(CodeBuffer* code) { 7.8 +StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, bool print_code) { 7.9 _masm = new MacroAssembler(code); 7.10 _first_stub = _last_stub = NULL; 7.11 + _print_code = print_code; 7.12 } 7.13 7.14 extern "C" { 7.15 @@ -94,7 +95,7 @@ 7.16 } 7.17 7.18 StubCodeGenerator::~StubCodeGenerator() { 7.19 - if (PrintStubCode) { 7.20 + if (PrintStubCode || _print_code) { 7.21 CodeBuffer* cbuf = _masm->code(); 7.22 CodeBlob* blob = CodeCache::find_blob_unsafe(cbuf->insts()->start()); 7.23 if (blob != NULL) {
8.1 --- a/src/share/vm/runtime/stubCodeGenerator.hpp Wed Jun 08 17:04:06 2011 -0700 8.2 +++ b/src/share/vm/runtime/stubCodeGenerator.hpp Tue Jun 14 14:41:33 2011 -0700 8.3 @@ -98,9 +98,10 @@ 8.4 8.5 StubCodeDesc* _first_stub; 8.6 StubCodeDesc* _last_stub; 8.7 + bool _print_code; 8.8 8.9 public: 8.10 - StubCodeGenerator(CodeBuffer* code); 8.11 + StubCodeGenerator(CodeBuffer* code, bool print_code = false); 8.12 ~StubCodeGenerator(); 8.13 8.14 MacroAssembler* assembler() const { return _masm; }