7116786: RFE: Detailed information on VerifyErrors
authorkamg
Mon, 06 Aug 2012 15:54:45 -0400
changeset 13476 471200fb94fd
parent 13475 27f1abd05ae9
child 13477 2ac00cd97cf6
7116786: RFE: Detailed information on VerifyErrors Summary: Provide additional detail in VerifyError messages Reviewed-by: sspitsyn, acorn
hotspot/src/os/solaris/vm/dtraceJSDT_solaris.cpp
hotspot/src/share/vm/classfile/stackMapFrame.cpp
hotspot/src/share/vm/classfile/stackMapFrame.hpp
hotspot/src/share/vm/classfile/stackMapTable.cpp
hotspot/src/share/vm/classfile/stackMapTable.hpp
hotspot/src/share/vm/classfile/stackMapTableFormat.hpp
hotspot/src/share/vm/classfile/verificationType.cpp
hotspot/src/share/vm/classfile/verificationType.hpp
hotspot/src/share/vm/classfile/verifier.cpp
hotspot/src/share/vm/classfile/verifier.hpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/src/share/vm/runtime/relocator.cpp
hotspot/src/share/vm/utilities/ostream.cpp
hotspot/src/share/vm/utilities/ostream.hpp
hotspot/test/runtime/7116786/Test7116786.java
hotspot/test/runtime/7116786/testcases.jar
--- a/hotspot/src/os/solaris/vm/dtraceJSDT_solaris.cpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/os/solaris/vm/dtraceJSDT_solaris.cpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -626,45 +626,6 @@
   }
 }
 
-/**
- * This prints out hex data in a 'windbg' or 'xxd' form, where each line is:
- *   <hex-address>: 8 * <hex-halfword> <ascii translation>
- * example:
- * 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000  .DOF............
- * 0000010: 0000 0000 0000 0040 0000 0020 0000 0005  .......@... ....
- * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d  .......@.......]
- * ...
- */
-static void printDOFRawData(void* dof) {
-  size_t size = ((dof_hdr_t*)dof)->dofh_loadsz;
-  size_t limit = (size + 16) / 16 * 16;
-  for (size_t i = 0; i < limit; ++i) {
-    if (i % 16 == 0) {
-      tty->print("%07x:", i);
-    }
-    if (i % 2 == 0) {
-      tty->print(" ");
-    }
-    if (i < size) {
-      tty->print("%02x", ((unsigned char*)dof)[i]);
-    } else {
-      tty->print("  ");
-    }
-    if ((i + 1) % 16 == 0) {
-      tty->print("  ");
-      for (size_t j = 0; j < 16; ++j) {
-        size_t idx = i + j - 15;
-        char c = ((char*)dof)[idx];
-        if (idx < size) {
-          tty->print("%c", c >= 32 && c <= 126 ? c : '.');
-        }
-      }
-      tty->print_cr("");
-    }
-  }
-  tty->print_cr("");
-}
-
 static void printDOFHelper(dof_helper_t* helper) {
   tty->print_cr("// dof_helper_t {");
   tty->print_cr("//   dofhp_mod = \"%s\"", helper->dofhp_mod);
@@ -672,7 +633,8 @@
   tty->print_cr("//   dofhp_dof = 0x%016llx", helper->dofhp_dof);
   printDOF((void*)helper->dofhp_dof);
   tty->print_cr("// }");
-  printDOFRawData((void*)helper->dofhp_dof);
+  size_t len = ((dof_hdr_t*)helper)->dofh_loadsz;
+  tty->print_data((void*)helper->dofhp_dof, len, true);
 }
 
 #else // ndef HAVE_DTRACE_H
--- a/hotspot/src/share/vm/classfile/stackMapFrame.cpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/classfile/stackMapFrame.cpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,9 +32,9 @@
 #include "utilities/globalDefinitions.hpp"
 
 StackMapFrame::StackMapFrame(u2 max_locals, u2 max_stack, ClassVerifier* v) :
-                      _offset(0), _locals_size(0), _stack_size(0), _flags(0),
-                      _max_locals(max_locals), _max_stack(max_stack),
-                      _verifier(v) {
+                      _offset(0), _locals_size(0), _stack_size(0),
+                      _stack_mark(0), _flags(0), _max_locals(max_locals),
+                      _max_stack(max_stack), _verifier(v) {
   Thread* thr = v->thread();
   _locals = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_locals);
   _stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_stack);
@@ -157,17 +157,17 @@
   }
 }
 
