7052219: JSR 292: Crash in ~BufferBlob::MethodHandles adapters

Tue, 14 Jun 2011 14:41:33 -0700

author
never
date
Tue, 14 Jun 2011 14:41:33 -0700
changeset 2954
f8c9417e3571
parent 2952
5cf771a79037
child 2955
e2ce15aa3daf

7052219: JSR 292: Crash in ~BufferBlob::MethodHandles adapters
Reviewed-by: twisti, kvn, jrose

src/cpu/sparc/vm/methodHandles_sparc.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/methodHandles_x86.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/methodHandleWalk.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/methodHandles.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/methodHandles.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/globals.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/stubCodeGenerator.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/stubCodeGenerator.hpp file | annotate | diff | comparison | revisions
     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; }

mercurial