-
-bool StackMapFrame::is_assignable_to(
+// Returns the location of the first mismatch, or 'len' if there are no
+// mismatches
+int StackMapFrame::is_assignable_to(
     VerificationType* from, VerificationType* to, int32_t len, TRAPS) const {
-  for (int32_t i = 0; i < len; i++) {
-    bool subtype = to[i].is_assignable_from(
-      from[i], verifier(), THREAD);
-    if (!subtype) {
-      return false;
+  int32_t i = 0;
+  for (i = 0; i < len; i++) {
+    if (!to[i].is_assignable_from(from[i], verifier(), THREAD)) {
+      break;
     }
   }
-  return true;
+  return i;
 }
 
 bool StackMapFrame::has_flag_match_exception(
@@ -209,50 +209,84 @@
 }
 
 bool StackMapFrame::is_assignable_to(
-    const StackMapFrame* target, bool is_exception_handler, TRAPS) const {
-  if (_max_locals != target->max_locals() ||
-      _stack_size != target->stack_size()) {
+    const StackMapFrame* target, bool is_exception_handler,
+    ErrorContext* ctx, TRAPS) const {
+  if (_max_locals != target->max_locals()) {
+    *ctx = ErrorContext::locals_size_mismatch(
+        _offset, (StackMapFrame*)this, (StackMapFrame*)target);
+    return false;
+  }
+  if (_stack_size != target->stack_size()) {
+    *ctx = ErrorContext::stack_size_mismatch(
+        _offset, (StackMapFrame*)this, (StackMapFrame*)target);
     return false;
   }
   // Only need to compare type elements up to target->locals() or target->stack().
   // The remaining type elements in this state can be ignored because they are
   // assignable to bogus type.
-  bool match_locals = is_assignable_to(
-    _locals, target->locals(), target->locals_size(), CHECK_false);
-  bool match_stack = is_assignable_to(
-    _stack, target->stack(), _stack_size, CHECK_false);
+  int mismatch_loc;
+  mismatch_loc = is_assignable_to(
+    _locals, target->locals(), target->locals_size(), THREAD);
+  if (mismatch_loc != target->locals_size()) {
+    *ctx = ErrorContext::bad_type(target->offset(),
+        TypeOrigin::local(mismatch_loc, (StackMapFrame*)this),
+        TypeOrigin::sm_local(mismatch_loc, (StackMapFrame*)target));
+    return false;
+  }
+  mismatch_loc = is_assignable_to(_stack, target->stack(), _stack_size, THREAD);
+  if (mismatch_loc != _stack_size) {
+    *ctx = ErrorContext::bad_type(target->offset(),
+        TypeOrigin::stack(mismatch_loc, (StackMapFrame*)this),
+        TypeOrigin::sm_stack(mismatch_loc, (StackMapFrame*)target));
+    return false;
+  }
+
   bool match_flags = (_flags | target->flags()) == target->flags();
-
-  return match_locals && match_stack &&
-    (match_flags || (is_exception_handler && has_flag_match_exception(target)));
+  if (match_flags || is_exception_handler && has_flag_match_exception(target)) {
+    return true;
+  } else {
+    *ctx = ErrorContext::bad_flags(target->offset(),
+        (StackMapFrame*)this, (StackMapFrame*)target);
+    return false;
+  }
 }
 
 VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) {
   if (_stack_size <= 0) {
-    verifier()->verify_error(_offset, "Operand stack underflow");
+    verifier()->verify_error(
+        ErrorContext::stack_underflow(_offset, this),
+        "Operand stack underflow");
     return VerificationType::bogus_type();
   }
   VerificationType top = _stack[--_stack_size];
   bool subtype = type.is_assignable_from(
     top, verifier(), CHECK_(VerificationType::bogus_type()));
   if (!subtype) {
-    verifier()->verify_error(_offset, "Bad type on operand stack");
+    verifier()->verify_error(
+        ErrorContext::bad_type(_offset, stack_top_ctx(),
+            TypeOrigin::implicit(type)),
+        "Bad type on operand stack");
     return VerificationType::bogus_type();
   }
-  NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
   return top;
 }
 
 VerificationType StackMapFrame::get_local(
     int32_t index, VerificationType type, TRAPS) {
   if (index >= _max_locals) {
-    verifier()->verify_error(_offset, "Local variable table overflow");
+    verifier()->verify_error(
+        ErrorContext::bad_local_index(_offset, index),
+        "Local variable table overflow");
     return VerificationType::bogus_type();
   }
   bool subtype = type.is_assignable_from(_locals[index],
     verifier(), CHECK_(VerificationType::bogus_type()));
   if (!subtype) {
-    verifier()->verify_error(_offset, "Bad local variable type");
+    verifier()->verify_error(
+        ErrorContext::bad_type(_offset,
+          TypeOrigin::local(index, this),
+          TypeOrigin::implicit(type)),
+        "Bad local variable type");
     return VerificationType::bogus_type();
   }
   if(index >= _locals_size) { _locals_size = index + 1; }
@@ -264,23 +298,37 @@
   assert(type1.is_long() || type1.is_double(), "must be long/double");
   assert(type2.is_long2() || type2.is_double2(), "must be long/double_2");
   if (index >= _locals_size - 1) {
-    verifier()->verify_error(_offset, "get long/double overflows locals");
+    verifier()->verify_error(
+        ErrorContext::bad_local_index(_offset, index),
+        "get long/double overflows locals");
     return;
   }
-  bool subtype1 = type1.is_assignable_from(
-    _locals[index], verifier(), CHECK);
-  bool subtype2 = type2.is_assignable_from(
-    _locals[index+1], verifier(), CHECK);
-  if (!subtype1 || !subtype2) {
-    verifier()->verify_error(_offset, "Bad local variable type");
-    return;
+  bool subtype = type1.is_assignable_from(_locals[index], verifier(), CHECK);
+  if (!subtype) {
+    verifier()->verify_error(
+        ErrorContext::bad_type(_offset,
+            TypeOrigin::local(index, this), TypeOrigin::implicit(type1)),
+        "Bad local variable type");
+  } else {
+    subtype = type2.is_assignable_from(_locals[index + 1], verifier(), CHECK);
+    if (!subtype) {
+      /* Unreachable? All local store routines convert a split long or double
+       * into a TOP during the store.  So we should never end up seeing an
+       * orphaned half.  */
+      verifier()->verify_error(
+          ErrorContext::bad_type(_offset,
+              TypeOrigin::local(index + 1, this), TypeOrigin::implicit(type2)),
+          "Bad local variable type");
+    }
   }
 }
 
 void StackMapFrame::set_local(int32_t index, VerificationType type, TRAPS) {
   assert(!type.is_check(), "Must be a real type");
   if (index >= _max_locals) {
-    verifier()->verify_error("Local variable table overflow", _offset);
+    verifier()->verify_error(
+        ErrorContext::bad_local_index(_offset, index),
+        "Local variable table overflow");
     return;
   }
   // If type at index is double or long, set the next location to be unusable
@@ -310,7 +358,9 @@
   assert(type1.is_long() || type1.is_double(), "must be long/double");
   assert(type2.is_long2() || type2.is_double2(), "must be long/double_2");
   if (index >= _max_locals - 1) {
-    verifier()->verify_error("Local variable table overflow", _offset);
+    verifier()->verify_error(
+        ErrorContext::bad_local_index(_offset, index),
+        "Local variable table overflow");
     return;
   }
   // If type at index+1 is double or long, set the next location to be unusable
@@ -336,21 +386,30 @@
   }
 }
 
-#ifndef PRODUCT
-
-void StackMapFrame::print() const {
-  tty->print_cr("stackmap_frame[%d]:", _offset);
-  tty->print_cr("flags = 0x%x", _flags);
-  tty->print("locals[%d] = { ", _locals_size);
-  for (int32_t i = 0; i < _locals_size; i++) {
-    _locals[i].print_on(tty);
-  }
-  tty->print_cr(" }");
-  tty->print("stack[%d] = { ", _stack_size);
-  for (int32_t j = 0; j < _stack_size; j++) {
-    _stack[j].print_on(tty);
-  }
-  tty->print_cr(" }");
+TypeOrigin StackMapFrame::stack_top_ctx() {
+  return TypeOrigin::stack(_stack_size, this);
 }
 
-#endif
+void StackMapFrame::print_on(outputStream* str) const {
+  str->indent().print_cr("bci: @%d", _offset);
+  str->indent().print_cr("flags: {%s }",
+      flag_this_uninit() ? " flagThisUninit" : "");
+  str->indent().print("locals: {");
+  for (int32_t i = 0; i < _locals_size; ++i) {
+    str->print(" ");
+    _locals[i].print_on(str);
+    if (i != _locals_size - 1) {
+      str->print(",");
+    }
+  }
+  str->print_cr(" }");
+  str->indent().print("stack: {");
+  for (int32_t j = 0; j < _stack_size; ++j) {
+    str->print(" ");
+    _stack[j].print_on(str);
+    if (j != _stack_size - 1) {
+      str->print(",");
+    }
+  }
+  str->print_cr(" }");
+}
--- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,8 @@
 
 // A StackMapFrame represents one frame in the stack map attribute.
 
+class TypeContext;
+
 enum {
   FLAG_THIS_UNINIT = 0x01
 };
@@ -47,6 +49,10 @@
   int32_t _locals_size;  // number of valid type elements in _locals
   int32_t _stack_size;   // number of valid type elements in _stack
 
+  int32_t _stack_mark;   // Records the size of the stack prior to an
+                         // instruction modification, to allow rewinding
+                         // when/if an error occurs.
+
   int32_t _max_locals;
   int32_t _max_stack;
 
@@ -56,6 +62,31 @@
 
   ClassVerifier* _verifier;  // the verifier verifying this method
 
+  StackMapFrame(const StackMapFrame& cp) :
+      _offset(cp._offset), _locals_size(cp._locals_size),
+      _stack_size(cp._stack_size), _stack_mark(cp._stack_mark),
+      _max_locals(cp._max_locals), _max_stack(cp._max_stack),
+      _flags(cp._flags) {
+    _locals = NEW_RESOURCE_ARRAY(VerificationType, _max_locals);
+    for (int i = 0; i < _max_locals; ++i) {
+      if (i < _locals_size) {
+        _locals[i] = cp._locals[i];
+      } else {
+        _locals[i] = VerificationType::bogus_type();
+      }
+    }
+    int ss = MAX2(_stack_size, _stack_mark);
+    _stack = NEW_RESOURCE_ARRAY(VerificationType, _max_stack);
+    for (int i = 0; i < _max_stack; ++i) {
+      if (i < ss) {
+        _stack[i] = cp._stack[i];
+      } else {
+        _stack[i] = VerificationType::bogus_type();
+      }
+    }
+    _verifier = NULL;
+  }
+
  public:
   // constructors
 
@@ -77,16 +108,21 @@
                 ClassVerifier* v) : _offset(offset), _flags(flags),
                                     _locals_size(locals_size),
                                     _stack_size(stack_size),
+                                    _stack_mark(-1),
                                     _max_locals(max_locals),
                                     _max_stack(max_stack),
                                     _locals(locals), _stack(stack),
                                     _verifier(v) { }
 
+  static StackMapFrame* copy(StackMapFrame* smf) {
+    return new StackMapFrame(*smf);
+  }
+
   inline void set_offset(int32_t offset)      { _offset = offset; }
   inline void set_verifier(ClassVerifier* v)  { _verifier = v; }
   inline void set_flags(u1 flags)             { _flags = flags; }
   inline void set_locals_size(u2 locals_size) { _locals_size = locals_size; }
-  inline void set_stack_size(u2 stack_size)   { _stack_size = stack_size; }
+  inline void set_stack_size(u2 stack_size)   { _stack_size = _stack_mark = stack_size; }
   inline void clear_stack()                   { _stack_size = 0; }
   inline int32_t offset()   const             { return _offset; }
   inline ClassVerifier* verifier() const      { return _verifier; }
@@ -134,14 +170,37 @@
   void copy_stack(const StackMapFrame* src);
 
   // Return true if this stack map frame is assignable to target.
-  bool is_assignable_to(const StackMapFrame* target,
-                        bool is_exception_handler, TRAPS) const;
+  bool is_assignable_to(
+      const StackMapFrame* target, bool is_exception_handler,
+      ErrorContext* ctx, TRAPS) const;
+
+  inline void set_mark() {
+#ifdef DEBUG
+    // Put bogus type to indicate it's no longer valid.
+    if (_stack_mark != -1) {
+      for (int i = _stack_mark; i >= _stack_size; --i) {
+        _stack[i] = VerificationType::bogus_type();
+      }
+    }
+#endif // def DEBUG
+    _stack_mark = _stack_size;
+  }
+
+  // Used when an error occurs and we want to reset the stack to the state
+  // it was before operands were popped off.
+  void restore() {
+    if (_stack_mark != -1) {
+      _stack_size = _stack_mark;
+    }
+  }
 
   // Push type into stack type array.
   inline void push_stack(VerificationType type, TRAPS) {
     assert(!type.is_check(), "Must be a real type");
     if (_stack_size >= _max_stack) {
-      verifier()->verify_error(_offset, "Operand stack overflow");
+      verifier()->verify_error(
+          ErrorContext::stack_overflow(_offset, this),
+          "Operand stack overflow");
       return;
     }
     _stack[_stack_size++] = type;
@@ -152,7 +211,9 @@
     assert(type1.is_long() || type1.is_double(), "must be long/double");
     assert(type2.is_long2() || type2.is_double2(), "must be long/double_2");
     if (_stack_size >= _max_stack - 1) {
-      verifier()->verify_error(_offset, "Operand stack overflow");
+      verifier()->verify_error(
+          ErrorContext::stack_overflow(_offset, this),
+          "Operand stack overflow");
       return;
     }
     _stack[_stack_size++] = type1;
@@ -162,13 +223,12 @@
   // Pop and return the top type on stack without verifying.
   inline VerificationType pop_stack(TRAPS) {
     if (_stack_size <= 0) {
-      verifier()->verify_error(_offset, "Operand stack underflow");
+      verifier()->verify_error(
+          ErrorContext::stack_underflow(_offset, this),
+          "Operand stack underflow");
       return VerificationType::bogus_type();
     }
-    // Put bogus type to indicate it's no longer valid.
-    // Added to make it consistent with the other pop_stack method.
     VerificationType top = _stack[--_stack_size];
-    NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
     return top;
   }
 
@@ -180,8 +240,7 @@
       bool subtype = type.is_assignable_from(
         top, verifier(), CHECK_(VerificationType::bogus_type()));
       if (subtype) {
-        _stack_size --;
-        NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
+        --_stack_size;
         return top;
       }
     }
@@ -199,8 +258,6 @@
       bool subtype2 = type2.is_assignable_from(top2, verifier(), CHECK);
       if (subtype1 && subtype2) {
         _stack_size -= 2;
-        NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
-        NOT_PRODUCT( _stack[_stack_size+1] = VerificationType::bogus_type(); )
         return;
       }
     }
@@ -208,6 +265,14 @@
     pop_stack_ex(type2, THREAD);
   }
 
+  VerificationType local_at(int index) {
+    return _locals[index];
+  }
+
+  VerificationType stack_at(int index) {
+    return _stack[index];
+  }
+
   // Uncommon case that throws exceptions.
   VerificationType pop_stack_ex(VerificationType type, TRAPS);
 
@@ -226,13 +291,14 @@
 
   // Private auxiliary method used only in is_assignable_to(StackMapFrame).
   // Returns true if src is assignable to target.
-  bool is_assignable_to(
+  int is_assignable_to(
     VerificationType* src, VerificationType* target, int32_t len, TRAPS) const;
 
   bool has_flag_match_exception(const StackMapFrame* target) const;
 
-  // Debugging
-  void print() const PRODUCT_RETURN;
+  TypeOrigin stack_top_ctx();
+
+  void print_on(outputStream* str) const;
 };
 
 #endif // SHARE_VM_CLASSFILE_STACKMAPFRAME_HPP
--- a/hotspot/src/share/vm/classfile/stackMapTable.cpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/classfile/stackMapTable.cpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,9 @@
       _frame_array[i] = frame;
       int offset = frame->offset();
       if (offset >= code_len || code_data[offset] == 0) {
-        frame->verifier()->verify_error("StackMapTable error: bad offset");
+        frame->verifier()->verify_error(
+            ErrorContext::bad_stackmap(i, frame),
+            "StackMapTable error: bad offset");
         return;
       }
       pre_frame = frame;
@@ -68,12 +70,9 @@
 
 bool StackMapTable::match_stackmap(
     StackMapFrame* frame, int32_t target,
-    bool match, bool update, TRAPS) const {
+    bool match, bool update, ErrorContext* ctx, TRAPS) const {
   int index = get_index_from_offset(target);
-
-  return match_stackmap(
-    frame, target, index, match,
-    update, CHECK_VERIFY_(frame->verifier(), false));
+  return match_stackmap(frame, target, index, match, update, ctx, THREAD);
 }
 
 // Match and/or update current_frame to the frame in stackmap table with
@@ -88,23 +87,23 @@
 // unconditional branch:                                 true   true
 bool StackMapTable::match_stackmap(
     StackMapFrame* frame, int32_t target, int32_t frame_index,
-    bool match, bool update, TRAPS) const {
+    bool match, bool update, ErrorContext* ctx, TRAPS) const {
   if (frame_index < 0 || frame_index >= _frame_count) {
-    frame->verifier()->verify_error(frame->offset(),
-      "Expecting a stackmap frame at branch target %d", target);
+    *ctx = ErrorContext::missing_stackmap(frame->offset());
+    frame->verifier()->verify_error(
+        *ctx, "Expecting a stackmap frame at branch target %d", target);
     return false;
   }
 
+  StackMapFrame *stackmap_frame = _frame_array[frame_index];
   bool result = true;
-  StackMapFrame *stackmap_frame = _frame_array[frame_index];
   if (match) {
     // when checking handler target, match == true && update == false
     bool is_exception_handler = !update;
     // Has direct control flow from last instruction, need to match the two
     // frames.
-    result = frame->is_assignable_to(
-      stackmap_frame, is_exception_handler,
-      CHECK_VERIFY_(frame->verifier(), false));
+    result = frame->is_assignable_to(stackmap_frame, is_exception_handler,
+        ctx, CHECK_VERIFY_(frame->verifier(), result));
   }
   if (update) {
     // Use the frame in stackmap table as current frame
@@ -125,11 +124,12 @@
 
 void StackMapTable::check_jump_target(
     StackMapFrame* frame, int32_t target, TRAPS) const {
+  ErrorContext ctx;
   bool match = match_stackmap(
-    frame, target, true, false, CHECK_VERIFY(frame->verifier()));
+    frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
   if (!match || (target < 0 || target >= _code_length)) {
-    frame->verifier()->verify_error(frame->offset(),
-      "Inconsistent stackmap frames at branch target %d", target);
+    frame->verifier()->verify_error(ctx,
+        "Inconsistent stackmap frames at branch target %d", target);
     return;
   }
   // check if uninitialized objects exist on backward branches
@@ -139,25 +139,25 @@
 void StackMapTable::check_new_object(
     const StackMapFrame* frame, int32_t target, TRAPS) const {
   if (frame->offset() > target && frame->has_new_object()) {
-    frame->verifier()->verify_error(frame->offset(),
-      "Uninitialized object exists on backward branch %d", target);
+    frame->verifier()->verify_error(
+        ErrorContext::bad_code(frame->offset()),
+        "Uninitialized object exists on backward branch %d", target);
     return;
   }
 }
 
-#ifndef PRODUCT
-
-void StackMapTable::print() const {
-  tty->print_cr("StackMapTable: frame_count = %d", _frame_count);
-  tty->print_cr("table = { ");
-  for (int32_t i = 0; i < _frame_count; i++) {
-    _frame_array[i]->print();
+void StackMapTable::print_on(outputStream* str) const {
+  str->indent().print_cr("StackMapTable: frame_count = %d", _frame_count);
+  str->indent().print_cr("table = { ");
+  {
+    streamIndentor si(str);
+    for (int32_t i = 0; i < _frame_count; ++i) {
+      _frame_array[i]->print_on(str);
+    }
   }
-  tty->print_cr(" }");
+  str->print_cr(" }");
 }
 
-#endif
-
 int32_t StackMapReader::chop(
     VerificationType* locals, int32_t length, int32_t chops) {
   if (locals == NULL) return -1;
--- a/hotspot/src/share/vm/classfile/stackMapTable.hpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/classfile/stackMapTable.hpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 #define SHARE_VM_CLASSFILE_STACKMAPTABLE_HPP
 
 #include "classfile/stackMapFrame.hpp"
+#include "classfile/verifier.hpp"
 #include "memory/allocation.hpp"
 #include "oops/constantPoolOop.hpp"
 #include "oops/methodOop.hpp"
@@ -73,12 +74,12 @@
   // specified offset. Return true if the two frames match.
   bool match_stackmap(
     StackMapFrame* current_frame, int32_t offset,
-    bool match, bool update, TRAPS) const;
+    bool match, bool update, ErrorContext* ctx, TRAPS) const;
   // Match and/or update current_frame to the frame in stackmap table with
   // specified offset and frame index. Return true if the two frames match.
   bool match_stackmap(
     StackMapFrame* current_frame, int32_t offset, int32_t frame_index,
-    bool match, bool update, TRAPS) const;
+    bool match, bool update, ErrorContext* ctx, TRAPS) const;
 
   // Check jump instructions. Make sure there are no uninitialized
   // instances on backward branch.
@@ -93,8 +94,7 @@
   void check_new_object(
     const StackMapFrame* frame, int32_t target, TRAPS) const;
 
-  // Debugging
-  void print() const PRODUCT_RETURN;
+  void print_on(outputStream* str) const;
 };
 
 class StackMapStream : StackObj {
--- a/hotspot/src/share/vm/classfile/stackMapTableFormat.hpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/classfile/stackMapTableFormat.hpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -135,7 +135,6 @@
                 !is_object() && !is_uninitialized()));
   }
 
-#ifdef ASSERT
   void print_on(outputStream* st) {
     switch (tag()) {
       case ITEM_Top: st->print("Top"); break;
@@ -154,14 +153,13 @@
         assert(false, "Bad verification_type_info");
     }
   }
-#endif
 };
 
 #define FOR_EACH_STACKMAP_FRAME_TYPE(macro, arg1, arg2) \
   macro(same_frame, arg1, arg2) \
   macro(same_frame_extended, arg1, arg2) \
-  macro(same_frame_1_stack_item_frame, arg1, arg2) \
-  macro(same_frame_1_stack_item_extended, arg1, arg2) \
+  macro(same_locals_1_stack_item_frame, arg1, arg2) \
+  macro(same_locals_1_stack_item_extended, arg1, arg2) \
   macro(chop_frame, arg1, arg2) \
   macro(append_frame, arg1, arg2) \
   macro(full_frame, arg1, arg2)
@@ -203,9 +201,8 @@
   // that we don't read past a particular memory limit.  It returns false
   // if any part of the data structure is outside the specified memory bounds.
   inline bool verify(address start, address end) const;
-#ifdef ASSERT
-  inline void print_on(outputStream* st) const;
-#endif
+
+  inline void print_on(outputStream* st, int current_offset) const;
 
   // Create as_xxx and is_xxx methods for the subtypes
 #define FRAME_TYPE_DECL(stackmap_frame_type, arg1, arg2) \
@@ -263,11 +260,9 @@
     return true;
   }
 
-#ifdef ASSERT
-  void print_on(outputStream* st) const {
-    st->print("same_frame(%d)", offset_delta());
+  void print_on(outputStream* st, int current_offset = -1) const {
+    st->print("same_frame(@%d)", offset_delta() + current_offset);
   }
-#endif
 };
 
 class same_frame_extended : public stack_map_frame {
@@ -311,14 +306,12 @@
     return frame_type_addr() + size() <= end;
   }
 
-#ifdef ASSERT
-  void print_on(outputStream* st) const {
-    st->print("same_frame_extended(%d)", offset_delta());
+  void print_on(outputStream* st, int current_offset = -1) const {
+    st->print("same_frame_extended(@%d)", offset_delta() + current_offset);
   }
-#endif
 };
 
-class same_frame_1_stack_item_frame : public stack_map_frame {
+class same_locals_1_stack_item_frame : public stack_map_frame {
  private:
   address type_addr() const { return frame_type_addr() + sizeof(u1); }
 
@@ -332,14 +325,14 @@
     return tag >= 64 && tag < 128;
   }
 
-  static same_frame_1_stack_item_frame* at(address addr) {
+  static same_locals_1_stack_item_frame* at(address addr) {
     assert(is_frame_type(*addr), "Wrong frame id");
-    return (same_frame_1_stack_item_frame*)addr;
+    return (same_locals_1_stack_item_frame*)addr;
   }
 
-  static same_frame_1_stack_item_frame* create_at(
+  static same_locals_1_stack_item_frame* create_at(
       address addr, int offset_delta, verification_type_info* vti) {
-    same_frame_1_stack_item_frame* sm = (same_frame_1_stack_item_frame*)addr;
+    same_locals_1_stack_item_frame* sm = (same_locals_1_stack_item_frame*)addr;
     sm->set_offset_delta(offset_delta);
     if (vti != NULL) {
       sm->set_type(vti);
@@ -382,16 +375,15 @@
     return types()->verify(start, end);
   }
 
-#ifdef ASSERT
-  void print_on(outputStream* st) const {
-    st->print("same_frame_1_stack_item_frame(%d,", offset_delta());
+  void print_on(outputStream* st, int current_offset = -1) const {
+    st->print("same_locals_1_stack_item_frame(@%d,",
+        offset_delta() + current_offset);
     types()->print_on(st);
     st->print(")");
   }
-#endif
 };
 
-class same_frame_1_stack_item_extended : public stack_map_frame {
+class same_locals_1_stack_item_extended : public stack_map_frame {
  private:
   address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
   address type_addr() const { return offset_delta_addr() + sizeof(u2); }
@@ -403,15 +395,15 @@
     return tag == _frame_id;
   }
 
-  static same_frame_1_stack_item_extended* at(address addr) {
+  static same_locals_1_stack_item_extended* at(address addr) {
     assert(is_frame_type(*addr), "Wrong frame id");
-    return (same_frame_1_stack_item_extended*)addr;
+    return (same_locals_1_stack_item_extended*)addr;
   }
 
-  static same_frame_1_stack_item_extended* create_at(
+  static same_locals_1_stack_item_extended* create_at(
       address addr, int offset_delta, verification_type_info* vti) {
-    same_frame_1_stack_item_extended* sm =
-       (same_frame_1_stack_item_extended*)addr;
+    same_locals_1_stack_item_extended* sm =
+       (same_locals_1_stack_item_extended*)addr;
     sm->set_frame_type(_frame_id);
     sm->set_offset_delta(offset_delta);
     if (vti != NULL) {
@@ -448,13 +440,12 @@
     return type_addr() < end && types()->verify(start, end);
   }
 
-#ifdef ASSERT
-  void print_on(outputStream* st) const {
-    st->print("same_frame_1_stack_item_extended(%d,", offset_delta());
+  void print_on(outputStream* st, int current_offset = -1) const {
+    st->print("same_locals_1_stack_item_extended(@%d,",
+        offset_delta() + current_offset);
     types()->print_on(st);
     st->print(")");
   }
-#endif
 };
 
 class chop_frame : public stack_map_frame {
@@ -517,11 +508,9 @@
     return frame_type_addr() + size() <= end;
   }
 
-#ifdef ASSERT
-  void print_on(outputStream* st) const {
-    st->print("chop_frame(%d,%d)", offset_delta(), chops());
+  void print_on(outputStream* st, int current_offset = -1) const {
+    st->print("chop_frame(@%d,%d)", offset_delta() + current_offset, chops());
   }
-#endif
 };
 
 class append_frame : public stack_map_frame {
@@ -618,9 +607,8 @@
     return false;
   }
 
-#ifdef ASSERT
-  void print_on(outputStream* st) const {
-    st->print("append_frame(%d,", offset_delta());
+  void print_on(outputStream* st, int current_offset = -1) const {
+    st->print("append_frame(@%d,", offset_delta() + current_offset);
     verification_type_info* vti = types();
     for (int i = 0; i < number_of_types(); ++i) {
       vti->print_on(st);
@@ -631,7 +619,6 @@
     }
     st->print(")");
   }
-#endif
 };
 
 class full_frame : public stack_map_frame {
@@ -774,9 +761,8 @@
     return true;
   }
 
-#ifdef ASSERT
-  void print_on(outputStream* st) const {
-    st->print("full_frame(%d,{", offset_delta());
+  void print_on(outputStream* st, int current_offset = -1) const {
+    st->print("full_frame(@%d,{", offset_delta() + current_offset);
     verification_type_info* vti = locals();
     for (int i = 0; i < num_locals(); ++i) {
       vti->print_on(st);
@@ -798,7 +784,6 @@
     }
     st->print("})");
   }
-#endif
 };
 
 #define VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \
@@ -852,11 +837,9 @@
   return false;
 }
 
-#ifdef ASSERT
-void stack_map_frame::print_on(outputStream* st) const {
-  FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st));
+void stack_map_frame::print_on(outputStream* st, int offs = -1) const {
+  FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st, offs));
 }
-#endif
 
 #undef VIRTUAL_DISPATCH
 #undef VOID_VIRTUAL_DISPATCH
@@ -873,16 +856,46 @@
 FOR_EACH_STACKMAP_FRAME_TYPE(AS_SUBTYPE_DEF, x, x)
 #undef AS_SUBTYPE_DEF
 
+class stack_map_table {
+ private:
+  address number_of_entries_addr() const {
+    return (address)this;
+  }
+  address entries_addr() const {
+    return number_of_entries_addr() + sizeof(u2);
+  }
+
+ protected:
+  // No constructors  - should be 'private', but GCC issues a warning if it is
+  stack_map_table() {}
+  stack_map_table(const stack_map_table&) {}
+
+ public:
+
+  static stack_map_table* at(address addr) {
+    return (stack_map_table*)addr;
+  }
+
+  u2 number_of_entries() const {
+    return Bytes::get_Java_u2(number_of_entries_addr());
+  }
+  stack_map_frame* entries() const {
+    return stack_map_frame::at(entries_addr());
+  }
+
+  void set_number_of_entries(u2 num) {
+    Bytes::put_Java_u2(number_of_entries_addr(), num);
+  }
+};
+
 class stack_map_table_attribute {
  private:
   address name_index_addr() const {
       return (address)this; }
   address attribute_length_addr() const {
       return name_index_addr() + sizeof(u2); }
-  address number_of_entries_addr() const {
+  address stack_map_table_addr() const {
       return attribute_length_addr() + sizeof(u4); }
-  address entries_addr() const {
-      return number_of_entries_addr() + sizeof(u2); }
 
  protected:
   // No constructors  - should be 'private', but GCC issues a warning if it is
@@ -896,17 +909,11 @@
   }
 
   u2 name_index() const {
-       return Bytes::get_Java_u2(name_index_addr()); }
+    return Bytes::get_Java_u2(name_index_addr()); }
   u4 attribute_length() const {
-      return Bytes::get_Java_u4(attribute_length_addr()); }
-  u2 number_of_entries() const {
-      return Bytes::get_Java_u2(number_of_entries_addr()); }
-  stack_map_frame* entries() const {
-    return stack_map_frame::at(entries_addr());
-  }
-
-  static size_t header_size() {
-      return sizeof(u2) + sizeof(u4);
+    return Bytes::get_Java_u4(attribute_length_addr()); }
+  stack_map_table* table() const {
+    return stack_map_table::at(stack_map_table_addr());
   }
 
   void set_name_index(u2 idx) {
@@ -915,9 +922,8 @@
   void set_attribute_length(u4 len) {
     Bytes::put_Java_u4(attribute_length_addr(), len);
   }
-  void set_number_of_entries(u2 num) {
-    Bytes::put_Java_u2(number_of_entries_addr(), num);
-  }
 };
 
+#undef FOR_EACH_STACKMAP_FRAME_TYPE
+
 #endif // SHARE_VM_CLASSFILE_STACKMAPTABLEFORMAT_HPP
--- a/hotspot/src/share/vm/classfile/verificationType.cpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/classfile/verificationType.cpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -110,34 +110,34 @@
   }
 }
 
-#ifndef PRODUCT
-
 void VerificationType::print_on(outputStream* st) const {
   switch (_u._data) {
-    case Bogus:            st->print(" bogus "); break;
-    case Category1:        st->print(" category1 "); break;
-    case Category2:        st->print(" category2 "); break;
-    case Category2_2nd:    st->print(" category2_2nd "); break;
-    case Boolean:          st->print(" boolean "); break;
-    case Byte:             st->print(" byte "); break;
-    case Short:            st->print(" short "); break;
-    case Char:             st->print(" char "); break;
-    case Integer:          st->print(" integer "); break;
-    case Float:            st->print(" float "); break;
-    case Long:             st->print(" long "); break;
-    case Double:           st->print(" double "); break;
-    case Long_2nd:         st->print(" long_2nd "); break;
-    case Double_2nd:       st->print(" double_2nd "); break;
-    case Null:             st->print(" null "); break;
+    case Bogus:            st->print("top"); break;
+    case Category1:        st->print("category1"); break;
+    case Category2:        st->print("category2"); break;
+    case Category2_2nd:    st->print("category2_2nd"); break;
+    case Boolean:          st->print("boolean"); break;
+    case Byte:             st->print("byte"); break;
+    case Short:            st->print("short"); break;
+    case Char:             st->print("char"); break;
+    case Integer:          st->print("integer"); break;
+    case Float:            st->print("float"); break;
+    case Long:             st->print("long"); break;
+    case Double:           st->print("double"); break;
+    case Long_2nd:         st->print("long_2nd"); break;
+    case Double_2nd:       st->print("double_2nd"); break;
+    case Null:             st->print("null"); break;
+    case ReferenceQuery:   st->print("reference type"); break;
+    case Category1Query:   st->print("category1 type"); break;
+    case Category2Query:   st->print("category2 type"); break;
+    case Category2_2ndQuery: st->print("category2_2nd type"); break;
     default:
       if (is_uninitialized_this()) {
-        st->print(" uninitializedThis ");
+        st->print("uninitializedThis");
       } else if (is_uninitialized()) {
-        st->print(" uninitialized %d ", bci());
+        st->print("uninitialized %d", bci());
       } else {
-        st->print(" class %s ", name()->as_klass_external_name());
+        name()->print_value_on(st);
       }
   }
 }
-
-#endif
--- a/hotspot/src/share/vm/classfile/verificationType.hpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/classfile/verificationType.hpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -157,7 +157,7 @@
 
   // For reference types, store the actual Symbol
   static VerificationType reference_type(Symbol* sh) {
-      assert(((uintptr_t)sh & 0x3) == 0, "Oops must be aligned");
+      assert(((uintptr_t)sh & 0x3) == 0, "Symbols must be aligned");
       // If the above assert fails in the future because oop* isn't aligned,
       // then this type encoding system will have to change to have a tag value
       // to descriminate between oops and primitives.
@@ -303,7 +303,7 @@
     return index;
   }
 
-  void print_on(outputStream* st) const PRODUCT_RETURN;
+  void print_on(outputStream* st) const;
 
  private:
 
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Mon Aug 06 15:54:45 2012 -0400
@@ -26,9 +26,12 @@
 #include "classfile/classFileStream.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/stackMapTable.hpp"
+#include "classfile/stackMapFrame.hpp"
+#include "classfile/stackMapTableFormat.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/verifier.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "interpreter/bytecodes.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
@@ -110,8 +113,11 @@
   Symbol* exception_name = NULL;
   const size_t message_buffer_len = klass->name()->utf8_length() + 1024;
   char* message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
+  char* exception_message = message_buffer;
 
   const char* klassName = klass->external_name();
+  bool can_failover = FailOverToOldVerifier &&
+      klass->major_version() < NOFAILOVER_MAJOR_VERSION;
 
   // If the class should be verified, first see if we can use the split
   // verifier.  If not, or if verification fails and FailOverToOldVerifier
@@ -122,27 +128,28 @@
     }
     if (UseSplitVerifier &&
         klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) {
-        ClassVerifier split_verifier(
-          klass, message_buffer, message_buffer_len, THREAD);
-        split_verifier.verify_class(THREAD);
-        exception_name = split_verifier.result();
-      if (klass->major_version() < NOFAILOVER_MAJOR_VERSION &&
-          FailOverToOldVerifier && !HAS_PENDING_EXCEPTION &&
+      ClassVerifier split_verifier(klass, THREAD);
+      split_verifier.verify_class(THREAD);
+      exception_name = split_verifier.result();
+      if (can_failover && !HAS_PENDING_EXCEPTION &&
           (exception_name == vmSymbols::java_lang_VerifyError() ||
            exception_name == vmSymbols::java_lang_ClassFormatError())) {
-        if (TraceClassInitialization) {
+        if (TraceClassInitialization || VerboseVerification) {
           tty->print_cr(
             "Fail over class verification to old verifier for: %s", klassName);
         }
         exception_name = inference_verify(
           klass, message_buffer, message_buffer_len, THREAD);
       }
+      if (exception_name != NULL) {
+        exception_message = split_verifier.exception_message();
+      }
     } else {
       exception_name = inference_verify(
           klass, message_buffer, message_buffer_len, THREAD);
     }
 
-    if (TraceClassInitialization) {
+    if (TraceClassInitialization || VerboseVerification) {
       if (HAS_PENDING_EXCEPTION) {
         tty->print("Verification for %s has", klassName);
         tty->print_cr(" exception pending %s ",
@@ -173,7 +180,7 @@
       kls = kls->super();
     }
     message_buffer[message_buffer_len - 1] = '\0'; // just to be sure
-    THROW_MSG_(exception_name, message_buffer, false);
+    THROW_MSG_(exception_name, exception_message, false);
   }
 }
 
@@ -221,7 +228,7 @@
   }
 
   ResourceMark rm(THREAD);
-  if (ClassVerifier::_verify_verbose) {
+  if (VerboseVerification) {
     tty->print_cr("Verifying class %s with old format", klass->external_name());
   }
 
@@ -265,14 +272,252 @@
   }
 }
 
+TypeOrigin TypeOrigin::null() {
+  return TypeOrigin();
+}
+TypeOrigin TypeOrigin::local(u2 index, StackMapFrame* frame) {
+  assert(frame != NULL, "Must have a frame");
+  return TypeOrigin(CF_LOCALS, index, StackMapFrame::copy(frame),
+     frame->local_at(index));
+}
+TypeOrigin TypeOrigin::stack(u2 index, StackMapFrame* frame) {
+  assert(frame != NULL, "Must have a frame");
+  return TypeOrigin(CF_STACK, index, StackMapFrame::copy(frame),
+      frame->stack_at(index));
+}
+TypeOrigin TypeOrigin::sm_local(u2 index, StackMapFrame* frame) {
+  assert(frame != NULL, "Must have a frame");
+  return TypeOrigin(SM_LOCALS, index, StackMapFrame::copy(frame),
+      frame->local_at(index));
+}
+TypeOrigin TypeOrigin::sm_stack(u2 index, StackMapFrame* frame) {
+  assert(frame != NULL, "Must have a frame");
+  return TypeOrigin(SM_STACK, index, StackMapFrame::copy(frame),
+      frame->stack_at(index));
+}
+TypeOrigin TypeOrigin::bad_index(u2 index) {
+  return TypeOrigin(BAD_INDEX, index, NULL, VerificationType::bogus_type());
+}
+TypeOrigin TypeOrigin::cp(u2 index, VerificationType vt) {
+  return TypeOrigin(CONST_POOL, index, NULL, vt);
+}
+TypeOrigin TypeOrigin::signature(VerificationType vt) {
+  return TypeOrigin(SIG, 0, NULL, vt);
+}
+TypeOrigin TypeOrigin::implicit(VerificationType t) {
+  return TypeOrigin(IMPLICIT, 0, NULL, t);
+}
+TypeOrigin TypeOrigin::frame(StackMapFrame* frame) {
+  return TypeOrigin(FRAME_ONLY, 0, StackMapFrame::copy(frame),
+                    VerificationType::bogus_type());
+}
+
+void TypeOrigin::reset_frame() {
+  if (_frame != NULL) {
+    _frame->restore();
+  }
+}
+
+void TypeOrigin::details(outputStream* ss) const {
+  _type.print_on(ss);
+  switch (_origin) {
+    case CF_LOCALS:
+      ss->print(" (current frame, locals[%d])", _index);
+      break;
+    case CF_STACK:
+      ss->print(" (current frame, stack[%d])", _index);
+      break;
+    case SM_LOCALS:
+      ss->print(" (stack map, locals[%d])", _index);
+      break;
+    case SM_STACK:
+      ss->print(" (stack map, stack[%d])", _index);
+      break;
+    case CONST_POOL:
+      ss->print(" (constant pool %d)", _index);
+      break;
+    case SIG:
+      ss->print(" (from method signature)");
+      break;
+    case IMPLICIT:
+    case FRAME_ONLY:
+    case NONE:
+    default:
+      ;
+  }
+}
+
+#ifdef ASSERT
+void TypeOrigin::print_on(outputStream* str) const {
+  str->print("{%d,%d,%p:", _origin, _index, _frame);
+  if (_frame != NULL) {
+    _frame->print_on(str);
+  } else {
+    str->print("null");
+  }
+  str->print(",");
+  _type.print_on(str);
+  str->print("}");
+}
+#endif
+
+void ErrorContext::details(outputStream* ss, methodOop method) const {
+  if (is_valid()) {
+    ss->print_cr("");
+    ss->print_cr("Exception Details:");
+    location_details(ss, method);
+    reason_details(ss);
+    frame_details(ss);
+    bytecode_details(ss, method);
+    handler_details(ss, method);
+    stackmap_details(ss, method);
+  }
+}
+
+void ErrorContext::reason_details(outputStream* ss) const {
+  streamIndentor si(ss);
+  ss->indent().print_cr("Reason:");
+  streamIndentor si2(ss);
+  ss->indent().print("");
+  switch (_fault) {
+    case INVALID_BYTECODE:
+      ss->print("Error exists in the bytecode");
+      break;
+    case WRONG_TYPE:
+      if (_expected.is_valid()) {
+        ss->print("Type ");
+        _type.details(ss);
+        ss->print(" is not assignable to ");
+        _expected.details(ss);
+      } else {
+        ss->print("Invalid type: ");
+        _type.details(ss);
+      }
+      break;
+    case FLAGS_MISMATCH:
+      if (_expected.is_valid()) {
+        ss->print("Current frame's flags are not assignable "
+                  "to stack map frame's.");
+      } else {
+        ss->print("Current frame's flags are invalid in this context.");
+      }
+      break;
+    case BAD_CP_INDEX:
+      ss->print("Constant pool index %d is invalid", _type.index());
+      break;
+    case BAD_LOCAL_INDEX:
+      ss->print("Local index %d is invalid", _type.index());
+      break;
+    case LOCALS_SIZE_MISMATCH:
+      ss->print("Current frame's local size doesn't match stackmap.");
+      break;
+    case STACK_SIZE_MISMATCH:
+      ss->print("Current frame's stack size doesn't match stackmap.");
+      break;
+    case STACK_OVERFLOW:
+      ss->print("Exceeded max stack size.");
+      break;
+    case STACK_UNDERFLOW:
+      ss->print("Attempt to pop empty stack.");
+      break;
+    case MISSING_STACKMAP:
+      ss->print("Expected stackmap frame at this location.");
+      break;
+    case BAD_STACKMAP:
+      ss->print("Invalid stackmap specification.");
+      break;
+    case UNKNOWN:
+    default:
+      ShouldNotReachHere();
+      ss->print_cr("Unknown");
+  }
+  ss->print_cr("");
+}
+
+void ErrorContext::location_details(outputStream* ss, methodOop method) const {
+  if (_bci != -1 && method != NULL) {
+    streamIndentor si(ss);
+    const char* bytecode_name = "<invalid>";
+    if (method->validate_bci_from_bcx(_bci) != -1) {
+      Bytecodes::Code code = Bytecodes::code_or_bp_at(method->bcp_from(_bci));
+      if (Bytecodes::is_defined(code)) {
+          bytecode_name = Bytecodes::name(code);
+      } else {
+          bytecode_name = "<illegal>";
+      }
+    }
+    instanceKlass* ik = instanceKlass::cast(method->method_holder());
+    ss->indent().print_cr("Location:");
+    streamIndentor si2(ss);
+    ss->indent().print_cr("%s.%s%s @%d: %s",
+        ik->name()->as_C_string(), method->name()->as_C_string(),
+        method->signature()->as_C_string(), _bci, bytecode_name);
+  }
+}
+
+void ErrorContext::frame_details(outputStream* ss) const {
+  streamIndentor si(ss);
+  if (_type.is_valid() && _type.frame() != NULL) {
+    ss->indent().print_cr("Current Frame:");
+    streamIndentor si2(ss);
+    _type.frame()->print_on(ss);
+  }
+  if (_expected.is_valid() && _expected.frame() != NULL) {
+    ss->indent().print_cr("Stackmap Frame:");
+    streamIndentor si2(ss);
+    _expected.frame()->print_on(ss);
+  }
+}
+
+void ErrorContext::bytecode_details(outputStream* ss, methodOop method) const {
+  if (method != NULL) {
+    streamIndentor si(ss);
+    ss->indent().print_cr("Bytecode:");
+    streamIndentor si2(ss);
+    ss->print_data(method->code_base(), method->code_size(), false);
+  }
+}
+
+void ErrorContext::handler_details(outputStream* ss, methodOop method) const {
+  if (method != NULL) {
+    streamIndentor si(ss);
+    ExceptionTable table(method);
+    if (table.length() > 0) {
+      ss->indent().print_cr("Exception Handler Table:");
+      streamIndentor si2(ss);
+      for (int i = 0; i < table.length(); ++i) {
+        ss->indent().print_cr("bci [%d, %d] => handler: %d", table.start_pc(i),
+            table.end_pc(i), table.handler_pc(i));
+      }
+    }
+  }
+}
+
+void ErrorContext::stackmap_details(outputStream* ss, methodOop method) const {
+  if (method != NULL && method->has_stackmap_table()) {
+    streamIndentor si(ss);
+    ss->indent().print_cr("Stackmap Table:");
+    typeArrayOop data = method->stackmap_data();
+    stack_map_table* sm_table =
+        stack_map_table::at((address)data->byte_at_addr(0));
+    stack_map_frame* sm_frame = sm_table->entries();
+    streamIndentor si2(ss);
+    int current_offset = -1;
+    for (u2 i = 0; i < sm_table->number_of_entries(); ++i) {
+      ss->indent();
+      sm_frame->print_on(ss, current_offset);
+      ss->print_cr("");
+      current_offset += sm_frame->offset_delta();
+      sm_frame = sm_frame->next();
+    }
+  }
+}
+
 // Methods in ClassVerifier
 
-bool ClassVerifier::_verify_verbose = false;
-
 ClassVerifier::ClassVerifier(
-    instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS)
-    : _thread(THREAD), _exception_type(NULL), _message(msg),
-      _message_buffer_len(msg_len), _klass(klass) {
+    instanceKlassHandle klass, TRAPS)
+    : _thread(THREAD), _exception_type(NULL), _message(NULL), _klass(klass) {
   _this_type = VerificationType::reference_type(klass->name());
   // Create list to hold symbols in reference area.
   _symbols = new GrowableArray<Symbol*>(100, 0, NULL);
@@ -290,8 +535,14 @@
   return VerificationType::reference_type(vmSymbols::java_lang_Object());
 }
 
+TypeOrigin ClassVerifier::ref_ctx(const char* sig, TRAPS) {
+  VerificationType vt = VerificationType::reference_type(
+      create_temporary_symbol(sig, (int)strlen(sig), THREAD));
+  return TypeOrigin::implicit(vt);
+}
+
 void ClassVerifier::verify_class(TRAPS) {
-  if (_verify_verbose) {
+  if (VerboseVerification) {
     tty->print_cr("Verifying class %s with new format",
       _klass->external_name());
   }
@@ -312,7 +563,7 @@
     verify_method(methodHandle(THREAD, m), CHECK_VERIFY(this));
   }
 
-  if (_verify_verbose || TraceClassInitialization) {
+  if (VerboseVerification || TraceClassInitialization) {
     if (was_recursively_verified())
       tty->print_cr("Recursive verification detected for: %s",
           _klass->external_name());
@@ -321,7 +572,7 @@
 
 void ClassVerifier::verify_method(methodHandle m, TRAPS) {
   _method = m;   // initialize _method
-  if (_verify_verbose) {
+  if (VerboseVerification) {
     tty->print_cr("Verifying method %s", m->name_and_sig_as_C_string());
   }
 
@@ -368,8 +619,8 @@
   StackMapTable stackmap_table(&reader, &current_frame, max_locals, max_stack,
                                code_data, code_length, CHECK_VERIFY(this));
 
-  if (_verify_verbose) {
-    stackmap_table.print();
+  if (VerboseVerification) {
+    stackmap_table.print_on(tty);
   }
 
   RawBytecodeStream bcs(m);
@@ -388,6 +639,7 @@
 
     // Set current frame's offset to bci
     current_frame.set_offset(bci);
+    current_frame.set_mark();
 
     // Make sure every offset in stackmap table point to the beginning to
     // an instruction. Match current_frame to stackmap_table entry with
@@ -396,6 +648,7 @@
       stackmap_index, bci, &current_frame, &stackmap_table,
       no_control_flow, CHECK_VERIFY(this));
 
+
     bool this_uninit = false;  // Set to true when invokespecial <init> initialized 'this'
 
     // Merge with the next instruction
@@ -406,8 +659,8 @@
       VerificationType atype;
 
 #ifndef PRODUCT
-      if (_verify_verbose) {
-        current_frame.print();
+      if (VerboseVerification) {
+        current_frame.print_on(tty);
         tty->print_cr("offset = %d,  opcode = %s", bci, Bytecodes::name(opcode));
       }
 #endif
@@ -420,7 +673,10 @@
             opcode != Bytecodes::_lstore && opcode != Bytecodes::_fload  &&
             opcode != Bytecodes::_dload  && opcode != Bytecodes::_fstore &&
             opcode != Bytecodes::_dstore) {
-          verify_error(bci, "Bad wide instruction");
+          /* Unreachable?  RawBytecodeStream's raw_next() returns 'illegal'
+           * if we encounter a wide instruction that modifies an invalid
+           * opcode (not one of the ones listed above) */
+          verify_error(ErrorContext::bad_code(bci), "Bad wide instruction");
           return;
         }
       }
@@ -532,7 +788,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_int_array()) {
-            verify_error(bci, bad_type_msg, "iaload");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[I", THREAD)),
+                bad_type_msg, "iaload");
             return;
           }
           current_frame.push_stack(
@@ -544,7 +802,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_bool_array() && !atype.is_byte_array()) {
-            verify_error(bci, bad_type_msg, "baload");
+            verify_error(
+                ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
+                bad_type_msg, "baload");
             return;
           }
           current_frame.push_stack(
@@ -556,7 +816,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_char_array()) {
-            verify_error(bci, bad_type_msg, "caload");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[C", THREAD)),
+                bad_type_msg, "caload");
             return;
           }
           current_frame.push_stack(
@@ -568,7 +830,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_short_array()) {
-            verify_error(bci, bad_type_msg, "saload");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[S", THREAD)),
+                bad_type_msg, "saload");
             return;
           }
           current_frame.push_stack(
@@ -580,7 +844,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_long_array()) {
-            verify_error(bci, bad_type_msg, "laload");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[J", THREAD)),
+                bad_type_msg, "laload");
             return;
           }
           current_frame.push_stack_2(
@@ -593,7 +859,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_float_array()) {
-            verify_error(bci, bad_type_msg, "faload");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[F", THREAD)),
+                bad_type_msg, "faload");
             return;
           }
           current_frame.push_stack(
@@ -605,7 +873,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_double_array()) {
-            verify_error(bci, bad_type_msg, "daload");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[D", THREAD)),
+                bad_type_msg, "daload");
             return;
           }
           current_frame.push_stack_2(
@@ -618,7 +888,10 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_reference_array()) {
-            verify_error(bci, bad_type_msg, "aaload");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(),
+                TypeOrigin::implicit(VerificationType::reference_check())),
+                bad_type_msg, "aaload");
             return;
           }
           if (atype.is_null()) {
@@ -689,7 +962,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_int_array()) {
-            verify_error(bci, bad_type_msg, "iastore");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[I", THREAD)),
+                bad_type_msg, "iastore");
             return;
           }
           no_control_flow = false; break;
@@ -701,7 +976,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_bool_array() && !atype.is_byte_array()) {
-            verify_error(bci, bad_type_msg, "bastore");
+            verify_error(
+                ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
+                bad_type_msg, "bastore");
             return;
           }
           no_control_flow = false; break;
@@ -713,7 +990,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_char_array()) {
-            verify_error(bci, bad_type_msg, "castore");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[C", THREAD)),
+                bad_type_msg, "castore");
             return;
           }
           no_control_flow = false; break;
@@ -725,7 +1004,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_short_array()) {
-            verify_error(bci, bad_type_msg, "sastore");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[S", THREAD)),
+                bad_type_msg, "sastore");
             return;
           }
           no_control_flow = false; break;
@@ -738,7 +1019,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_long_array()) {
-            verify_error(bci, bad_type_msg, "lastore");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[J", THREAD)),
+                bad_type_msg, "lastore");
             return;
           }
           no_control_flow = false; break;
@@ -750,7 +1033,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_float_array()) {
-            verify_error(bci, bad_type_msg, "fastore");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[F", THREAD)),
+                bad_type_msg, "fastore");
             return;
           }
           no_control_flow = false; break;
@@ -763,7 +1048,9 @@
           atype = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!atype.is_double_array()) {
-            verify_error(bci, bad_type_msg, "dastore");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(), ref_ctx("[D", THREAD)),
+                bad_type_msg, "dastore");
             return;
           }
           no_control_flow = false; break;
@@ -775,7 +1062,10 @@
             VerificationType::reference_check(), CHECK_VERIFY(this));
           // more type-checking is done at runtime
           if (!atype.is_reference_array()) {
-            verify_error(bci, bad_type_msg, "aastore");
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(),
+                TypeOrigin::implicit(VerificationType::reference_check())),
+                bad_type_msg, "aastore");
             return;
           }
           // 4938384: relaxed constraint in JVMS 3nd edition.
@@ -793,7 +1083,11 @@
             current_frame.pop_stack(
               VerificationType::category2_check(), CHECK_VERIFY(this));
           } else {
-            verify_error(bci, bad_type_msg, "pop2");
+            /* Unreachable? Would need a category2_1st on TOS
+             * which does not appear possible. */
+            verify_error(
+                ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
+                bad_type_msg, "pop2");
             return;
           }
           no_control_flow = false; break;
@@ -825,7 +1119,10 @@
             type3 = current_frame.pop_stack(
               VerificationType::category2_check(), CHECK_VERIFY(this));
           } else {
-            verify_error(bci, bad_type_msg, "dup_x2");
+            /* Unreachable? Would need a category2_1st at stack depth 2 with
+             * a category1 on TOS which does not appear possible. */
+            verify_error(ErrorContext::bad_type(
+                bci, current_frame.stack_top_ctx()), bad_type_msg, "dup_x2");
             return;
           }
           current_frame.push_stack(type, CHECK_VERIFY(this));
@@ -843,7 +1140,11 @@
             type2 = current_frame.pop_stack(
               VerificationType::category2_check(), CHECK_VERIFY(this));
           } else {
-            verify_error(bci, bad_type_msg, "dup2");
+            /* Unreachable?  Would need a category2_1st on TOS which does not
+             * appear possible. */
+            verify_error(
+                ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
+                bad_type_msg, "dup2");
             return;
           }
           current_frame.push_stack(type2, CHECK_VERIFY(this));
@@ -858,11 +1159,15 @@
           if (type.is_category1()) {
             type2 = current_frame.pop_stack(
               VerificationType::category1_check(), CHECK_VERIFY(this));
-          } else if(type.is_category2_2nd()) {
-            type2 = current_frame.pop_stack
-              (VerificationType::category2_check(), CHECK_VERIFY(this));
+          } else if (type.is_category2_2nd()) {
+            type2 = current_frame.pop_stack(
+              VerificationType::category2_check(), CHECK_VERIFY(this));
           } else {
-            verify_error(bci, bad_type_msg, "dup2_x1");
+            /* Unreachable?  Would need a category2_1st on TOS which does
+             * not appear possible. */
+            verify_error(
+                ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
+                bad_type_msg, "dup2_x1");
             return;
           }
           type3 = current_frame.pop_stack(
@@ -885,7 +1190,11 @@
             type2 = current_frame.pop_stack(
               VerificationType::category2_check(), CHECK_VERIFY(this));
           } else {
-            verify_error(bci, bad_type_msg, "dup2_x2");
+            /* Unreachable?  Would need a category2_1st on TOS which does
+             * not appear possible. */
+            verify_error(
+                ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
+                bad_type_msg, "dup2_x2");
             return;
           }
           type3 = current_frame.pop_stack(CHECK_VERIFY(this));
@@ -896,7 +1205,12 @@
             type4 = current_frame.pop_stack(
               VerificationType::category2_check(), CHECK_VERIFY(this));
           } else {
-            verify_error(bci, bad_type_msg, "dup2_x2");
+            /* Unreachable?  Would need a category2_1st on TOS after popping
+             * a long/double or two category 1's, which does not
+             * appear possible. */
+            verify_error(
+                ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
+                bad_type_msg, "dup2_x2");
             return;
           }
           current_frame.push_stack(type2, CHECK_VERIFY(this));
@@ -1176,43 +1490,50 @@
         case Bytecodes::_ireturn :
           type = current_frame.pop_stack(
             VerificationType::integer_type(), CHECK_VERIFY(this));
-          verify_return_value(return_type, type, bci, CHECK_VERIFY(this));
+          verify_return_value(return_type, type, bci,
+                              &current_frame, CHECK_VERIFY(this));
           no_control_flow = true; break;
         case Bytecodes::_lreturn :
           type2 = current_frame.pop_stack(
             VerificationType::long2_type(), CHECK_VERIFY(this));
           type = current_frame.pop_stack(
             VerificationType::long_type(), CHECK_VERIFY(this));
-          verify_return_value(return_type, type, bci, CHECK_VERIFY(this));
+          verify_return_value(return_type, type, bci,
+                              &current_frame, CHECK_VERIFY(this));
           no_control_flow = true; break;
         case Bytecodes::_freturn :
           type = current_frame.pop_stack(
             VerificationType::float_type(), CHECK_VERIFY(this));
-          verify_return_value(return_type, type, bci, CHECK_VERIFY(this));
+          verify_return_value(return_type, type, bci,
+                              &current_frame, CHECK_VERIFY(this));
           no_control_flow = true; break;
         case Bytecodes::_dreturn :
           type2 = current_frame.pop_stack(
             VerificationType::double2_type(),  CHECK_VERIFY(this));
           type = current_frame.pop_stack(
             VerificationType::double_type(), CHECK_VERIFY(this));
-          verify_return_value(return_type, type, bci, CHECK_VERIFY(this));
+          verify_return_value(return_type, type, bci,
+                              &current_frame, CHECK_VERIFY(this));
           no_control_flow = true; break;
         case Bytecodes::_areturn :
           type = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
-          verify_return_value(return_type, type, bci, CHECK_VERIFY(this));
+          verify_return_value(return_type, type, bci,
+                              &current_frame, CHECK_VERIFY(this));
           no_control_flow = true; break;
         case Bytecodes::_return :
           if (return_type != VerificationType::bogus_type()) {
-            verify_error(bci, "Method expects no return value");
+            verify_error(ErrorContext::bad_code(bci),
+                         "Method expects a return value");
             return;
           }
           // Make sure "this" has been initialized if current method is an
           // <init>
           if (_method->name() == vmSymbols::object_initializer_name() &&
               current_frame.flag_this_uninit()) {
-            verify_error(bci,
-              "Constructor must call super() or this() before return");
+            verify_error(ErrorContext::bad_code(bci),
+                         "Constructor must call super() or this() "
+                         "before return");
             return;
           }
           no_control_flow = true; break;
@@ -1239,11 +1560,13 @@
         case Bytecodes::_new :
         {
           index = bcs.get_index_u2();
-          verify_cp_class_type(index, cp, CHECK_VERIFY(this));
+          verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
           VerificationType new_class_type =
             cp_index_to_type(index, cp, CHECK_VERIFY(this));
           if (!new_class_type.is_object()) {
-            verify_error(bci, "Illegal new instruction");
+            verify_error(ErrorContext::bad_type(bci,
+                TypeOrigin::cp(index, new_class_type)),
+                "Illegal new instruction");
             return;
           }
           type = VerificationType::uninitialized_type(bci);
@@ -1258,13 +1581,15 @@
           no_control_flow = false; break;
         case Bytecodes::_anewarray :
           verify_anewarray(
-            bcs.get_index_u2(), cp, &current_frame, CHECK_VERIFY(this));
+            bci, bcs.get_index_u2(), cp, &current_frame, CHECK_VERIFY(this));
           no_control_flow = false; break;
         case Bytecodes::_arraylength :
           type = current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
           if (!(type.is_null() || type.is_array())) {
-            verify_error(bci, bad_type_msg, "arraylength");
+            verify_error(ErrorContext::bad_type(
+                bci, current_frame.stack_top_ctx()),
+                bad_type_msg, "arraylength");
           }
           current_frame.push_stack(
             VerificationType::integer_type(), CHECK_VERIFY(this));
@@ -1272,7 +1597,7 @@
         case Bytecodes::_checkcast :
         {
           index = bcs.get_index_u2();
-          verify_cp_class_type(index, cp, CHECK_VERIFY(this));
+          verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
           current_frame.pop_stack(object_type(), CHECK_VERIFY(this));
           VerificationType klass_type = cp_index_to_type(
             index, cp, CHECK_VERIFY(this));
@@ -1281,7 +1606,7 @@
         }
         case Bytecodes::_instanceof : {
           index = bcs.get_index_u2();
-          verify_cp_class_type(index, cp, CHECK_VERIFY(this));
+          verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
           current_frame.pop_stack(object_type(), CHECK_VERIFY(this));
           current_frame.push_stack(
             VerificationType::integer_type(), CHECK_VERIFY(this));
@@ -1296,17 +1621,18 @@
         {
           index = bcs.get_index_u2();
           u2 dim = *(bcs.bcp()+3);
-          verify_cp_class_type(index, cp, CHECK_VERIFY(this));
+          verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
           VerificationType new_array_type =
             cp_index_to_type(index, cp, CHECK_VERIFY(this));
           if (!new_array_type.is_array()) {
-            verify_error(bci,
-              "Illegal constant pool index in multianewarray instruction");
+            verify_error(ErrorContext::bad_type(bci,
+                TypeOrigin::cp(index, new_array_type)),
+                "Illegal constant pool index in multianewarray instruction");
             return;
           }
           if (dim < 1 || new_array_type.dimensions() < dim) {
-            verify_error(bci,
-              "Illegal dimension in multianewarray instruction");
+            verify_error(ErrorContext::bad_code(bci),
+                "Illegal dimension in multianewarray instruction: %d", dim);
             return;
           }
           for (int i = 0; i < dim; i++) {
@@ -1324,7 +1650,8 @@
         default:
           // We only need to check the valid bytecodes in class file.
           // And jsr and ret are not in the new class file format in JDK1.5.
-          verify_error(bci, "Bad instruction");
+          verify_error(ErrorContext::bad_code(bci),
+              "Bad instruction: %02x", opcode);
           no_control_flow = false;
           return;
       }  // end switch
@@ -1340,7 +1667,8 @@
 
   // Make sure that control flow does not fall through end of the method
   if (!no_control_flow) {
-    verify_error(code_length, "Control flow falls through code end");
+    verify_error(ErrorContext::bad_code(code_length),
+        "Control flow falls through code end");
     return;
   }
 }
@@ -1359,7 +1687,7 @@
         code_data[bci] = BYTECODE_OFFSET;
       }
     } else {
-      verify_error(bcs.bci(), "Bad instruction");
+      verify_error(ErrorContext::bad_code(bcs.bci()), "Bad instruction");
       return NULL;
     }
   }
@@ -1402,9 +1730,11 @@
         catch_type, this, CHECK_VERIFY(this));
       if (!is_subclass) {
         // 4286534: should throw VerifyError according to recent spec change
-        verify_error(
-          "Catch type is not a subclass of Throwable in handler %d",
-          handler_pc);
+        verify_error(ErrorContext::bad_type(handler_pc,
+            TypeOrigin::cp(catch_type_index, catch_type),
+            TypeOrigin::implicit(throwable)),
+            "Catch type is not a subclass "
+            "of Throwable in exception handler %d", handler_pc);
         return;
       }
     }
@@ -1444,19 +1774,21 @@
   if (stackmap_index < stackmap_table->get_frame_count()) {
     u2 this_offset = stackmap_table->get_offset(stackmap_index);
     if (no_control_flow && this_offset > bci) {
-      verify_error(bci, "Expecting a stack map frame");
+      verify_error(ErrorContext::missing_stackmap(bci),
+                   "Expecting a stack map frame");
       return 0;
     }
     if (this_offset == bci) {
+      ErrorContext ctx;
       // See if current stack map can be assigned to the frame in table.
       // current_frame is the stackmap frame got from the last instruction.
       // If matched, current_frame will be updated by this method.
-      bool match = stackmap_table->match_stackmap(
+      bool matches = stackmap_table->match_stackmap(
         current_frame, this_offset, stackmap_index,
-        !no_control_flow, true, CHECK_VERIFY_(this, 0));
-      if (!match) {
+        !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0));
+      if (!matches) {
         // report type error
-        verify_error(bci, "Instruction type does not match stack map");
+        verify_error(ctx, "Instruction type does not match stack map");
         return 0;
       }
       stackmap_index++;
@@ -1466,7 +1798,7 @@
       return 0;
     }
   } else if (no_control_flow) {
-    verify_error(bci, "Expecting a stack map frame");
+    verify_error(ErrorContext::bad_code(bci), "Expecting a stack map frame");
     return 0;
   }
   return stackmap_index;
@@ -1498,29 +1830,31 @@
           VerificationType::reference_type(vmSymbols::java_lang_Throwable());
         new_frame->push_stack(throwable, CHECK_VERIFY(this));
       }
-      bool match = stackmap_table->match_stackmap(
-        new_frame, handler_pc, true, false, CHECK_VERIFY(this));
-      if (!match) {
-        verify_error(bci,
-          "Stack map does not match the one at exception handler %d",
-          handler_pc);
+      ErrorContext ctx;
+      bool matches = stackmap_table->match_stackmap(
+        new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this));
+      if (!matches) {
+        verify_error(ctx, "Stack map does not match the one at "
+            "exception handler %d", handler_pc);
         return;
       }
     }
   }
 }
 
-void ClassVerifier::verify_cp_index(constantPoolHandle cp, int index, TRAPS) {
+void ClassVerifier::verify_cp_index(
+    u2 bci, constantPoolHandle cp, int index, TRAPS) {
   int nconstants = cp->length();
   if ((index <= 0) || (index >= nconstants)) {
-    verify_error("Illegal constant pool index %d in class %s",
-      index, instanceKlass::cast(cp->pool_holder())->external_name());
+    verify_error(ErrorContext::bad_cp_index(bci, index),
+        "Illegal constant pool index %d in class %s",
+        index, instanceKlass::cast(cp->pool_holder())->external_name());
     return;
   }
 }
 
 void ClassVerifier::verify_cp_type(
-    int index, constantPoolHandle cp, unsigned int types, TRAPS) {
+    u2 bci, int index, constantPoolHandle cp, unsigned int types, TRAPS) {
 
   // In some situations, bytecode rewriting may occur while we're verifying.
   // In this case, a constant pool cache exists and some indices refer to that
@@ -1528,10 +1862,10 @@
   // We must check was_recursively_verified() before we get here.
   guarantee(cp->cache() == NULL, "not rewritten yet");
 
-  verify_cp_index(cp, index, CHECK_VERIFY(this));
+  verify_cp_index(bci, cp, index, CHECK_VERIFY(this));
   unsigned int tag = cp->tag_at(index).value();
   if ((types & (1 << tag)) == 0) {
-    verify_error(
+    verify_error(ErrorContext::bad_cp_index(bci, index),
       "Illegal type at constant pool entry %d in class %s",
       index, instanceKlass::cast(cp->pool_holder())->external_name());
     return;
@@ -1539,51 +1873,46 @@
 }
 
 void ClassVerifier::verify_cp_class_type(
-    int index, constantPoolHandle cp, TRAPS) {
-  verify_cp_index(cp, index, CHECK_VERIFY(this));
+    u2 bci, int index, constantPoolHandle cp, TRAPS) {
+  verify_cp_index(bci, cp, index, CHECK_VERIFY(this));
   constantTag tag = cp->tag_at(index);
   if (!tag.is_klass() && !tag.is_unresolved_klass()) {
-    verify_error("Illegal type at constant pool entry %d in class %s",
-      index, instanceKlass::cast(cp->pool_holder())->external_name());
+    verify_error(ErrorContext::bad_cp_index(bci, index),
+        "Illegal type at constant pool entry %d in class %s",
+        index, instanceKlass::cast(cp->pool_holder())->external_name());
     return;
   }
 }
 
-void ClassVerifier::format_error_message(
-    const char* fmt, int offset, va_list va) {
-  ResourceMark rm(_thread);
-  stringStream message(_message, _message_buffer_len);
-  message.vprint(fmt, va);
-  if (!_method.is_null()) {
-    message.print(" in method %s", _method->name_and_sig_as_C_string());
-  }
-  if (offset != -1) {
-    message.print(" at offset %d", offset);
-  }
-}
+void ClassVerifier::verify_error(ErrorContext ctx, const char* msg, ...) {
+  stringStream ss;
 
-void ClassVerifier::verify_error(u2 offset, const char* fmt, ...) {
+  ctx.reset_frames();
   _exception_type = vmSymbols::java_lang_VerifyError();
+  _error_context = ctx;
   va_list va;
-  va_start(va, fmt);
-  format_error_message(fmt, offset, va);
+  va_start(va, msg);
+  ss.vprint(msg, va);
   va_end(va);
-}
-
-void ClassVerifier::verify_error(const char* fmt, ...) {
-  _exception_type = vmSymbols::java_lang_VerifyError();
-  va_list va;
-  va_start(va, fmt);
-  format_error_message(fmt, -1, va);
-  va_end(va);
+  _message = ss.as_string();
+#ifdef ASSERT
+  ResourceMark rm;
+  const char* exception_name = _exception_type->as_C_string();
+  Exceptions::debug_check_abort(exception_name, NULL);
+#endif // ndef ASSERT
 }
 
 void ClassVerifier::class_format_error(const char* msg, ...) {
+  stringStream ss;
   _exception_type = vmSymbols::java_lang_ClassFormatError();
   va_list va;
   va_start(va, msg);
-  format_error_message(msg, -1, va);
+  ss.vprint(msg, va);
   va_end(va);
+  if (!_method.is_null()) {
+    ss.print(" in method %s", _method->name_and_sig_as_C_string());
+  }
+  _message = ss.as_string();
 }
 
 klassOop ClassVerifier::load_class(Symbol* name, TRAPS) {
@@ -1619,7 +1948,7 @@
     }
   } else {
     klassOop member_klass = target_instance->find_field(field_name, field_sig, &fd);
-    if(member_klass != NULL && fd.is_protected()) {
+    if (member_klass != NULL && fd.is_protected()) {
       if (!this_class->is_same_class_package(member_klass)) {
         return true;
       }
@@ -1629,9 +1958,9 @@
 }
 
 void ClassVerifier::verify_ldc(
-    int opcode, u2 index, StackMapFrame *current_frame,
-     constantPoolHandle cp, u2 bci, TRAPS) {
-  verify_cp_index(cp, index, CHECK_VERIFY(this));
+    int opcode, u2 index, StackMapFrame* current_frame,
+    constantPoolHandle cp, u2 bci, TRAPS) {
+  verify_cp_index(bci, cp, index, CHECK_VERIFY(this));
   constantTag tag = cp->tag_at(index);
   unsigned int types;
   if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) {
@@ -1641,12 +1970,12 @@
             | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType);
       // Note:  The class file parser already verified the legality of
       // MethodHandle and MethodType constants.
-      verify_cp_type(index, cp, types, CHECK_VERIFY(this));
+      verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this));
     }
   } else {
     assert(opcode == Bytecodes::_ldc2_w, "must be ldc2_w");
     types = (1 << JVM_CONSTANT_Double) | (1 << JVM_CONSTANT_Long);
-    verify_cp_type(index, cp, types, CHECK_VERIFY(this));
+    verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this));
   }
   if (tag.is_string() && cp->is_pseudo_string_at(index)) {
     current_frame->push_stack(object_type(), CHECK_VERIFY(this));
@@ -1681,7 +2010,9 @@
       VerificationType::reference_type(
         vmSymbols::java_lang_invoke_MethodType()), CHECK_VERIFY(this));
   } else {
-    verify_error(bci, "Invalid index in ldc");
+    /* Unreachable? verify_cp_type has already validated the cp type. */
+    verify_error(
+        ErrorContext::bad_cp_index(bci, index), "Invalid index in ldc");
     return;
   }
 }
@@ -1697,7 +2028,8 @@
   u2 padding_offset = 1;
   while ((bcp + padding_offset) < aligned_bcp) {
     if(*(bcp + padding_offset) != 0) {
-      verify_error(bci, "Nonzero padding byte in lookswitch or tableswitch");
+      verify_error(ErrorContext::bad_code(bci),
+                   "Nonzero padding byte in lookswitch or tableswitch");
       return;
     }
     padding_offset++;
@@ -1710,20 +2042,21 @@
     jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize);
     jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize);
     if (low > high) {
-      verify_error(bci,
-        "low must be less than or equal to high in tableswitch");
+      verify_error(ErrorContext::bad_code(bci),
+          "low must be less than or equal to high in tableswitch");
       return;
     }
     keys = high - low + 1;
     if (keys < 0) {
-      verify_error(bci, "too many keys in tableswitch");
+      verify_error(ErrorContext::bad_code(bci), "too many keys in tableswitch");
       return;
     }
     delta = 1;
   } else {
     keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize);
     if (keys < 0) {
-      verify_error(bci, "number of keys in lookupswitch less than 0");
+      verify_error(ErrorContext::bad_code(bci),
+                   "number of keys in lookupswitch less than 0");
       return;
     }
     delta = 2;
@@ -1732,7 +2065,8 @@
       jint this_key = Bytes::get_Java_u4(aligned_bcp + (2+2*i)*jintSize);
       jint next_key = Bytes::get_Java_u4(aligned_bcp + (2+2*i+2)*jintSize);
       if (this_key >= next_key) {
-        verify_error(bci, "Bad lookupswitch instruction");
+        verify_error(ErrorContext::bad_code(bci),
+                     "Bad lookupswitch instruction");
         return;
       }
     }
@@ -1767,7 +2101,8 @@
                                               constantPoolHandle cp,
                                               TRAPS) {
   u2 index = bcs->get_index_u2();
-  verify_cp_type(index, cp, 1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this));
+  verify_cp_type(bcs->bci(), index, cp,
+      1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this));
 
   // Get field name and signature
   Symbol* field_name = cp->name_ref_at(index);
@@ -1784,9 +2119,11 @@
   VerificationType ref_class_type = cp_ref_index_to_type(
     index, cp, CHECK_VERIFY(this));
   if (!ref_class_type.is_object()) {
-    verify_error(
-      "Expecting reference to class in class %s at constant pool index %d",
-      _klass->external_name(), index);
+    /* Unreachable?  Class file parser verifies Fieldref contents */
+    verify_error(ErrorContext::bad_type(bcs->bci(),
+        TypeOrigin::cp(index, ref_class_type)),
+        "Expecting reference to class in class %s at constant pool index %d",
+        _klass->external_name(), index);
     return;
   }
   VerificationType target_class_type = ref_class_type;
@@ -1844,7 +2181,10 @@
       is_assignable = target_class_type.is_assignable_from(
         stack_object_type, this, CHECK_VERIFY(this));
       if (!is_assignable) {
-        verify_error(bci, "Bad type on operand stack in putfield");
+        verify_error(ErrorContext::bad_type(bci,
+            current_frame->stack_top_ctx(),
+            TypeOrigin::cp(index, target_class_type)),
+            "Bad type on operand stack in putfield");
         return;
       }
     }
@@ -1868,7 +2208,10 @@
         is_assignable = current_type().is_assignable_from(
           stack_object_type, this, CHECK_VERIFY(this));
         if (!is_assignable) {
-          verify_error(bci, "Bad access to protected data in getfield");
+          verify_error(ErrorContext::bad_type(bci,
+              current_frame->stack_top_ctx(),
+              TypeOrigin::implicit(current_type())),
+              "Bad access to protected data in getfield");
           return;
         }
       }
@@ -1879,7 +2222,7 @@
 }
 
 void ClassVerifier::verify_invoke_init(
-    RawBytecodeStream* bcs, VerificationType ref_class_type,
+    RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type,
     StackMapFrame* current_frame, u4 code_length, bool *this_uninit,
     constantPoolHandle cp, TRAPS) {
   u2 bci = bcs->bci();
@@ -1890,7 +2233,10 @@
     klassOop superk = current_class()->super();
     if (ref_class_type.name() != current_class()->name() &&
         ref_class_type.name() != superk->klass_part()->name()) {
-      verify_error(bci, "Bad <init> method call");
+      verify_error(ErrorContext::bad_type(bci,
+          TypeOrigin::implicit(ref_class_type),
+          TypeOrigin::implicit(current_type())),
+          "Bad <init> method call");
       return;
     }
     current_frame->initialize_object(type, current_type());
@@ -1899,17 +2245,23 @@
     u2 new_offset = type.bci();
     address new_bcp = bcs->bcp() - bci + new_offset;
     if (new_offset > (code_length - 3) || (*new_bcp) != Bytecodes::_new) {
-      verify_error(new_offset, "Expecting new instruction");
+      /* Unreachable?  Stack map parsing ensures valid type and new
+       * instructions have a valid BCI. */
+      verify_error(ErrorContext::bad_code(new_offset),
+                   "Expecting new instruction");
       return;
     }
     u2 new_class_index = Bytes::get_Java_u2(new_bcp + 1);
-    verify_cp_class_type(new_class_index, cp, CHECK_VERIFY(this));
+    verify_cp_class_type(bci, new_class_index, cp, CHECK_VERIFY(this));
 
     // The method must be an <init> method of the indicated class
     VerificationType new_class_type = cp_index_to_type(
       new_class_index, cp, CHECK_VERIFY(this));
     if (!new_class_type.equals(ref_class_type)) {
-      verify_error(bci, "Call to wrong <init> method");
+      verify_error(ErrorContext::bad_type(bci,
+          TypeOrigin::cp(new_class_index, new_class_type),
+          TypeOrigin::cp(ref_class_index, ref_class_type)),
+          "Call to wrong <init> method");
       return;
     }
     // According to the VM spec, if the referent class is a superclass of the
@@ -1928,14 +2280,18 @@
         bool assignable = current_type().is_assignable_from(
           objectref_type, this, CHECK_VERIFY(this));
         if (!assignable) {
-          verify_error(bci, "Bad access to protected <init> method");
+          verify_error(ErrorContext::bad_type(bci,
+              TypeOrigin::cp(new_class_index, objectref_type),
+              TypeOrigin::implicit(current_type())),
+              "Bad access to protected <init> method");
           return;
         }
       }
     }
     current_frame->initialize_object(type, new_class_type);
   } else {
-    verify_error(bci, "Bad operand type when invoking <init>");
+    verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()),
+        "Bad operand type when invoking <init>");
     return;
   }
 }
@@ -1952,7 +2308,7 @@
                       : opcode == Bytecodes::_invokedynamic
                                 ? 1 << JVM_CONSTANT_InvokeDynamic
                                 : 1 << JVM_CONSTANT_Methodref);
-  verify_cp_type(index, cp, types, CHECK_VERIFY(this));
+  verify_cp_type(bcs->bci(), index, cp, types, CHECK_VERIFY(this));
 
   // Get method name and signature
   Symbol* method_name = cp->name_ref_at(index);
@@ -2029,11 +2385,13 @@
     // the difference between the size of the operand stack before and after the instruction
     // executes.
     if (*(bcp+3) != (nargs+1)) {
-      verify_error(bci, "Inconsistent args count operand in invokeinterface");
+      verify_error(ErrorContext::bad_code(bci),
+          "Inconsistent args count operand in invokeinterface");
       return;
     }
     if (*(bcp+4) != 0) {
-      verify_error(bci, "Fourth operand byte of invokeinterface must be zero");
+      verify_error(ErrorContext::bad_code(bci),
+          "Fourth operand byte of invokeinterface must be zero");
       return;
     }
   }
@@ -2041,7 +2399,8 @@
   if (opcode == Bytecodes::_invokedynamic) {
     address bcp = bcs->bcp();
     if (*(bcp+3) != 0 || *(bcp+4) != 0) {
-      verify_error(bci, "Third and fourth operand bytes of invokedynamic must be zero");
+      verify_error(ErrorContext::bad_code(bci),
+          "Third and fourth operand bytes of invokedynamic must be zero");
       return;
     }
   }
@@ -2050,7 +2409,8 @@
     // Make sure <init> can only be invoked by invokespecial
     if (opcode != Bytecodes::_invokespecial ||
         method_name != vmSymbols::object_initializer_name()) {
-      verify_error(bci, "Illegal call to internal method");
+      verify_error(ErrorContext::bad_code(bci),
+          "Illegal call to internal method");
       return;
     }
   } else if (opcode == Bytecodes::_invokespecial
@@ -2060,7 +2420,8 @@
     bool subtype = ref_class_type.is_assignable_from(
       current_type(), this, CHECK_VERIFY(this));
     if (!subtype) {
-      verify_error(bci, "Bad invokespecial instruction: "
+      verify_error(ErrorContext::bad_code(bci),
+          "Bad invokespecial instruction: "
           "current class isn't assignable to reference class.");
        return;
     }
@@ -2073,7 +2434,7 @@
   if (opcode != Bytecodes::_invokestatic &&
       opcode != Bytecodes::_invokedynamic) {
     if (method_name == vmSymbols::object_initializer_name()) {  // <init> method
-      verify_invoke_init(bcs, ref_class_type, current_frame,
+      verify_invoke_init(bcs, index, ref_class_type, current_frame,
         code_length, this_uninit, cp, CHECK_VERIFY(this));
     } else {   // other methods
       // Ensures that target class is assignable to method class.
@@ -2103,8 +2464,10 @@
                   // Special case: arrays pretend to implement public Object
                   // clone().
                 } else {
-                  verify_error(bci,
-                    "Bad access to protected data in invokevirtual");
+                  verify_error(ErrorContext::bad_type(bci,
+                      current_frame->stack_top_ctx(),
+                      TypeOrigin::implicit(current_type())),
+                      "Bad access to protected data in invokevirtual");
                   return;
                 }
               }
@@ -2121,7 +2484,10 @@
   if (sig_stream.type() != T_VOID) {
     if (method_name == vmSymbols::object_initializer_name()) {
       // <init> method must have a void return type
-      verify_error(bci, "Return type must be void in <init> method");
+      /* Unreachable?  Class file parser verifies that methods with '<' have
+       * void return */
+      verify_error(ErrorContext::bad_code(bci),
+          "Return type must be void in <init> method");
       return;
     }
     VerificationType return_type[2];
@@ -2139,7 +2505,7 @@
     NULL, NULL, NULL, NULL, "[Z", "[C", "[F", "[D", "[B", "[S", "[I", "[J",
   };
   if (index < T_BOOLEAN || index > T_LONG) {
-    verify_error(bci, "Illegal newarray instruction");
+    verify_error(ErrorContext::bad_code(bci), "Illegal newarray instruction");
     return VerificationType::bogus_type();
   }
 
@@ -2150,8 +2516,9 @@
 }
 
 void ClassVerifier::verify_anewarray(
-    u2 index, constantPoolHandle cp, StackMapFrame* current_frame, TRAPS) {
-  verify_cp_class_type(index, cp, CHECK_VERIFY(this));
+    u2 bci, u2 index, constantPoolHandle cp,
+    StackMapFrame* current_frame, TRAPS) {
+  verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
   current_frame->pop_stack(
     VerificationType::integer_type(), CHECK_VERIFY(this));
 
@@ -2264,14 +2631,19 @@
 }
 
 void ClassVerifier::verify_return_value(
-    VerificationType return_type, VerificationType type, u2 bci, TRAPS) {
+    VerificationType return_type, VerificationType type, u2 bci,
+    StackMapFrame* current_frame, TRAPS) {
   if (return_type == VerificationType::bogus_type()) {
-    verify_error(bci, "Method expects a return value");
+    verify_error(ErrorContext::bad_type(bci,
+        current_frame->stack_top_ctx(), TypeOrigin::signature(return_type)),
+        "Method expects a return value");
     return;
   }
   bool match = return_type.is_assignable_from(type, this, CHECK_VERIFY(this));
   if (!match) {
-    verify_error(bci, "Bad return type");
+    verify_error(ErrorContext::bad_type(bci,
+        current_frame->stack_top_ctx(), TypeOrigin::signature(return_type)),
+        "Bad return type");
     return;
   }
 }
--- a/hotspot/src/share/vm/classfile/verifier.hpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.hpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -88,18 +88,178 @@
 #define CHECK_VERIFY_(verifier, result) \
   CHECK_(result)); if ((verifier)->has_error()) return (result); (0
 
+class TypeOrigin VALUE_OBJ_CLASS_SPEC {
+ private:
+  typedef enum {
+    CF_LOCALS,  // Comes from the current frame locals
+    CF_STACK,   // Comes from the current frame expression stack
+    SM_LOCALS,  // Comes from stackmap locals
+    SM_STACK,   // Comes from stackmap expression stack
+    CONST_POOL, // Comes from the constant pool
+    SIG,        // Comes from method signature
+    IMPLICIT,   // Comes implicitly from code or context
+    BAD_INDEX,  // No type, but the index is bad
+    FRAME_ONLY, // No type, context just contains the frame
+    NONE
+  } Origin;
+
+  Origin _origin;
+  u2 _index;              // local, stack, or constant pool index
+  StackMapFrame* _frame;  // source frame if CF or SM
+  VerificationType _type; // The actual type
+
+  TypeOrigin(
+      Origin origin, u2 index, StackMapFrame* frame, VerificationType type)
+      : _origin(origin), _index(index), _frame(frame), _type(type) {}
+
+ public:
+  TypeOrigin() : _origin(NONE), _index(0), _frame(NULL) {}
+
+  static TypeOrigin null();
+  static TypeOrigin local(u2 index, StackMapFrame* frame);
+  static TypeOrigin stack(u2 index, StackMapFrame* frame);
+  static TypeOrigin sm_local(u2 index, StackMapFrame* frame);
+  static TypeOrigin sm_stack(u2 index, StackMapFrame* frame);
+  static TypeOrigin cp(u2 index, VerificationType vt);
+  static TypeOrigin signature(VerificationType vt);
+  static TypeOrigin bad_index(u2 index);
+  static TypeOrigin implicit(VerificationType t);
+  static TypeOrigin frame(StackMapFrame* frame);
+
+  void reset_frame();
+  void details(outputStream* ss) const;
+  void print_frame(outputStream* ss) const;
+  const StackMapFrame* frame() const { return _frame; }
+  bool is_valid() const { return _origin != NONE; }
+  u2 index() const { return _index; }
+
+#ifdef ASSERT
+  void print_on(outputStream* str) const;
+#endif
+};
+
+class ErrorContext VALUE_OBJ_CLASS_SPEC {
+ private:
+  typedef enum {
+    INVALID_BYTECODE,     // There was a problem with the bytecode
+    WRONG_TYPE,           // Type value was not as expected
+    FLAGS_MISMATCH,       // Frame flags are not assignable
+    BAD_CP_INDEX,         // Invalid constant pool index
+    BAD_LOCAL_INDEX,      // Invalid local index
+    LOCALS_SIZE_MISMATCH, // Frames have differing local counts
+    STACK_SIZE_MISMATCH,  // Frames have different stack sizes
+    STACK_OVERFLOW,       // Attempt to push onto a full expression stack
+    STACK_UNDERFLOW,      // Attempt to pop and empty expression stack
+    MISSING_STACKMAP,     // No stackmap for this location and there should be
+    BAD_STACKMAP,         // Format error in stackmap
+    NO_FAULT,             // No error
+    UNKNOWN
+  } FaultType;
+
+  int _bci;
+  FaultType _fault;
+  TypeOrigin _type;
+  TypeOrigin _expected;
+
+  ErrorContext(int bci, FaultType fault) :
+      _bci(bci), _fault(fault)  {}
+  ErrorContext(int bci, FaultType fault, TypeOrigin type) :
+      _bci(bci), _fault(fault), _type(type)  {}
+  ErrorContext(int bci, FaultType fault, TypeOrigin type, TypeOrigin exp) :
+      _bci(bci), _fault(fault), _type(type), _expected(exp)  {}
+
+ public:
+  ErrorContext() : _bci(-1), _fault(NO_FAULT) {}
+
+  static ErrorContext bad_code(u2 bci) {
+    return ErrorContext(bci, INVALID_BYTECODE);
+  }
+  static ErrorContext bad_type(u2 bci, TypeOrigin type) {
+    return ErrorContext(bci, WRONG_TYPE, type);
+  }
+  static ErrorContext bad_type(u2 bci, TypeOrigin type, TypeOrigin exp) {
+    return ErrorContext(bci, WRONG_TYPE, type, exp);
+  }
+  static ErrorContext bad_flags(u2 bci, StackMapFrame* frame) {
+    return ErrorContext(bci, FLAGS_MISMATCH, TypeOrigin::frame(frame));
+  }
+  static ErrorContext bad_flags(u2 bci, StackMapFrame* cur, StackMapFrame* sm) {
+    return ErrorContext(bci, FLAGS_MISMATCH,
+                        TypeOrigin::frame(cur), TypeOrigin::frame(sm));
+  }
+  static ErrorContext bad_cp_index(u2 bci, u2 index) {
+    return ErrorContext(bci, BAD_CP_INDEX, TypeOrigin::bad_index(index));
+  }
+  static ErrorContext bad_local_index(u2 bci, u2 index) {
+    return ErrorContext(bci, BAD_LOCAL_INDEX, TypeOrigin::bad_index(index));
+  }
+  static ErrorContext locals_size_mismatch(
+      u2 bci, StackMapFrame* frame0, StackMapFrame* frame1) {
+    return ErrorContext(bci, LOCALS_SIZE_MISMATCH,
+        TypeOrigin::frame(frame0), TypeOrigin::frame(frame1));
+  }
+  static ErrorContext stack_size_mismatch(
+      u2 bci, StackMapFrame* frame0, StackMapFrame* frame1) {
+    return ErrorContext(bci, STACK_SIZE_MISMATCH,
+        TypeOrigin::frame(frame0), TypeOrigin::frame(frame1));
+  }
+  static ErrorContext stack_overflow(u2 bci, StackMapFrame* frame) {
+    return ErrorContext(bci, STACK_OVERFLOW, TypeOrigin::frame(frame));
+  }
+  static ErrorContext stack_underflow(u2 bci, StackMapFrame* frame) {
+    return ErrorContext(bci, STACK_UNDERFLOW, TypeOrigin::frame(frame));
+  }
+  static ErrorContext missing_stackmap(u2 bci) {
+    return ErrorContext(bci, MISSING_STACKMAP);
+  }
+  static ErrorContext bad_stackmap(int index, StackMapFrame* frame) {
+    return ErrorContext(0, BAD_STACKMAP, TypeOrigin::frame(frame));
+  }
+
+  bool is_valid() const { return _fault != NO_FAULT; }
+  int bci() const { return _bci; }
+
+  void reset_frames() {
+    _type.reset_frame();
+    _expected.reset_frame();
+  }
+
+  void details(outputStream* ss, methodOop method) const;
+
+#ifdef ASSERT
+  void print_on(outputStream* str) const {
+    str->print("error_context(%d, %d,", _bci, _fault);
+    _type.print_on(str);
+    str->print(",");
+    _expected.print_on(str);
+    str->print(")");
+  }
+#endif
+
+ private:
+  void location_details(outputStream* ss, methodOop method) const;
+  void reason_details(outputStream* ss) const;
+  void frame_details(outputStream* ss) const;
+  void bytecode_details(outputStream* ss, methodOop method) const;
+  void handler_details(outputStream* ss, methodOop method) const;
+  void stackmap_details(outputStream* ss, methodOop method) const;
+};
+
 // A new instance of this class is created for each class being verified
 class ClassVerifier : public StackObj {
  private:
   Thread* _thread;
+  GrowableArray<Symbol*>* _symbols;  // keep a list of symbols created
+
   Symbol* _exception_type;
   char* _message;
-  size_t _message_buffer_len;
-  GrowableArray<Symbol*>* _symbols;  // keep a list of symbols created
+
+  ErrorContext _error_context;  // contains information about an error
 
   void verify_method(methodHandle method, TRAPS);
   char* generate_code_data(methodHandle m, u4 code_length, TRAPS);
-  void verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS);
+  void verify_exception_handler_table(u4 code_length, char* code_data,
+                                      int& min, int& max, TRAPS);
   void verify_local_variable_table(u4 code_length, char* code_data, TRAPS);
 
   VerificationType cp_ref_index_to_type(
@@ -111,10 +271,10 @@
     instanceKlassHandle this_class, klassOop target_class,
     Symbol* field_name, Symbol* field_sig, bool is_method);
 
-  void verify_cp_index(constantPoolHandle cp, int index, TRAPS);
-  void verify_cp_type(
-    int index, constantPoolHandle cp, unsigned int types, TRAPS);
-  void verify_cp_class_type(int index, constantPoolHandle cp, TRAPS);
+  void verify_cp_index(u2 bci, constantPoolHandle cp, int index, TRAPS);
+  void verify_cp_type(u2 bci, int index, constantPoolHandle cp,
+      unsigned int types, TRAPS);
+  void verify_cp_class_type(u2 bci, int index, constantPoolHandle cp, TRAPS);
 
   u2 verify_stackmap_table(
     u2 stackmap_index, u2 bci, StackMapFrame* current_frame,
@@ -137,7 +297,7 @@
     constantPoolHandle cp, TRAPS);
 
   void verify_invoke_init(
-    RawBytecodeStream* bcs, VerificationType ref_class_type,
+    RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
     StackMapFrame* current_frame, u4 code_length, bool* this_uninit,
     constantPoolHandle cp, TRAPS);
 
@@ -147,10 +307,11 @@
     constantPoolHandle cp, TRAPS);
 
   VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);
-  void verify_anewarray(
-    u2 index, constantPoolHandle cp, StackMapFrame* current_frame, TRAPS);
+  void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp,
+      StackMapFrame* current_frame, TRAPS);
   void verify_return_value(
-    VerificationType return_type, VerificationType type, u2 offset, TRAPS);
+      VerificationType return_type, VerificationType type, u2 offset,
+      StackMapFrame* current_frame, TRAPS);
 
   void verify_iload (u2 index, StackMapFrame* current_frame, TRAPS);
   void verify_lload (u2 index, StackMapFrame* current_frame, TRAPS);
@@ -189,7 +350,7 @@
   };
 
   // constructor
-  ClassVerifier(instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS);
+  ClassVerifier(instanceKlassHandle klass, TRAPS);
 
   // destructor
   ~ClassVerifier();
@@ -207,13 +368,17 @@
   // Return status modes
   Symbol* result() const { return _exception_type; }
   bool has_error() const { return result() != NULL; }
+  char* exception_message() {
+    stringStream ss;
+    ss.print(_message);
+    _error_context.details(&ss, _method());
+    return ss.as_string();
+  }
 
   // Called when verify or class format errors are encountered.
   // May throw an exception based upon the mode.
-  void verify_error(u2 offset, const char* fmt, ...);
-  void verify_error(const char* fmt, ...);
+  void verify_error(ErrorContext ctx, const char* fmt, ...);
   void class_format_error(const char* fmt, ...);
-  void format_error_message(const char* fmt, int offset, va_list args);
 
   klassOop load_class(Symbol* name, TRAPS);
 
@@ -228,10 +393,11 @@
   // their reference counts need to be decrememented when the verifier object
   // goes out of scope.  Since these symbols escape the scope in which they're
   // created, we can't use a TempNewSymbol.
-  Symbol* create_temporary_symbol(const Symbol* s, int begin, int end, TRAPS);
+  Symbol* create_temporary_symbol(
+      const Symbol* s, int begin, int end, TRAPS);
   Symbol* create_temporary_symbol(const char *s, int length, TRAPS);
 
-  static bool _verify_verbose;  // for debugging
+  TypeOrigin ref_ctx(const char* str, TRAPS);
 };
 
 inline int ClassVerifier::change_sig_to_verificationType(
--- a/hotspot/src/share/vm/runtime/globals.hpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Mon Aug 06 15:54:45 2012 -0400
@@ -829,6 +829,9 @@
   product(bool, PrintGCApplicationStoppedTime, false,                       \
           "Print the time the application has been stopped")                \
                                                                             \
+  diagnostic(bool, VerboseVerification, false,                              \
+             "Display detailed verification details")                       \
+                                                                            \
   notproduct(uintx, ErrorHandlerTest, 0,                                    \
           "If > 0, provokes an error after VM initialization; the value"    \
           "determines which error to provoke.  See test_error_handler()"    \
--- a/hotspot/src/share/vm/runtime/relocator.cpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/runtime/relocator.cpp	Mon Aug 06 15:54:45 2012 -0400
@@ -465,13 +465,12 @@
 void Relocator::adjust_stack_map_table(int bci, int delta) {
   if (method()->has_stackmap_table()) {
     typeArrayOop data = method()->stackmap_data();
-    // The data in the array is a classfile representation of the stackmap
-    // table attribute, less the initial u2 tag and u4 attribute_length fields.
-    stack_map_table_attribute* attr = stack_map_table_attribute::at(
-        (address)data->byte_at_addr(0) - (sizeof(u2) + sizeof(u4)));
+    // The data in the array is a classfile representation of the stackmap table
+    stack_map_table* sm_table =
+        stack_map_table::at((address)data->byte_at_addr(0));
 
-    int count = attr->number_of_entries();
-    stack_map_frame* frame = attr->entries();
+    int count = sm_table->number_of_entries();
+    stack_map_frame* frame = sm_table->entries();
     int bci_iter = -1;
     bool offset_adjusted = false; // only need to adjust one offset
 
@@ -486,7 +485,7 @@
           frame->set_offset_delta(new_offset_delta);
         } else {
           assert(frame->is_same_frame() ||
-                 frame->is_same_frame_1_stack_item_frame(),
+                 frame->is_same_locals_1_stack_item_frame(),
                  "Frame must be one of the compressed forms");
           // The new delta exceeds the capacity of the 'same_frame' or
           // 'same_frame_1_stack_item_frame' frame types.  We need to
@@ -513,7 +512,7 @@
           if (frame->is_same_frame()) {
             same_frame_extended::create_at(frame_addr, new_offset_delta);
           } else {
-            same_frame_1_stack_item_extended::create_at(
+            same_locals_1_stack_item_extended::create_at(
               frame_addr, new_offset_delta, NULL);
             // the verification_info_type should already be at the right spot
           }
--- a/hotspot/src/share/vm/utilities/ostream.cpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.cpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -237,8 +237,9 @@
   return;
 }
 
-void outputStream::indent() {
+outputStream& outputStream::indent() {
   while (_position < _indentation) sp();
+  return *this;
 }
 
 void outputStream::print_jlong(jlong value) {
@@ -251,6 +252,47 @@
   print(os::julong_format_specifier(), value);
 }
 
+/**
+ * This prints out hex data in a 'windbg' or 'xxd' form, where each line is:
+ *   <hex-address>: 8 * <hex-halfword> <ascii translation (optional)>
+ * example:
+ * 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000  .DOF............
+ * 0000010: 0000 0000 0000 0040 0000 0020 0000 0005  .......@... ....
+ * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d  .......@.......]
+ * ...
+ *
+ * indent is applied to each line.  Ends with a CR.
+ */
+void outputStream::print_data(void* data, size_t len, bool with_ascii) {
+  size_t limit = (len + 16) / 16 * 16;
+  for (size_t i = 0; i < limit; ++i) {
+    if (i % 16 == 0) {
+      indent().print("%07x:", i);
+    }
+    if (i % 2 == 0) {
+      print(" ");
+    }
+    if (i < len) {
+      print("%02x", ((unsigned char*)data)[i]);
+    } else {
+      print("  ");
+    }
+    if ((i + 1) % 16 == 0) {
+      if (with_ascii) {
+        print("  ");
+        for (size_t j = 0; j < 16; ++j) {
+          size_t idx = i + j - 15;
+          if (idx < len) {
+            char c = ((char*)data)[idx];
+            print("%c", c >= 32 && c <= 126 ? c : '.');
+          }
+        }
+      }
+      print_cr("");
+    }
+  }
+}
+
 stringStream::stringStream(size_t initial_size) : outputStream() {
   buffer_length = initial_size;
   buffer        = NEW_RESOURCE_ARRAY(char, buffer_length);
--- a/hotspot/src/share/vm/utilities/ostream.hpp	Mon Aug 06 09:34:40 2012 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.hpp	Mon Aug 06 15:54:45 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,9 +59,11 @@
    outputStream(int width, bool has_time_stamps);
 
    // indentation
-   void indent();
+   outputStream& indent();
    void inc() { _indentation++; };
    void dec() { _indentation--; };
+   void inc(int n) { _indentation += n; };
+   void dec(int n) { _indentation -= n; };
    int  indentation() const    { return _indentation; }
    void set_indentation(int i) { _indentation = i;    }
    void fill_to(int col);
@@ -84,6 +86,7 @@
    void print_raw(const char* str, int len)   { write(str,         len); }
    void print_raw_cr(const char* str)         { write(str, strlen(str)); cr(); }
    void print_raw_cr(const char* str, int len){ write(str,         len); cr(); }
+   void print_data(void* data, size_t len, bool with_ascii);
    void put(char ch);
    void sp(int count = 1);
    void cr();
@@ -122,6 +125,19 @@
 extern outputStream* tty;           // tty output
 extern outputStream* gclog_or_tty;  // stream for gc log if -Xloggc:<f>, or tty
 
+class streamIndentor : public StackObj {
+ private:
+  outputStream* _str;
+  int _amount;
+
+ public:
+  streamIndentor(outputStream* str, int amt = 2) : _str(str), _amount(amt) {
+    _str->inc(_amount);
+  }
+  ~streamIndentor() { _str->dec(_amount); }
+};
+
+
 // advisory locking for the shared tty stream:
 class ttyLocker: StackObj {
   friend class ttyUnlocker;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/7116786/Test7116786.java	Mon Aug 06 15:54:45 2012 -0400
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test Test7116786
+ * @summary verify that VerifyError messages are as expected
+ * @library testcases.jar
+ * @run main/othervm -Xverify:all Test7116786
+ */
+
+
+/**
+ * This class contains information regarding when a VerifyError is thrown
+ * in the verifier.  Most of the data is informational-only, and can be
+ * used to track down where and why VerifyErrors are thrown.  As such it
+ * is possible the information may go out-of-date.
+ *
+ * The only fields used for the purpose of testing is the 'caseName' and
+ * the 'message'.  The 'caseName' corresponds to a classfile which exhibits
+ * the VerifyError, and the 'message' is a regular expression which we expect
+ * to match the verify error message.  If the 'message' doesn't match what
+ * we expect, it warrents investigation to see if we are still triggering
+ * the VerifyError that we expect.  It could simply just be that the message
+ * changed, which is fine.
+ *
+ * Some cases are not testable, either because the code is probably unreachable
+ * or the test classfile would be too onerous to create.  These cases are
+ * marked with 'testable' == false, and the test runner will skip them.
+ */
+class Case {
+    private String caseName;    // Name of the case
+    private String file;        // Source file where VerifyError is thrown
+    private String location;    // enclosing function or switch case
+    private String description; // What causes this VerifyError
+    private String message;     // The VerifyError message used.
+
+    private boolean testable;   // Whether this case is testable or not.
+
+    public Case(String caseName, String file, boolean testable,
+                String location, String description, String message) {
+        this.caseName = caseName;
+        this.file = file;
+        this.testable = testable;
+        this.location = location;
+        this.description = description;
+        this.message = message;
+    }
+
+    String getCaseName() { return this.caseName; }
+    String getFile() { return this.file; }
+    String getLocation() { return this.location; }
+    String getDescription() { return this.description; }
+    String getMessage() { return this.message; }
+
+    boolean isTestable() { return this.testable; }
+}
+
+/**
+ * These are the locations in the source code where VerifyErrors are thrown
+ * as of today, 2012/07/18.  These may change as the verification code is
+ * modified, which is ok.  This test is trying to provide coverage for all
+ * VerifyErrors (just to make sure there are no crashes) and it's probably
+ * not necessary to update it every time the VM changes.
+ */
+class VerifyErrorCases {
+    public static final Case[] cases = {
+
+        new Case("case00", "stackMapFrame.cpp", true, "pop_stack_ex",
+                 "stack underflow",
+                 "Operand stack underflow"),
+
+        new Case("case01", "stackMapFrame.cpp", true, "pop_stack_ex",
+                 "stack pop not assignable to expected",
+                 "Bad type on operand stack"),
+
+        new Case("case02", "stackMapFrame.cpp", true, "get_local",
+                 "local index out-of-bounds",
+                 "Local variable table overflow"),
+
+        new Case("case03", "stackMapFrame.cpp", true, "get_local",
+                 "local not assignable to expected",
+                 "Bad local variable type"),
+
+        new Case("case04", "stackMapFrame.cpp", true, "get_local_2",
+                 "local index out-of-bounds [type2]",
+                 "get long/double overflows locals"),
+
+        new Case("case05", "stackMapFrame.cpp", true, "get_local_2",
+                 "local not assignabled to expected [type2]",
+                 "Bad local variable type"),
+
+        /* Unreachable: Can't split long/double on stack */
+        new Case("case06", "stackMapFrame.cpp", false, "get_local_2",
+                 "local second-word not assignabled to expected",
+                 "Bad local variable type"),
+
+        new Case("case07", "stackMapFrame.cpp", true, "set_local",
+                 "local index out-of-bounds",
+                 "Local variable table overflow"),
+
+        new Case("case08", "stackMapFrame.cpp", true, "set_local_2",
+                 "local index out-of-bounds [type2]",
+                 "Local variable table overflow"),
+
+        new Case("case09", "stackMapFrame.hpp", true, "push_stack",
+                 "stack overflow",
+                 "Operand stack overflow"),
+
+        new Case("case10", "stackMapFrame.hpp", true, "push_stack_2",
+                 "stack overflow [type2]",
+                 "Operand stack overflow"),
+
+        new Case("case11", "stackMapFrame.hpp", true, "pop_stack",
+                 "stack underflow",
+                 "Operand stack underflow"),
+
+        new Case("case12", "stackMapTable.cpp", true, "StackMapTable ctor",
+                 "stackmap offset beyond code size",
+                 "StackMapTable error: bad offset"),
+
+        new Case("case13", "stackMapTable.cpp", true, "match_stackmap",
+                 "no stackmap frame at expected location",
+                 "Expecting a stackmap frame at branch target "),
+
+        new Case("case14", "stackMapTable.cpp", true, "check_jump_target",
+                 "no stackmap frame at jump location or bad jump",
+                 "Inconsistent stackmap frames at branch target "),
+
+        new Case("case15", "stackMapTable.cpp", true, "check_new_object",
+                 "backward jump with uninit",
+                 "Uninitialized object exists on backward branch "),
+
+        /* Unreachable: wide instructions verified during bytecode analysis */
+        new Case("case16", "verifier.cpp", false, "loop header",
+                 "bad op in wide instruction",
+                 "Bad wide instruction"),
+
+        new Case("case17", "verifier.cpp", true, "case iaload",
+                 "TOS not X array",
+                 "Bad type on operand stack in iaload"),
+
+        new Case("case18", "verifier.cpp", true, "case baload",
+                 "TOS not X array",
+                 "Bad type on operand stack in baload"),
+
+        new Case("case19", "verifier.cpp", true, "case caload",
+                 "TOS not X array",
+                 "Bad type on operand stack in caload"),
+
+        new Case("case20", "verifier.cpp", true, "case saload",
+                 "TOS not X array",
+                 "Bad type on operand stack in saload"),
+
+        new Case("case21", "verifier.cpp", true, "case laload",
+                 "TOS not X array",
+                 "Bad type on operand stack in laload"),
+
+        new Case("case22", "verifier.cpp", true, "case faload",
+                 "TOS not X array",
+                 "Bad type on operand stack in faload"),
+
+        new Case("case23", "verifier.cpp", true, "case daload",
+                 "TOS not X array",
+                 "Bad type on operand stack in daload"),
+
+        new Case("case24", "verifier.cpp", true, "case aaload",
+                 "TOS not X array",
+                 "Bad type on operand stack in aaload"),
+
+        new Case("case25", "verifier.cpp", true, "case iastore",
+                 "TOS not int array",
+                 "Bad type on operand stack in iastore"),
+
+        new Case("case26", "verifier.cpp", true, "case bastore",
+                 "TOS not byte array",
+                 "Bad type on operand stack in bastore"),
+
+        new Case("case27", "verifier.cpp", true, "case castore",
+                 "TOS not char array",
+                 "Bad type on operand stack in castore"),
+
+        new Case("case28", "verifier.cpp", true, "case sastore",
+                 "TOS not short array",
+                 "Bad type on operand stack in sastore"),
+
+        new Case("case29", "verifier.cpp", true, "case lastore",
+                 "TOS not long array",
+                 "Bad type on operand stack in lastore"),
+
+        new Case("case30", "verifier.cpp", true, "case fastore",
+                 "TOS not float array",
+                 "Bad type on operand stack in fastore"),
+
+        new Case("case31", "verifier.cpp", true, "case dastore",
+                 "TOS not double array",
+                 "Bad type on operand stack in dastore"),
+
+        new Case("case32", "verifier.cpp", true, "case aastore",
+                 "TOS not object array",
+                 "Bad type on operand stack in aastore"),
+
+        /* Unreachable: In order to hit this case, we would need a
+         * category2_1st at TOS which is not possible. */
+        new Case("case33", "verifier.cpp", false, "case pop2",
+                 "TOS is category2_1st (would split)",
+                 "Bad type on operand stack in pop2"),
+
+        /* Unreachable: In order to hit this case, we would need a
+         * category2_1st at stack depth 2 with category_1 on TOS which is not
+         * possible. */
+        new Case("case34", "verifier.cpp", false, "case dup_x2",
+                 "TOS-1 is category2_1st (would split)",
+                 "Bad type on operand stack in dup_x2"),
+
+        /* Unreachable: In order to hit this case, we would need a
+         * category2_1st at TOS which is not possible. */
+        new Case("case35", "verifier.cpp", false, "case dup2",
+                 "TOS-1 is category2_1st (would split)",
+                 "Bad type on operand stack in dup2"),
+
+        /* Unreachable: In order to hit this case, we would need a
+         * category2_1st at TOS which is not possible. */
+        new Case("case36", "verifier.cpp", false, "case dup2_x1",
+                 "TOS-1 is category2_1st (would split)",
+                 "Bad type on operand stack in dup2_x1"),
+
+        /* Unreachable: In order to hit this case, we would need a
+         * category2_1st at TOS which is not possible. */
+        new Case("case37", "verifier.cpp", false, "case dup2_x2",
+                 "TOS-1 is category2_1st (would split)",
+                 "Bad type on operand stack in dup2_x2"),
+
+        /* Unreachable: In order to hit this case, we would need a
+         * category2_1st at stack depth 3 with either 2 category_1 or 1
+         * category_2 on TOS, which is not possible. */
+        new Case("case38", "verifier.cpp", false, "case dup2_x2",
+                 "TOS-3 is category2_1st (would split)",
+                 "Bad type on operand stack in dup2_x2"),
+
+        new Case("case39", "verifier.cpp", true, "case return",
+                 "return type of method is not void",
+                 "Method expects a return value"),
+
+        new Case("case40", "verifier.cpp", true, "case return",
+                 "return with uninitialized this ",
+                 "Constructor must call super() or this() before return"),
+
+        new Case("case41", "verifier.cpp", true, "case new",
+                 "cp index not a class type",
+                 "Illegal new instruction"),
+
+        new Case("case42", "verifier.cpp", true, "case arraylength",
+                 "TOS is not an array",
+                 "Bad type on operand stack in arraylength"),
+
+        new Case("case43", "verifier.cpp", true, "case multianewarray",
+                 "CP index does not refer to array type",
+                 "Illegal constant pool index in multianewarray instruction"),
+
+        new Case("case44", "verifier.cpp", true, "case multianewarray",
+                 "Bad dimension (<1) or does not match CP signature",
+                 "Illegal dimension in multianewarray instruction: "),
+
+        new Case("case45", "verifier.cpp", true, "case default",
+                 "Unrecognized bytecode",
+                 "Bad instruction: "),
+
+        new Case("case46", "verifier.cpp", true, "loop end",
+                 "control flow falls off method",
+                 "Control flow falls through code end"),
+
+        new Case("case47", "verifier.cpp", true, "generate_code_data",
+                 "illegal bytecode via RawBytecodeStream (breakpoint)",
+                 "Bad instruction"),
+
+        new Case("case48", "verifier.cpp", true, "generate_code_data",
+                 "illegal bytecode via RawBytecodeStream (other illegal)",
+                 "Bad instruction"),
+
+        new Case("case49", "verifier.cpp", true,
+                 "verify_exception_handler_table",
+                 "catch_type is not throwable",
+                 "Catch type is not a subclass of Throwable in " +
+                 "exception handler "),
+
+        new Case("case50", "verifier.cpp", true, "verify_stackmap_table",
+                 "missing a stack map frame @ target location (mid table)",
+                 "Expecting a stack map frame"),
+
+        new Case("case51", "verifier.cpp", true, "verify_stackmap_table",
+                 "stack map does not match?",
+                 "Instruction type does not match stack map"),
+
+        new Case("case52", "verifier.cpp", true, "verify_stackmap_table",
+                 "missing a stack map frame @ target location (end of table)",
+                 "Expecting a stack map frame"),
+
+        new Case("case53", "verifier.cpp", true,
+                 "verify_exception_handler_targets",
+                 "stackmap mismatch at exception handler",
+                 "Stack map does not match the one at exception handler "),
+
+        new Case("case54", "verifier.cpp", true, "verify_cp_index",
+                 "constant pool index is out-of-bounds",
+                 "Illegal constant pool index "),
+
+        new Case("case55", "verifier.cpp", true, "verify_cp_type",
+                 "constant pool entry is not expected type",
+                 "Illegal type at constant pool entry "),
+
+        new Case("case56", "verifier.cpp", true, "verify_cp_class_type",
+                 "constant pool entry is not an object type",
+                 "Illegal type at constant pool entry "),
+
+        /* Unreachable: verify_cp_type gates this case */
+        new Case("case57", "verifier.cpp", false, "verify_ldc",
+                 "invalid constant pool index in ldc",
+                 "Invalid index in ldc"),
+
+        new Case("case58", "verifier.cpp", true, "verify_switch",
+                 "bad switch padding",
+                 "Nonzero padding byte in lookswitch or tableswitch"),
+
+        new Case("case59", "verifier.cpp", true, "verify_switch",
+                 "tableswitch low is greater than high",
+                 "low must be less than or equal to high in tableswitch"),
+
+        /* Unreachable on 64-bit?  Only way to get here is to overflow
+         * the 'keys' variable which can't happen on 64-bit since we're dealing
+         * with 32-bit values.  Perhaps reachable on 32-bit but the
+         * triggering class would be quite large */
+        new Case("case60", "verifier.cpp", false, "verify_switch",
+                 "high - low + 1 < 0 (overflow?)",
+                 "too many keys in tableswitch"),
+
+        /* Would have to create a 16G classfile to trip this.  Possible but
+         * not reasonable to do in a test.  */
+        new Case("case61", "verifier.cpp", false, "verify_switch",
+                 "lookupswitch keys < 0",
+                 "number of keys in lookupswitch less than 0"),
+
+        new Case("case62", "verifier.cpp", true, "verify_switch",
+                 "lookupswitch keys out-of-order",
+                 "Bad lookupswitch instruction"),
+
+        /* Unreachable: Class file parser verifies Fieldref contents */
+        new Case("case63", "verifier.cpp", false, "verify_field_instructions",
+                 "referenced class is not an CP object",
+                 "Expecting reference to class in class "),
+
+        new Case("case64", "verifier.cpp", true, "verify_field_instructions",
+                 "TOS not assignable to field type in putfield",
+                 "Bad type on operand stack in putfield"),
+
+        new Case("case65", "verifier.cpp", true, "verify_field_instructions",
+                 "TOS not assignable to class when accessing protected field",
+                 "Bad access to protected data in getfield"),
+
+        new Case("case66", "verifier.cpp", true, "verify_invoke_init",
+                 "Uninit_this is not of the current type or it's supertype",
+                 "Bad <init> method call"),
+
+        /* Unreachable:  Stack map parsing ensures valid type and new
+         * instructions have a valid BCI. */
+        new Case("case67", "verifier.cpp", false, "verify_invoke_init",
+                 "Uninit type with bad new instruction index",
+                 "Expecting new instruction"),
+
+        new Case("case68", "verifier.cpp", true, "verify_invoke_init",
+                 "calling other class's <init> method",
+                 "Call to wrong <init> method"),
+
+        new Case("case69", "verifier.cpp", true, "verify_invoke_init",
+                 "Calling protected <init> and type unassignable from current",
+                 "Bad access to protected <init> method"),
+
+        new Case("case70", "verifier.cpp", true, "verify_invoke_init",
+                 "TOS is not an uninitialized (or Uninit_this) type",
+                 "Bad operand type when invoking <init>"),
+
+        new Case("case71", "verifier.cpp", true, "verify_invoke_instructions",
+                 "Arg count in instruction doesn't match signature",
+                 "Inconsistent args count operand in invokeinterface"),
+
+        new Case("case72", "verifier.cpp", true, "verify_invoke_instructions",
+                 "Non-zero pad in invokeinterface",
+                 "Fourth operand byte of invokeinterface must be zero"),
+
+        new Case("case73", "verifier.cpp", true, "verify_invoke_instructions",
+                 "Non-zero pad in invokedynamic",
+                 "Third and fourth operand bytes of " +
+                 "invokedynamic must be zero"),
+
+        new Case("case74", "verifier.cpp", true, "verify_invoke_instructions",
+                 "Non-invokespecial trying to invoke a '<' method",
+                 "Illegal call to internal method"),
+
+        new Case("case75", "verifier.cpp", true, "verify_invoke_instructions",
+                 "invokespecial and current unassignable from referenced type",
+                 "Bad invokespecial instruction: current class isn't " +
+                 "assignable to reference class."),
+
+        new Case("case76", "verifier.cpp", true, "verify_invoke_instructions",
+                 "TOS not assignable to current when calling protected method",
+                 "Bad access to protected data in invokevirtual"),
+
+        /* Unreachable:  class file parser enforces void signature */
+        new Case("case77", "verifier.cpp", false, "verify_invoke_instructions",
+                 "<init> method is not void return",
+                 "Return type must be void in <init> method"),
+
+        new Case("case78", "verifier.cpp", true, "get_newarray_type",
+                 "newarray type invalid",
+                 "Illegal newarray instruction"),
+
+        new Case("case79", "verifier.cpp", true, "verify_return_value",
+                 "void return from method which has a return value",
+                 "Method expects a return value"),
+
+        new Case("case80", "verifier.cpp", true, "verify_return_value",
+                 "TOS type does not match signature",
+                 "Bad return type"),
+
+        new Case("case81", "verifier.cpp", true, "verify_stackmap_table",
+                 "stack map does not match (flags)",
+                 "Instruction type does not match stack map")
+    };
+}
+
+public class Test7116786 {
+    public static void main(String argv[]) throws Exception {
+        for (Case c : VerifyErrorCases.cases) {
+            System.out.println("******** " + c.getCaseName() + " ********");
+            if (c.isTestable()) {
+                try {
+                    ClassLoader cl = Test7116786.class.getClassLoader();
+                    Class<?> cls = Class.forName(c.getCaseName(), true, cl);
+                    throw new RuntimeException(
+                        "++ FAIL: No verify error encountered");
+                } catch (VerifyError ve) {
+                    String message = c.getMessage();
+                    String veMessage = ve.getMessage();
+                    System.out.print(veMessage);
+                    if (!veMessage.startsWith(message)) {
+                        // We're not seeing the message we expect.  Could be
+                        // that we've gotten the wrong VerifyError case, or
+                        // maybe the message changed.
+                        System.out.println("++ FAIL? " +
+                            "Message does not match what was expected: " +
+                            message);
+                        continue;
+                    }
+                    if (!veMessage.contains("Exception Details:") &&
+                        !veMessage.contains("Reason:")) {
+                        System.out.println("++ FAIL: No details found");
+                        throw new RuntimeException("FAIL: No details found");
+                    }
+                    System.out.println("++ PASS");
+                }
+            } else {
+               System.out.println("++ SKIPPED");
+            }
+        }
+    }
+}
Binary file hotspot/test/runtime/7116786/testcases.jar has changed