changeset 13577:cf519e23a3f1 mvt

8182367: Byte-code verifier support for minimal value types Summary: Support verifier recognition of new value type VerificationType and add verifier processing of minimal value type bytecodes Reviewed-by: acorn, hseigel, jrose
author lfoltan
date Thu, 07 Sep 2017 13:52:56 -0400
parents d0625b614897
children 5e389fdf564c
files src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/stackMapFrame.cpp src/share/vm/classfile/stackMapTable.cpp src/share/vm/classfile/verificationType.cpp src/share/vm/classfile/verificationType.hpp src/share/vm/classfile/verifier.cpp src/share/vm/classfile/verifier.hpp test/runtime/valhalla/valuetypes/DeriveValueTypeCreation.java test/runtime/valhalla/valuetypes/MVTComboDebugTier1.java test/runtime/valhalla/valuetypes/MVTComboTier1.java test/runtime/valhalla/valuetypes/UninitializedValueFieldsTest.java test/runtime/valhalla/valuetypes/VDefaultTest.java test/runtime/valhalla/valuetypes/VTBufferTest.java test/runtime/valhalla/valuetypes/VWithFieldTest.java test/runtime/valhalla/valuetypes/ValueOops.java test/runtime/valhalla/valuetypes/ValueTypeArray.java test/runtime/valhalla/valuetypes/ValueTypeCreation.java test/runtime/valhalla/valuetypes/ValueTypeDensity.java test/runtime/valhalla/valuetypes/ValueTypeGetField.java test/runtime/valhalla/valuetypes/VboxUnbox.java test/runtime/valhalla/valuetypes/verifier/ValueCapableClass.java test/runtime/valhalla/valuetypes/verifier/VloadTest.java test/runtime/valhalla/valuetypes/verifier/VunboxErrorIndex.java
diffstat 23 files changed, 770 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/classFileParser.cpp	Wed Aug 30 14:50:03 2017 -0400
+++ b/src/share/vm/classfile/classFileParser.cpp	Thu Sep 07 13:52:56 2017 -0400
@@ -421,7 +421,10 @@
         if (!_need_verify) break;
         const int klass_ref_index = cp->klass_ref_index_at(index);
         const int name_and_type_ref_index = cp->name_and_type_ref_index_at(index);
-        check_property(valid_klass_reference_at(klass_ref_index),
+        check_property(valid_klass_reference_at(klass_ref_index) ||
+                       (valid_value_type_reference_at(klass_ref_index) &&
+                        ((EnableMVT && (tag == JVM_CONSTANT_Fieldref)) ||
+                         EnableValhalla)),
                        "Invalid constant pool index %u in class file %s",
                        klass_ref_index, CHECK);
         check_property(valid_cp_range(name_and_type_ref_index, length) &&
@@ -481,13 +484,14 @@
             cp->symbol_at_put(class_index, vmSymbols::java_lang____Value());
             cp->unresolved_value_type_at_put(index, class_index, num_klasses++);
         } else if (EnableValhalla || EnableMVT) {
+          const char* derive_vt_classname_postfix = "$Value;";
           // check for a value type
           // check for name > 3 to rule out ";Q;" where no name is present
           if (name_len != 0 &&
               name_len > 3 &&
-              name->byte_at(0) == ';' &&
-              name->byte_at(1) == 'Q' &&
-              name->byte_at(name_len-1) == ';') {
+              name->starts_with(";Q") &&
+              ((EnableValhalla && (name->byte_at(name_len-1) == ';')) ||
+               (EnableMVT && ClassLoader::string_ends_with(name->as_utf8(), derive_vt_classname_postfix)))) {
             Symbol* const strippedsym = SymbolTable::new_symbol(name, 2, name_len-1, CHECK);
             assert(strippedsym != NULL, "failure to create value type stripped name");
             cp->symbol_at_put(class_index, strippedsym);
--- a/src/share/vm/classfile/stackMapFrame.cpp	Wed Aug 30 14:50:03 2017 -0400
+++ b/src/share/vm/classfile/stackMapFrame.cpp	Thu Sep 07 13:52:56 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -101,6 +101,7 @@
   switch (ss.type()) {
     case T_OBJECT:
     case T_ARRAY:
+    case T_VALUETYPE:
     {
       Symbol* sig = ss.as_symbol(CHECK_(VerificationType::bogus_type()));
       // Create another symbol to save as signature stream unreferences
@@ -109,6 +110,9 @@
         verifier()->create_temporary_symbol(sig, 0, sig->utf8_length(),
                                  CHECK_(VerificationType::bogus_type()));
       assert(sig_copy == sig, "symbols don't match");
+      if (ss.type() == T_VALUETYPE) {
+        return VerificationType::valuetype_type(sig_copy);
+      }
       return VerificationType::reference_type(sig_copy);
     }
     case T_INT:     return VerificationType::integer_type();
--- a/src/share/vm/classfile/stackMapTable.cpp	Wed Aug 30 14:50:03 2017 -0400
+++ b/src/share/vm/classfile/stackMapTable.cpp	Thu Sep 07 13:52:56 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -169,10 +169,16 @@
     int nconstants = _cp->length();
     if ((class_index <= 0 || class_index >= nconstants) ||
         (!_cp->tag_at(class_index).is_klass() &&
-         !_cp->tag_at(class_index).is_unresolved_klass())) {
+         !_cp->tag_at(class_index).is_unresolved_klass() &&
+         !_cp->tag_at(class_index).is_value_type() &&
+         !_cp->tag_at(class_index).is_unresolved_value_type())) {
       _stream->stackmap_format_error("bad class index", THREAD);
       return VerificationType::bogus_type();
     }
+    if (_cp->tag_at(class_index).is_value_type() ||
+        _cp->tag_at(class_index).is_unresolved_value_type()) {
+      return VerificationType::valuetype_type(_cp->klass_name_at(class_index));
+    }
     return VerificationType::reference_type(_cp->klass_name_at(class_index));
   }
   if (tag == ITEM_UninitializedThis) {
--- a/src/share/vm/classfile/verificationType.cpp	Wed Aug 30 14:50:03 2017 -0400
+++ b/src/share/vm/classfile/verificationType.cpp	Thu Sep 07 13:52:56 2017 -0400
@@ -135,6 +135,11 @@
         name(), 2, name()->utf8_length() - 1,
         CHECK_(VerificationType::bogus_type()));
       return VerificationType::reference_type(component);
+    case 'Q':
+      component = context->create_temporary_symbol(
+        name(), 2, name()->utf8_length() - 1,
+        CHECK_(VerificationType::bogus_type()));
+      return VerificationType::valuetype_type(component);
     default:
       // Met an invalid type signature, e.g. [X
       return VerificationType::bogus_type();
@@ -159,6 +164,7 @@
     case Double_2nd:       st->print("double_2nd"); break;
     case Null:             st->print("null"); break;
     case ReferenceQuery:   st->print("reference type"); break;
+    case ValueTypeQuery:   st->print("value 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;
--- a/src/share/vm/classfile/verificationType.hpp	Wed Aug 30 14:50:03 2017 -0400
+++ b/src/share/vm/classfile/verificationType.hpp	Thu Sep 07 13:52:56 2017 -0400
@@ -70,21 +70,23 @@
 
     // Enum for the _data field
     enum {
-      // Bottom two bits determine if the type is a reference, primitive,
-      // uninitialized or a query-type.
-      TypeMask           = 0x00000003,
+      // Bottom three bits determine if the type is a reference, value type,
+      // primitive, uninitialized or a query-type.
+      TypeMask           = 0x00000007,
 
       // Topmost types encoding
-      Reference          = 0x0,        // _sym contains the name
+      Reference          = 0x0,        // _sym contains the name of an object 
       Primitive          = 0x1,        // see below for primitive list
       Uninitialized      = 0x2,        // 0x00ffff00 contains bci
       TypeQuery          = 0x3,        // Meta-types used for category testing
+      ValueType          = 0x4,        // _sym contains the name of a value type
 
       // Utility flags
       ReferenceFlag      = 0x00,       // For reference query types
       Category1Flag      = 0x01,       // One-word values
       Category2Flag      = 0x02,       // First word of a two-word value
       Category2_2ndFlag  = 0x04,       // Second word of a two-word value
+      ValueTypeFlag      = 0x08,       // For value type query types
 
       // special reference values
       Null               = 0x00000000, // A reference with a 0 sym is null
@@ -116,7 +118,8 @@
       ReferenceQuery     = (ReferenceFlag     << 1 * BitsPerByte) | TypeQuery,
       Category1Query     = (Category1Flag     << 1 * BitsPerByte) | TypeQuery,
       Category2Query     = (Category2Flag     << 1 * BitsPerByte) | TypeQuery,
-      Category2_2ndQuery = (Category2_2ndFlag << 1 * BitsPerByte) | TypeQuery
+      Category2_2ndQuery = (Category2_2ndFlag << 1 * BitsPerByte) | TypeQuery,
+      ValueTypeQuery     = (ValueTypeFlag     << 1 * BitsPerByte) | TypeQuery
     };
 
   VerificationType(uintptr_t raw_data) {
@@ -149,6 +152,8 @@
   // any reference is assignable to reference_check.
   static VerificationType reference_check()
     { return VerificationType(ReferenceQuery); }
+  static VerificationType valuetype_check()
+    { return VerificationType(ValueTypeQuery); }
   static VerificationType category1_check()
     { return VerificationType(Category1Query); }
   static VerificationType category2_check()
@@ -158,17 +163,28 @@
 
   // For reference types, store the actual Symbol
   static VerificationType reference_type(Symbol* sh) {
-      assert(((uintptr_t)sh & 0x3) == 0, "Symbols must be aligned");
+      assert(((uintptr_t)sh & TypeMask) == 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.
       return VerificationType((uintptr_t)sh);
-  }
+  }  
   static VerificationType uninitialized_type(u2 bci)
     { return VerificationType(bci << 1 * BitsPerByte | Uninitialized); }
   static VerificationType uninitialized_this_type()
     { return uninitialized_type(BciForThis); }
 
+  // For value types, store the actual Symbol* and set the 3rd bit.
+  // Provides a way for a value type to be distinguished from a reference type.
+  static VerificationType valuetype_type(Symbol* sh) {
+      assert(((uintptr_t)sh & TypeMask) == 0, "Symbols must be aligned");
+      assert((uintptr_t)sh != 0, "Null is not a valid value type");
+      // 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.
+      return VerificationType((uintptr_t)sh | ValueType);
+  }
+
   // Create based on u1 read from classfile
   static VerificationType from_tag(u1 tag);
 
@@ -184,11 +200,12 @@
   bool is_double() const    { return (_u._data == Double); }
   bool is_long2() const     { return (_u._data == Long_2nd); }
   bool is_double2() const   { return (_u._data == Double_2nd); }
-  bool is_reference() const { return ((_u._data & TypeMask) == Reference); }
+  bool is_reference() const { return (((_u._data & TypeMask) == Reference) && !is_valuetype_check()); }
+  bool is_valuetype() const { return ((_u._data & TypeMask) == ValueType); }
   bool is_category1() const {
     // This should return true for all one-word types, which are category1
-    // primitives, and references (including uninitialized refs).  Though
-    // the 'query' types should technically return 'false' here, if we
+    // primitives, references (including uninitialized refs) and value types.
+    // Though the 'query' types should technically return 'false' here, if we
     // allow this to return true, we can perform the test using only
     // 2 operations rather than 8 (3 masks, 3 compares and 2 logical 'ands').
     // Since noone should call this on a query type anyway, this is ok.
@@ -202,6 +219,7 @@
     return ((_u._data & Category2_2nd) == Category2_2nd);
   }
   bool is_reference_check() const { return _u._data == ReferenceQuery; }
+  bool is_valuetype_check() const { return _u._data == ValueTypeQuery; }
   bool is_category1_check() const { return _u._data == Category1Query; }
   bool is_category2_check() const { return _u._data == Category2Query; }
   bool is_category2_2nd_check() const { return _u._data == Category2_2ndQuery; }
@@ -219,6 +237,7 @@
   bool is_float_array() const { return is_x_array('F'); }
   bool is_double_array() const { return is_x_array('D'); }
   bool is_object_array() const { return is_x_array('L'); }
+  bool is_value_array() const { return is_x_array('Q'); }
   bool is_array_array() const { return is_x_array('['); }
   bool is_reference_array() const
     { return is_object_array() || is_array_array(); }
@@ -244,14 +263,14 @@
   }
 
   Symbol* name() const {
-    assert(is_reference() && !is_null(), "Must be a non-null reference");
-    return _u._sym;
+    assert(!is_null() && (is_reference() || is_valuetype()), "Must be a non-null reference or a value type");
+    return (is_reference() ? _u._sym : ((Symbol*)(_u._data & ~(uintptr_t)ValueType)));
   }
 
   bool equals(const VerificationType& t) const {
     return (_u._data == t._u._data ||
-      (is_reference() && t.is_reference() && !is_null() && !t.is_null() &&
-       name() == t.name()));
+            (((is_reference() && t.is_reference()) || (is_valuetype() && t.is_valuetype())) &&
+             !is_null() && !t.is_null() && name() == t.name()));
   }
 
   bool operator ==(const VerificationType& t) const {
@@ -280,6 +299,8 @@
           return from.is_category2_2nd();
         case ReferenceQuery:
           return from.is_reference() || from.is_uninitialized();
+        case ValueTypeQuery:
+          return from.is_valuetype();
         case Boolean:
         case Byte:
         case Char:
@@ -291,6 +312,8 @@
             return is_reference_assignable_from(from, context,
                                                 from_field_is_protected,
                                                 THREAD);
+          } else if (is_valuetype() && from.is_valuetype()) {
+            return is_valuetype_assignable_from(from, context, THREAD);
           } else {
             return false;
           }
@@ -335,6 +358,14 @@
     const VerificationType&, ClassVerifier*, bool from_field_is_protected,
     TRAPS) const;
 
+  bool is_valuetype_assignable_from(const VerificationType& from, ClassVerifier* context, TRAPS) const {
+    // 1. Check names - two value types are assignable if they have the same name
+    // 2. Check java/lang/__Value - from may be trying to be assigned to a __Value parameter
+    assert(is_valuetype() && from.is_valuetype(), "Is value type assignable called with a non-value type");
+    return (name() == from.name() ||
+            name() == vmSymbols::java_lang____Value());
+  }
+
  public:
   static bool resolve_and_check_assignability(InstanceKlass* klass, Symbol* name,
                                               Symbol* from_name, bool from_field_is_protected,
--- a/src/share/vm/classfile/verifier.cpp	Wed Aug 30 14:50:03 2017 -0400
+++ b/src/share/vm/classfile/verifier.cpp	Thu Sep 07 13:52:56 2017 -0400
@@ -239,8 +239,9 @@
   return (should_verify_for(klass->class_loader(), should_verify_class) &&
     // return if the class is a bootstrapping class
     // or defineClass specified not to verify by default (flags override passed arg)
-    // We need to skip the following four for bootstraping
+    // We need to skip the following few for bootstrapping
     name != vmSymbols::java_lang_Object() &&
+    name != vmSymbols::java_lang____Value() &&
     name != vmSymbols::java_lang_Class() &&
     name != vmSymbols::java_lang_String() &&
     name != vmSymbols::java_lang_Throwable() &&
@@ -251,6 +252,11 @@
     // Shared classes shouldn't have stackmaps either.
     !klass->is_shared() &&
 
+    // A MVT derived value type contains no code atrribute - no private static
+    // methods, no instance methods, no <clinit>, no <init>.  So while format
+    // checking is performed on it, verification is not.
+    (!((EnableMVT || EnableValhalla) && klass->access_flags().is_value_type())) &&
+
     // As of the fix for 4486457 we disable verification for all of the
     // dynamically-generated bytecodes associated with the 1.4
     // reflection implementation, not just those associated with
@@ -584,12 +590,22 @@
   return VerificationType::reference_type(vmSymbols::java_lang_Object());
 }
 
+VerificationType ClassVerifier::__value_type() const {
+  return VerificationType::valuetype_type(vmSymbols::java_lang____Value());
+}
+
 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);
 }
 
+TypeOrigin ClassVerifier::valuetype_ctx(const char* sig, TRAPS) {
+  VerificationType vt = VerificationType::valuetype_type(
+      create_temporary_symbol(sig, (int)strlen(sig), THREAD));
+  return TypeOrigin::implicit(vt);
+}
+
 void ClassVerifier::verify_class(TRAPS) {
   log_info(verification)("Verifying class %s with new format", _klass->external_name());
 
@@ -634,6 +650,12 @@
     return;
   }
 
+  // Verify value type bytecodes if enabled and class file version supports them.
+  // Commented check out for now until class file version 54.1 is generated.
+  bool vbytecodes_allowed = (EnableMVT || EnableValhalla);
+                             //_klass->major_version() >= Verifier::VALUETYPE_MAJOR_VERSION &&
+                             //_klass->minor_version() >= Verifier::VALUETYPE_MINOR_VERSION);
+
   // Initial stack map frame: offset is 0, stack is initially empty.
   StackMapFrame current_frame(max_locals, max_stack, this);
   // Set initial locals
@@ -841,6 +863,15 @@
           index = opcode - Bytecodes::_dload_0;
           verify_dload(index, &current_frame, CHECK_VERIFY(this));
           no_control_flow = false; break;
+        case Bytecodes::_vload :
+          if (!vbytecodes_allowed) {
+            class_format_error(
+              "vload not supported by this class file version (%d.%d), class %s",
+              _klass->major_version(), _klass->minor_version(), _klass->external_name());
+            return;
+          }
+          verify_vload(bcs.get_index(), &current_frame, CHECK_VERIFY(this));
+          no_control_flow = false; break;
         case Bytecodes::_aload :
           verify_aload(bcs.get_index(), &current_frame, CHECK_VERIFY(this));
           no_control_flow = false; break;
@@ -973,6 +1004,37 @@
           }
           no_control_flow = false; break;
         }
+        case Bytecodes::_vaload : {
+          if (!vbytecodes_allowed) {
+            class_format_error(
+              "vaload not supported by this class file version (%d.%d), class %s",
+              _klass->major_version(), _klass->minor_version(), _klass->external_name());
+            return;
+          }
+          type = current_frame.pop_stack(
+            VerificationType::integer_type(), CHECK_VERIFY(this));
+          atype = current_frame.pop_stack(
+            VerificationType::reference_check(), CHECK_VERIFY(this));
+          // The null check is strictly not be necessary, left in for future proofing.
+          // Will be reconsidered if type indexes are removed.
+          if (atype.is_null() || !atype.is_value_array()) {
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(),
+                TypeOrigin::implicit(VerificationType::reference_check())),
+                bad_type_msg, "vaload");
+            return;
+          }
+          VerificationType component = atype.get_component(this, CHECK_VERIFY(this));
+          if (!component.is_valuetype()) {
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(),
+                TypeOrigin::implicit(VerificationType::valuetype_check())),
+                bad_type_msg, "vaload");
+            return;  
+          } 
+          current_frame.push_stack(component, CHECK_VERIFY(this));
+          no_control_flow = false; break;
+        }
         case Bytecodes::_istore :
           verify_istore(bcs.get_index(), &current_frame, CHECK_VERIFY(this));
           no_control_flow = false; break;
@@ -1013,6 +1075,15 @@
           index = opcode - Bytecodes::_dstore_0;
           verify_dstore(index, &current_frame, CHECK_VERIFY(this));
           no_control_flow = false; break;
+        case Bytecodes::_vstore :
+          if (!vbytecodes_allowed) {
+            class_format_error(
+              "vstore not supported by this class file version (%d.%d), class %s",
+              _klass->major_version(), _klass->minor_version(), _klass->external_name());
+            return;
+          }
+          verify_vstore(bcs.get_index(), &current_frame, CHECK_VERIFY(this));
+          no_control_flow = false; break;
         case Bytecodes::_astore :
           verify_astore(bcs.get_index(), &current_frame, CHECK_VERIFY(this));
           no_control_flow = false; break;
@@ -1139,6 +1210,28 @@
           }
           // 4938384: relaxed constraint in JVMS 3nd edition.
           no_control_flow = false; break;
+        case Bytecodes::_vastore :
+          if (!vbytecodes_allowed) {
+            class_format_error(
+              "vastore not supported by this class file version (%d.%d), class %s",
+              _klass->major_version(), _klass->minor_version(), _klass->external_name());
+            return;
+          }
+          type = current_frame.pop_stack(__value_type(), CHECK_VERIFY(this));
+          type2 = current_frame.pop_stack(
+            VerificationType::integer_type(), CHECK_VERIFY(this));
+          atype = current_frame.pop_stack(
+            VerificationType::reference_check(), CHECK_VERIFY(this));
+          // The null check is strictly not be necessary, left in for future proofing.
+          // Will be reconsidered if type indexes are removed.
+          if (atype.is_null() || !atype.is_value_array()) {
+            verify_error(ErrorContext::bad_type(bci,
+                current_frame.stack_top_ctx(),
+                TypeOrigin::implicit(VerificationType::reference_check())),
+                bad_type_msg, "vastore");
+            return;
+          }
+          no_control_flow = false; break;
         case Bytecodes::_pop :
           current_frame.pop_stack(
             VerificationType::category1_check(), CHECK_VERIFY(this));
@@ -1590,6 +1683,18 @@
           verify_return_value(return_type, type, bci,
                               &current_frame, CHECK_VERIFY(this));
           no_control_flow = true; break;
+        case Bytecodes::_vreturn :
+          if (!vbytecodes_allowed) {
+            class_format_error(
+              "vreturn not supported by this class file version (%d.%d), class %s",
+              _klass->major_version(), _klass->minor_version(), _klass->external_name());
+            return;
+          }
+          type = current_frame.pop_stack(
+            VerificationType::valuetype_check(), 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(ErrorContext::bad_code(bci),
@@ -1618,6 +1723,15 @@
           verify_field_instructions(
             &bcs, &current_frame, cp, false, CHECK_VERIFY(this));
           no_control_flow = false; break;
+        case Bytecodes::_vwithfield :
+          if (!vbytecodes_allowed) {
+            class_format_error(
+              "vwithfield not supported by this class file version (%d.%d), class %s",
+              _klass->major_version(), _klass->minor_version(), _klass->external_name());
+            return;
+          }
+          verify_vwithfield(&bcs, &current_frame, cp, CHECK_VERIFY(this));
+          no_control_flow = false; break;
         case Bytecodes::_invokevirtual :
         case Bytecodes::_invokespecial :
         case Bytecodes::_invokestatic :
@@ -1636,7 +1750,7 @@
           index = bcs.get_index_u2();
           verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
           VerificationType new_class_type =
-            cp_index_to_type(index, cp, CHECK_VERIFY(this));
+            cp_index_to_reference_type(index, cp, CHECK_VERIFY(this));
           if (!new_class_type.is_object()) {
             verify_error(ErrorContext::bad_type(bci,
                 TypeOrigin::cp(index, new_class_type)),
@@ -1647,6 +1761,27 @@
           current_frame.push_stack(type, CHECK_VERIFY(this));
           no_control_flow = false; break;
         }
+        case Bytecodes::_vdefault :
+        {
+          if (!vbytecodes_allowed) {
+            class_format_error(
+              "vdefault not supported by this class file version (%d.%d), class %s",
+              _klass->major_version(), _klass->minor_version(), _klass->external_name());
+            return;
+          }
+          index = bcs.get_index_u2();
+          verify_cp_value_type(bci, index, cp, CHECK_VERIFY(this));
+          VerificationType new_value_type =
+            cp_index_to_valuetype(index, cp, CHECK_VERIFY(this));
+          if (!new_value_type.is_valuetype()) {
+            verify_error(ErrorContext::bad_type(bci,
+                TypeOrigin::cp(index, new_value_type)),
+                "Illegal vdefault instruction");
+            return;
+          }
+          current_frame.push_stack(new_value_type, CHECK_VERIFY(this));
+          no_control_flow = false; break;
+        }
         case Bytecodes::_newarray :
           type = get_newarray_type(bcs.get_index(), bci, CHECK_VERIFY(this));
           current_frame.pop_stack(
@@ -1673,7 +1808,7 @@
           index = bcs.get_index_u2();
           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(
+          VerificationType klass_type = cp_index_to_reference_type(
             index, cp, CHECK_VERIFY(this));
           current_frame.push_stack(klass_type, CHECK_VERIFY(this));
           no_control_flow = false; break;
@@ -1686,6 +1821,36 @@
             VerificationType::integer_type(), CHECK_VERIFY(this));
           no_control_flow = false; break;
         }
+        case Bytecodes::_vbox : {
+          if (!EnableMVT || !vbytecodes_allowed) {
+            class_format_error(
+              "vbox not supported by this class file version (%d.%d), class %s",
+              _klass->major_version(), _klass->minor_version(), _klass->external_name());
+            return;
+          }
+          index = bcs.get_index_u2();
+          verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
+          current_frame.pop_stack(VerificationType::valuetype_check(), CHECK_VERIFY(this));
+          VerificationType klass_type = cp_index_to_reference_type(
+            index, cp, CHECK_VERIFY(this));
+          current_frame.push_stack(klass_type, CHECK_VERIFY(this));
+          no_control_flow = false; break;
+        }
+        case Bytecodes::_vunbox : {
+          if (!EnableMVT || !vbytecodes_allowed) {
+            class_format_error(
+              "vunbox not supported by this class file version (%d.%d), class %s",
+              _klass->major_version(), _klass->minor_version(), _klass->external_name());
+            return;
+          }
+          index = bcs.get_index_u2();
+          verify_cp_value_type(bci, index, cp, CHECK_VERIFY(this));
+          current_frame.pop_stack(object_type(), CHECK_VERIFY(this));
+          VerificationType value_type = cp_index_to_valuetype(
+            index, cp, CHECK_VERIFY(this));
+          current_frame.push_stack(value_type, CHECK_VERIFY(this));
+          no_control_flow = false; break;
+        }
         case Bytecodes::_monitorenter :
         case Bytecodes::_monitorexit :
           current_frame.pop_stack(
@@ -1695,9 +1860,9 @@
         {
           index = bcs.get_index_u2();
           u2 dim = *(bcs.bcp()+3);
-          verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
+          verify_cp_class_or_value_type(bci, index, cp, CHECK_VERIFY(this));
           VerificationType new_array_type =
-            cp_index_to_type(index, cp, CHECK_VERIFY(this));
+            cp_index_to_reference_type(index, cp, CHECK_VERIFY(this));
           if (!new_array_type.is_array()) {
             verify_error(ErrorContext::bad_type(bci,
                 TypeOrigin::cp(index, new_array_type)),
@@ -1804,7 +1969,7 @@
     }
     int catch_type_index = exhandlers.catch_type_index(i);
     if (catch_type_index != 0) {
-      VerificationType catch_type = cp_index_to_type(
+      VerificationType catch_type = cp_index_to_reference_type(
         catch_type_index, cp, CHECK_VERIFY(this));
       VerificationType throwable =
         VerificationType::reference_type(vmSymbols::java_lang_Throwable());
@@ -1907,7 +2072,7 @@
       if (catch_type_index != 0) {
         if (was_recursively_verified()) return;
         // We know that this index refers to a subclass of Throwable
-        VerificationType catch_type = cp_index_to_type(
+        VerificationType catch_type = cp_index_to_reference_type(
           catch_type_index, cp, CHECK_VERIFY(this));
         new_frame->push_stack(catch_type, CHECK_VERIFY(this));
       } else {
@@ -1949,6 +2114,11 @@
 
   verify_cp_index(bci, cp, index, CHECK_VERIFY(this));
   unsigned int tag = cp->tag_at(index).value();
+
+  if (tag == JVM_CONSTANT_Value) {
+    tag = SAFE_JVM_CONSTANT_Value; //avoid overflow
+  }
+
   if ((types & (1 << tag)) == 0) {
     verify_error(ErrorContext::bad_cp_index(bci, index),
       "Illegal type at constant pool entry %d in class %s",
@@ -1969,6 +2139,32 @@
   }
 }
 
+void ClassVerifier::verify_cp_value_type(
+    u2 bci, int index, const constantPoolHandle& cp, TRAPS) {
+  verify_cp_index(bci, cp, index, CHECK_VERIFY(this));
+  constantTag tag = cp->tag_at(index);
+  if (!tag.is_value_type() && !tag.is_unresolved_value_type()) {
+    verify_error(ErrorContext::bad_cp_index(bci, index),
+        "Illegal type at constant pool entry %d in class %s",
+        index, cp->pool_holder()->external_name());
+    return;
+  }
+}
+
+// Used for MVT value type overloaded bytecodes (anewarray, getfield, multianewarray)
+void ClassVerifier::verify_cp_class_or_value_type(
+    u2 bci, int index, const 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() &&
+      !tag.is_value_type() && !tag.is_unresolved_value_type()) {
+    verify_error(ErrorContext::bad_cp_index(bci, index),
+        "Illegal type at constant pool entry %d in class %s",
+        index, cp->pool_holder()->external_name());
+    return;
+  }
+}
+
 void ClassVerifier::verify_error(ErrorContext ctx, const char* msg, ...) {
   stringStream ss;
 
@@ -2056,12 +2252,17 @@
   constantTag tag = cp->tag_at(index);
   unsigned int types;
   if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) {
-    if (!tag.is_unresolved_klass()) {
+    if (!tag.is_unresolved_klass() && !tag.is_unresolved_value_type()) {
       types = (1 << JVM_CONSTANT_Integer) | (1 << JVM_CONSTANT_Float)
-            | (1 << JVM_CONSTANT_String)  | (1 << JVM_CONSTANT_Class)
+            | (1 << JVM_CONSTANT_String) | (1 << JVM_CONSTANT_Class)
+            | (1 << SAFE_JVM_CONSTANT_Value)
             | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType);
       // Note:  The class file parser already verified the legality of
       // MethodHandle and MethodType constants.
+      // Note: SAFE_JVM_CONSTANT_Value is used instead of JVM_CONSTANT_Value
+      //       since JVM_CONSTANT_Value is an internally defined CP tag that is
+      //       defined with a large value.  When shifting left JVM_CONSTANT_Value
+      //       would overrun the width of types.
       verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this));
     }
   } else {
@@ -2075,7 +2276,8 @@
     current_frame->push_stack(
       VerificationType::reference_type(
         vmSymbols::java_lang_String()), CHECK_VERIFY(this));
-  } else if (tag.is_klass() || tag.is_unresolved_klass()) {
+  } else if (tag.is_klass() || tag.is_unresolved_klass() ||
+             tag.is_value_type() || tag.is_unresolved_value_type()) {
     current_frame->push_stack(
       VerificationType::reference_type(
         vmSymbols::java_lang_Class()), CHECK_VERIFY(this));
@@ -2211,17 +2413,34 @@
     return;
   }
 
-  // Get referenced class type
-  VerificationType ref_class_type = cp_ref_index_to_type(
-    index, cp, CHECK_VERIFY(this));
-  if (!ref_class_type.is_object() &&
-    (!allow_arrays || !ref_class_type.is_array())) {
-    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;
+  // Get referenced class or value type
+  constantTag field_class_tag = cp->tag_at(cp->klass_ref_index_at(index));
+  VerificationType ref_class_type;
+  
+  // getfield is overloaded to allow for either a reference or value type
+  if (bcs->raw_code() == Bytecodes::_getfield &&
+      (EnableMVT || EnableValhalla) &&
+      (field_class_tag.is_value_type() || field_class_tag.is_unresolved_value_type())) {
+    ref_class_type = cp_value_index_to_type(index, cp, CHECK_VERIFY(this));
+    if (!ref_class_type.is_valuetype()) {
+      verify_error(ErrorContext::bad_type(bcs->bci(),
+          TypeOrigin::cp(index, ref_class_type)),
+          "Expecting reference to value type in class %s at constant pool index %d",
+          _klass->external_name(), index);
+      return;
+    }
+  } else {
+    ref_class_type = cp_ref_index_to_type(index, cp, CHECK_VERIFY(this));
+    if (!ref_class_type.is_object() &&
+        (!allow_arrays || !ref_class_type.is_array())) {
+      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;
 
   assert(sizeof(VerificationType) == sizeof(uintptr_t),
@@ -2318,6 +2537,74 @@
   }
 }
 
+void ClassVerifier::verify_vwithfield(RawBytecodeStream* bcs,
+                                      StackMapFrame* current_frame,
+                                      const constantPoolHandle& cp,
+                                      TRAPS) {
+  u2 index = bcs->get_index_u2();
+  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);
+  Symbol* field_sig = cp->signature_ref_at(index);
+
+  if (!SignatureVerifier::is_valid_type_signature(field_sig)) {
+    class_format_error(
+      "Invalid signature for field in value type %s referenced "
+      "from constant pool index %d", _klass->external_name(), index);
+    return;
+  }
+
+  // Check referenced value type
+  VerificationType ref_value_type = cp_value_index_to_type(
+    index, cp, CHECK_VERIFY(this));
+  if (!ref_value_type.is_valuetype()) {
+    verify_error(ErrorContext::bad_type(bcs->bci(),
+        TypeOrigin::cp(index, ref_value_type)),
+        "Expecting reference to value type in class %s at constant pool index %d",
+        _klass->external_name(), index);
+    return;
+  }
+  VerificationType target_value_type = ref_value_type;
+
+  assert(sizeof(VerificationType) == sizeof(uintptr_t),
+        "buffer type must match VerificationType size");
+  uintptr_t field_type_buffer[2];
+  VerificationType* field_type = (VerificationType*)field_type_buffer;
+  // If we make a VerificationType[2] array directly, the compiler calls
+  // to the c-runtime library to do the allocation instead of just
+  // stack allocating it.  Plus it would run constructors.  This shows up
+  // in performance profiles.
+
+  SignatureStream sig_stream(field_sig, false);
+  int n = change_sig_to_verificationType(
+    &sig_stream, field_type, CHECK_VERIFY(this));
+  u2 bci = bcs->bci();
+
+  // The type of value2 must be compatible with the descriptor of the referenced field.
+  // n could be 2 if it is a double or long.
+  for (int i = n - 1; i >= 0; i--) {
+   current_frame->pop_stack(field_type[i], CHECK_VERIFY(this));
+  }
+
+  // The type of value1 must be the direct value class type appearing in the field reference.
+  VerificationType stack_object_type = current_frame->pop_stack(CHECK_VERIFY(this));
+
+  bool is_assignable = target_value_type.is_assignable_from(
+                         stack_object_type, this, false, CHECK_VERIFY(this));
+  if (!is_assignable) {
+    verify_error(ErrorContext::bad_type(bci,
+                 current_frame->stack_top_ctx(),
+                 TypeOrigin::cp(index, target_value_type)),
+                 "Bad type on operand stack in vwithfield");
+    return;
+  }
+
+  // The derived value class instance from another, modifying a field
+  current_frame->push_stack(stack_object_type, CHECK_VERIFY(this));
+}
+
 // Look at the method's handlers.  If the bci is in the handler's try block
 // then check if the handler_pc is already on the stack.  If not, push it
 // unless the handler has already been scanned.
@@ -2587,7 +2874,7 @@
     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(
+    VerificationType new_class_type = cp_index_to_reference_type(
       new_class_index, cp, CHECK_VERIFY(this));
     if (!new_class_type.equals(ref_class_type)) {
       verify_error(ErrorContext::bad_type(bci,
@@ -2695,7 +2982,7 @@
     return;
   }
 
-  // Get referenced class type
+  // Get referenced class or value type
   VerificationType ref_class_type;
   if (opcode == Bytecodes::_invokedynamic) {
     if (_klass->major_version() < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
@@ -2705,7 +2992,14 @@
       return;
     }
   } else {
-    ref_class_type = cp_ref_index_to_type(index, cp, CHECK_VERIFY(this));
+    constantTag method_class_tag = cp->tag_at(cp->klass_ref_index_at(index));
+    if (EnableValhalla &&
+        opcode == Bytecodes::_invokevirtual &&
+        (method_class_tag.is_value_type() || method_class_tag.is_unresolved_value_type())) {
+      ref_class_type = cp_value_index_to_type(index, cp, CHECK_VERIFY(this));
+    } else {
+      ref_class_type = cp_ref_index_to_type(index, cp, CHECK_VERIFY(this));
+    }
   }
 
   // For a small signature length, we just allocate 128 bytes instead
@@ -2930,13 +3224,18 @@
 void ClassVerifier::verify_anewarray(
     u2 bci, u2 index, const constantPoolHandle& cp,
     StackMapFrame* current_frame, TRAPS) {
-  verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
+  verify_cp_class_or_value_type(bci, index, cp, CHECK_VERIFY(this));
   current_frame->pop_stack(
     VerificationType::integer_type(), CHECK_VERIFY(this));
 
   if (was_recursively_verified()) return;
-  VerificationType component_type =
-    cp_index_to_type(index, cp, CHECK_VERIFY(this));
+  constantTag class_tag = cp->tag_at(index);
+  VerificationType component_type;
+  if (class_tag.is_value_type() || class_tag.is_unresolved_value_type()) {
+    component_type = cp_index_to_valuetype(index, cp, CHECK_VERIFY(this));
+  } else {
+    component_type = cp_index_to_reference_type(index, cp, CHECK_VERIFY(this));
+  }
   int length;
   char* arr_sig_str;
   if (component_type.is_array()) {     // it's an array
@@ -2955,11 +3254,11 @@
     strncpy(&arr_sig_str[1], component_name, length - 1);
   } else {         // it's an object or interface
     const char* component_name = component_type.name()->as_utf8();
-    // add one dimension to component with 'L' prepended and ';' postpended.
+    // add one dimension to component with 'L' or 'Q' (value type) prepended and ';' appended.
     length = (int)strlen(component_name) + 3;
     arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length);
     arr_sig_str[0] = '[';
-    arr_sig_str[1] = 'L';
+    arr_sig_str[1] = component_type.is_reference() ? 'L' : 'Q';
     strncpy(&arr_sig_str[2], component_name, length - 2);
     arr_sig_str[length - 1] = ';';
   }
@@ -3007,6 +3306,12 @@
   current_frame->push_stack(type, CHECK_VERIFY(this));
 }
 
+void ClassVerifier::verify_vload(u2 index, StackMapFrame* current_frame, TRAPS) {
+  VerificationType type = current_frame->get_local(
+    index, VerificationType::valuetype_check(), CHECK_VERIFY(this));
+  current_frame->push_stack(type, CHECK_VERIFY(this));
+}
+
 void ClassVerifier::verify_istore(u2 index, StackMapFrame* current_frame, TRAPS) {
   current_frame->pop_stack(
     VerificationType::integer_type(), CHECK_VERIFY(this));
@@ -3044,6 +3349,12 @@
   current_frame->set_local(index, type, CHECK_VERIFY(this));
 }
 
+void ClassVerifier::verify_vstore(u2 index, StackMapFrame* current_frame, TRAPS) {
+  VerificationType type = current_frame->pop_stack(
+    VerificationType::valuetype_check(), CHECK_VERIFY(this));
+  current_frame->set_local(index, type, CHECK_VERIFY(this));
+}
+
 void ClassVerifier::verify_iinc(u2 index, StackMapFrame* current_frame, TRAPS) {
   VerificationType type = current_frame->get_local(
     index, VerificationType::integer_type(), CHECK_VERIFY(this));
--- a/src/share/vm/classfile/verifier.hpp	Wed Aug 30 14:50:03 2017 -0400
+++ b/src/share/vm/classfile/verifier.hpp	Thu Sep 07 13:52:56 2017 -0400
@@ -33,6 +33,10 @@
 #include "utilities/exceptions.hpp"
 #include "utilities/growableArray.hpp"
 
+// For bit tests involving JVM_CONSTANT_Value during verification,
+// define a "safe" number to avoid integer overflow of types
+#define SAFE_JVM_CONSTANT_Value JVM_CONSTANT_ExternalMax
+
 // The verifier class
 class Verifier : AllStatic {
  public:
@@ -40,7 +44,9 @@
     STRICTER_ACCESS_CTRL_CHECK_VERSION  = 49,
     STACKMAP_ATTRIBUTE_MAJOR_VERSION    = 50,
     INVOKEDYNAMIC_MAJOR_VERSION         = 51,
-    NO_RELAX_ACCESS_CTRL_CHECK_VERSION  = 52
+    NO_RELAX_ACCESS_CTRL_CHECK_VERSION  = 52,
+    VALUETYPE_MAJOR_VERSION             = 53,
+    VALUETYPE_MINOR_VERSION             =  1
   };
   typedef enum { ThrowException, NoException } Mode;
 
@@ -271,7 +277,12 @@
 
   VerificationType cp_ref_index_to_type(
       int index, const constantPoolHandle& cp, TRAPS) {
-    return cp_index_to_type(cp->klass_ref_index_at(index), cp, THREAD);
+    return cp_index_to_reference_type(cp->klass_ref_index_at(index), cp, THREAD);
+  }
+
+  VerificationType cp_value_index_to_type(
+      int index, const constantPoolHandle& cp, TRAPS) {
+    return cp_index_to_valuetype(cp->klass_ref_index_at(index), cp, THREAD);
   }
 
   bool is_protected_access(
@@ -282,6 +293,8 @@
   void verify_cp_type(u2 bci, int index, const constantPoolHandle& cp,
       unsigned int types, TRAPS);
   void verify_cp_class_type(u2 bci, int index, const constantPoolHandle& cp, TRAPS);
+  void verify_cp_value_type(u2 bci, int index, const constantPoolHandle& cp, TRAPS);
+  void verify_cp_class_or_value_type(u2 bci, int index, const constantPoolHandle& cp, TRAPS);
 
   u2 verify_stackmap_table(
     u2 stackmap_index, u2 bci, StackMapFrame* current_frame,
@@ -303,6 +316,10 @@
     RawBytecodeStream* bcs, StackMapFrame* current_frame,
     const constantPoolHandle& cp, bool allow_arrays, TRAPS);
 
+  void verify_vwithfield(
+    RawBytecodeStream* bcs, StackMapFrame* current_frame,
+    const constantPoolHandle& cp, TRAPS);
+
   void verify_invoke_init(
     RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
     StackMapFrame* current_frame, u4 code_length, bool in_try_block,
@@ -337,16 +354,19 @@
   void verify_fload (u2 index, StackMapFrame* current_frame, TRAPS);
   void verify_dload (u2 index, StackMapFrame* current_frame, TRAPS);
   void verify_aload (u2 index, StackMapFrame* current_frame, TRAPS);
+  void verify_vload (u2 index, StackMapFrame* current_frame, TRAPS);
   void verify_istore(u2 index, StackMapFrame* current_frame, TRAPS);
   void verify_lstore(u2 index, StackMapFrame* current_frame, TRAPS);
   void verify_fstore(u2 index, StackMapFrame* current_frame, TRAPS);
   void verify_dstore(u2 index, StackMapFrame* current_frame, TRAPS);
   void verify_astore(u2 index, StackMapFrame* current_frame, TRAPS);
+  void verify_vstore(u2 index, StackMapFrame* current_frame, TRAPS);
   void verify_iinc  (u2 index, StackMapFrame* current_frame, TRAPS);
 
   bool name_in_supers(Symbol* ref_name, InstanceKlass* current);
 
   VerificationType object_type() const;
+  VerificationType __value_type() const;
 
   InstanceKlass*      _klass;  // the class being verified
   methodHandle        _method; // current method being verified
@@ -407,10 +427,14 @@
   int change_sig_to_verificationType(
     SignatureStream* sig_type, VerificationType* inference_type, TRAPS);
 
-  VerificationType cp_index_to_type(int index, const constantPoolHandle& cp, TRAPS) {
+  VerificationType cp_index_to_reference_type(int index, const constantPoolHandle& cp, TRAPS) {
     return VerificationType::reference_type(cp->klass_name_at(index));
   }
 
+  VerificationType cp_index_to_valuetype(int index, const constantPoolHandle& cp, TRAPS) {
+    return VerificationType::valuetype_type(cp->klass_name_at(index));
+  }
+
   // Keep a list of temporary symbols created during verification because
   // their reference counts need to be decremented when the verifier object
   // goes out of scope.  Since these symbols escape the scope in which they're
@@ -427,6 +451,7 @@
   }
 
   TypeOrigin ref_ctx(const char* str, TRAPS);
+  TypeOrigin valuetype_ctx(const char* str, TRAPS);
 
 };
 
@@ -436,13 +461,14 @@
   switch (bt) {
     case T_OBJECT:
     case T_ARRAY:
+    case T_VALUETYPE:
       {
         Symbol* name = sig_type->as_symbol(CHECK_0);
         // Create another symbol to save as signature stream unreferences this symbol.
         Symbol* name_copy = create_temporary_symbol(name);
         assert(name_copy == name, "symbols don't match");
-        *inference_type =
-          VerificationType::reference_type(name_copy);
+        *inference_type = ((bt == T_VALUETYPE) ? VerificationType::valuetype_type(name_copy) :
+                                                 VerificationType::reference_type(name_copy));
         return 1;
       }
     case T_LONG:
--- a/test/runtime/valhalla/valuetypes/DeriveValueTypeCreation.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/DeriveValueTypeCreation.java	Thu Sep 07 13:52:56 2017 -0400
@@ -43,8 +43,8 @@
  * @library /test/lib
  * @modules java.base/jdk.internal.org.objectweb.asm
  * @build runtime.valhalla.valuetypes.ValueCapableClass
- * @run main/othervm -Xint -noverify -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation
- * @run main/othervm -Xcomp -noverify -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation
+ * @run main/othervm -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation
+ * @run main/othervm -Xcomp -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation
  */
 public class DeriveValueTypeCreation {
 
--- a/test/runtime/valhalla/valuetypes/MVTComboDebugTier1.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/MVTComboDebugTier1.java	Thu Sep 07 13:52:56 2017 -0400
@@ -36,8 +36,8 @@
  *          jdk.compiler/com.sun.tools.javac.util
  * @compile MVTCombo.java
  * @build jdk.test.lib.combo.ComboTestHelper
- * @run main/othervm -noverify -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 3
- * @run main/othervm -noverify -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 -reducetypes 6
+ * @run main/othervm -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 3
+ * @run main/othervm -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 -reducetypes 6
  */
 public class MVTComboDebugTier1 {
 
--- a/test/runtime/valhalla/valuetypes/MVTComboTier1.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/MVTComboTier1.java	Thu Sep 07 13:52:56 2017 -0400
@@ -36,9 +36,9 @@
  *          jdk.compiler/com.sun.tools.javac.util
  * @compile MVTCombo.java
  * @build jdk.test.lib.combo.ComboTestHelper
- * @run main/othervm -noverify -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 3
- * @run main/othervm -noverify -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 -reducetypes 6
- * @run main/othervm -noverify -Xcomp -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 -reducetypes 5
+ * @run main/othervm -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 3
+ * @run main/othervm -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 -reducetypes 6
+ * @run main/othervm -Xcomp -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 -reducetypes 5
  */
 public class MVTComboTier1 {
 
--- a/test/runtime/valhalla/valuetypes/UninitializedValueFieldsTest.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/UninitializedValueFieldsTest.java	Thu Sep 07 13:52:56 2017 -0400
@@ -7,8 +7,8 @@
  * @summary Uninitialized value fields test
  * @library /test/lib
  * @compile -XDenableValueTypes Point.java UninitializedValueFieldsTest.java
- * @run main/othervm -noverify -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.UninitializedValueFieldsTest
- * @run main/othervm -noverify -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.UninitializedValueFieldsTest
+ * @run main/othervm -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.UninitializedValueFieldsTest
+ * @run main/othervm -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.UninitializedValueFieldsTest
  */
 public class UninitializedValueFieldsTest {
 
--- a/test/runtime/valhalla/valuetypes/VDefaultTest.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/VDefaultTest.java	Thu Sep 07 13:52:56 2017 -0400
@@ -30,8 +30,8 @@
  * @summary vdefault bytecode test
  * @library /test/lib
  * @compile -XDenableValueTypes Point.java VDefaultTest.java
- * @run main/othervm -noverify -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.VDefaultTest
- * @run main/othervm -noverify -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.VDefaultTest
+ * @run main/othervm -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.VDefaultTest
+ * @run main/othervm -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.VDefaultTest
  */
 
 public class VDefaultTest {
--- a/test/runtime/valhalla/valuetypes/VTBufferTest.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/VTBufferTest.java	Thu Sep 07 13:52:56 2017 -0400
@@ -26,9 +26,9 @@
  * @summary Value Type interpreter value buffering test
  * @library /test/lib
  * @build ValueTypeGenerator
- * @run main/othervm -noverify -Xint -XX:+EnableValhalla VTBufferTest generate-and-run
- * @run main/othervm -noverify -Xint -XX:+EnableValhalla -XX:ValueTypesBufferMaxMemory=0 VTBufferTest generate-and-run
- * @run main/othervm -noverify -Xint -XX:+EnableValhalla -XX:BigValueTypeThreshold=196 VTBufferTest generate-and-run
+ * @run main/othervm -Xint -XX:+EnableValhalla VTBufferTest generate-and-run
+ * @run main/othervm -Xint -XX:+EnableValhalla -XX:ValueTypesBufferMaxMemory=0 VTBufferTest generate-and-run
+ * @run main/othervm -Xint -XX:+EnableValhalla -XX:BigValueTypeThreshold=196 VTBufferTest generate-and-run
  */
 
 /* This test generates its source code.
--- a/test/runtime/valhalla/valuetypes/VWithFieldTest.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/VWithFieldTest.java	Thu Sep 07 13:52:56 2017 -0400
@@ -30,8 +30,8 @@
  * @summary vwithfield bytecode test
  * @library /test/lib
  * @compile -XDenableValueTypes Point.java VWithFieldTest.java
- * @run main/othervm -noverify -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.VWithFieldTest
- * @run main/othervm -noverify -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.VWithFieldTest
+ * @run main/othervm -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.VWithFieldTest
+ * @run main/othervm -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.VWithFieldTest
  */
 
 public class VWithFieldTest {
--- a/test/runtime/valhalla/valuetypes/ValueOops.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/ValueOops.java	Thu Sep 07 13:52:56 2017 -0400
@@ -42,33 +42,37 @@
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xint -noverify -XX:+UseSerialGC -Xmx128m -XX:+EnableMVT
+ * @run main/othervm -Xint -noverify -XX:+UseSerialGC -Xmx128m -XX:+EnableMVT -XX:+EnableValhalla
  *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   runtime.valhalla.valuetypes.ValueOops
- * @run main/othervm -Xint -noverify -XX:+UseG1GC -Xmx128m -XX:+EnableMVT
+ * @run main/othervm -Xint -noverify -XX:+UseG1GC -Xmx128m -XX:+EnableMVT -XX:+EnableValhalla
  *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   runtime.valhalla.valuetypes.ValueOops
- * @run main/othervm -Xint -noverify -XX:+UseParallelGC -Xmx128m -XX:+EnableMVT
+ * @run main/othervm -Xint -noverify -XX:+UseParallelGC -Xmx128m -XX:+EnableMVT -XX:+EnableValhalla
  *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   runtime.valhalla.valuetypes.ValueOops
- * @run main/othervm -Xint -noverify -XX:+UseConcMarkSweepGC -Xmx128m -XX:+EnableMVT
+ * @run main/othervm -Xint -noverify -XX:+UseConcMarkSweepGC -Xmx128m -XX:+EnableMVT -XX:+EnableValhalla
  *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   runtime.valhalla.valuetypes.ValueOops
- * @run main/othervm -Xcomp -noverify -XX:+UseSerialGC -Xmx128m -XX:+EnableMVT
+ * @run main/othervm -Xcomp -noverify -XX:+UseSerialGC -Xmx128m -XX:+EnableMVT -XX:+EnableValhalla
  *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   runtime.valhalla.valuetypes.ValueOops
- * @run main/othervm -Xcomp -noverify -XX:+UseG1GC -Xmx128m -XX:+EnableMVT
+ * @run main/othervm -Xcomp -noverify -XX:+UseG1GC -Xmx128m -XX:+EnableMVT -XX:+EnableValhalla
  *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   runtime.valhalla.valuetypes.ValueOops
- * @run main/othervm -Xcomp -noverify -XX:+UseParallelGC -Xmx128m -XX:+EnableMVT
+ * @run main/othervm -Xcomp -noverify -XX:+UseParallelGC -Xmx128m -XX:+EnableMVT -XX:+EnableValhalla
  *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   runtime.valhalla.valuetypes.ValueOops
- * @run main/othervm -Xcomp -noverify -XX:+UseConcMarkSweepGC -Xmx128m -XX:+EnableMVT
+ * @run main/othervm -Xcomp -noverify -XX:+UseConcMarkSweepGC -Xmx128m -XX:+EnableMVT -XX:+EnableValhalla
  *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   runtime.valhalla.valuetypes.ValueOops
  */
 public class ValueOops {
 
+    // Note: -noverify can not be eliminated. Possible issue with ValueType::mhName(),
+    //       does not translate '.' to '/' for JVM.
+    //       java.lang.ClassFormatError: Illegal method name "runtime.valhalla.valuetypes.PersonVcc_default"
+    //
     // Extra debug: -XX:+VerifyOops -XX:+VerifyStack -XX:+VerifyLastFrame -XX:+VerifyBeforeGC -XX:+VerifyAfterGC -XX:+VerifyDuringGC -XX:VerifySubSet=threads,heap
     // Even more debugging: -XX:+TraceNewOopMapGeneration -Xlog:gc*=info
 
--- a/test/runtime/valhalla/valuetypes/ValueTypeArray.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/ValueTypeArray.java	Thu Sep 07 13:52:56 2017 -0400
@@ -32,10 +32,10 @@
  * @summary Plain array test for Value Types
  * @library /test/lib
  * @compile -XDenableValueTypes ValueTypeArray.java Point.java Long8Value.java Person.java
- * @run main/othervm -noverify -Xint -XX:+ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray
- * @run main/othervm -noverify -Xint -XX:-ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray
- * @run main/othervm -noverify -Xcomp -XX:+ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray
- * @run main/othervm -noverify -Xcomp -XX:-ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray
+ * @run main/othervm -Xint -XX:+ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray
+ * @run main/othervm -Xint -XX:-ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray
+ * @run main/othervm -Xcomp -XX:+ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray
+ * @run main/othervm -Xcomp -XX:-ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray
  */
 public class ValueTypeArray {
     public static void main(String[] args) {
--- a/test/runtime/valhalla/valuetypes/ValueTypeCreation.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/ValueTypeCreation.java	Thu Sep 07 13:52:56 2017 -0400
@@ -7,8 +7,8 @@
  * @summary Value Type creation test
  * @library /test/lib
  * @compile  -XDenableValueTypes ValueTypeCreation.java Point.java Long8Value.java Person.java
- * @run main/othervm -noverify -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeCreation
- * @run main/othervm -noverify -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeCreation
+ * @run main/othervm -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeCreation
+ * @run main/othervm -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeCreation
  */
 public class ValueTypeCreation {
     public static void main(String[] args) {
--- a/test/runtime/valhalla/valuetypes/ValueTypeDensity.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/ValueTypeDensity.java	Thu Sep 07 13:52:56 2017 -0400
@@ -33,10 +33,10 @@
  * @library /test/lib
  * @compile -XDenableValueTypes ValueTypeDensity.java
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * @run main/othervm -noverify -Xint -XX:+EnableValhalla -XX:+ValueArrayFlatten
+ * @run main/othervm -Xint -XX:+EnableValhalla -XX:+ValueArrayFlatten
  *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                    -XX:+WhiteBoxAPI ValueTypeDensity
- * @run main/othervm -noverify -Xcomp -XX:+EnableValhalla -XX:+ValueArrayFlatten
+ * @run main/othervm -Xcomp -XX:+EnableValhalla -XX:+ValueArrayFlatten
  *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI ValueTypeDensity
  */
--- a/test/runtime/valhalla/valuetypes/ValueTypeGetField.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/ValueTypeGetField.java	Thu Sep 07 13:52:56 2017 -0400
@@ -7,8 +7,8 @@
  * @summary Value Type get field test
  * @library /test/lib
  * @compile -XDenableValueTypes Point.java ValueTypeGetField.java
- * @run main/othervm -noverify -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeGetField
- * @run main/othervm -noverify -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeGetField
+ * @run main/othervm -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeGetField
+ * @run main/othervm -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeGetField
  */
 public class ValueTypeGetField {
 
--- a/test/runtime/valhalla/valuetypes/VboxUnbox.java	Wed Aug 30 14:50:03 2017 -0400
+++ b/test/runtime/valhalla/valuetypes/VboxUnbox.java	Thu Sep 07 13:52:56 2017 -0400
@@ -78,6 +78,9 @@
         catch (ClassCastException cce) {}
         catch (Throwable t) { fail("Invokation Exception", t); }
 
+        // With -verify, this test will yield a VerifyError
+        // since the constant pool entry at the index is not a
+        // symbolic reference to a direct value class type.
         MethodHandle unbox = unboxMh(vcc, String.class); // Illegal unbox type
         try {
             unbox.invoke(ValueCapableClass.create());
@@ -90,8 +93,6 @@
     /*
        Create new DVT via loading a value array element. Why this workaround:
        1) to avoid "ValueType.defaultValueConstant()" which may or may not be implemented with vunbox
-       2) vnew requires valuefactory attribute, which at the time of writing isn't generated with the DVT
-       3) vdefault doesn't exist at the time of writing
     */
     public static MethodHandle newDvtMh(Class<?> dvt) {
         return MethodHandleBuilder.loadCode(MethodHandles.lookup(), "newDvt", MethodType.methodType(dvt), CODE->{
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/valhalla/valuetypes/verifier/ValueCapableClass.java	Thu Sep 07 13:52:56 2017 -0400
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+package runtime.valhalla.valuetypes.verifier;
+
+@jvm.internal.value.ValueCapableClass
+public final class ValueCapableClass {
+
+    public static final int DEFAULT_X = 11;
+    public static final short DEFAULT_Y = 13;
+    public static final short DEFAULT_Z = 15;
+    public static final String STATIC_FIELD = "Should be left alone";
+
+    public final int   x;
+    public final short y;
+    public final short z;
+
+    private ValueCapableClass() {
+        this(DEFAULT_X, DEFAULT_Y, DEFAULT_Z);
+    }
+
+    private ValueCapableClass(int x, short y, short z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public short getY() {
+        return y;
+    }
+
+    public short getZ() {
+        return z;
+    }
+
+    public String toString() {
+        int ax = getX();
+        short ay = getY();
+        short az = getZ();
+        return "ValueCapableClass x=" + ax + " y=" + ay + " z=" + az;
+    }
+
+    public static ValueCapableClass create(int x, short y, short z) {
+        return new ValueCapableClass(x, y, z);
+    }
+
+    public static ValueCapableClass create() {
+        return new ValueCapableClass();
+    }
+
+    public static void test() {
+        ValueCapableClass value = create(4711, (short)7, (short)11);
+        String s = value.toString();
+        if ((value.getX() != 4711) || (value.getY() != 7) || value.getZ() != 11) {
+            throw new IllegalStateException("Bad value: " + s);
+        }
+        System.out.println(s);
+        ValueCapableClass defaultValue = create();
+        s = defaultValue.toString();
+        if ((defaultValue.getX() != DEFAULT_X) ||
+            (defaultValue.getY() != DEFAULT_Y) ||
+            (defaultValue.getZ() != DEFAULT_Z)) {
+            throw new IllegalStateException("Bad value: " + s);
+        }
+
+        if (!STATIC_FIELD.equals("Should be left alone")) {
+            throw new IllegalStateException("Bad static field: " + STATIC_FIELD);
+        }
+    }
+
+    public static void main(String[] args) {
+        test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/valhalla/valuetypes/verifier/VloadTest.java	Thu Sep 07 13:52:56 2017 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+package runtime.valhalla.valuetypes.verifier;
+
+import java.lang.invoke.*;
+import java.lang.ref.*;
+import java.util.concurrent.*;
+import jdk.experimental.value.*;
+import sun.hotspot.WhiteBox;
+
+/**
+ * @test VloadTest
+ * @summary Test vload opcode
+ * @library /test/lib
+ * @compile -XDenableValueTypes VloadTest.java
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *                                sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xint -XX:+UseG1GC -Xmx128m -XX:+EnableMVT
+ *                   -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   runtime.valhalla.valuetypes.verifier.VloadTest
+ */
+public class VloadTest {
+
+    public static void main(String[] args) throws Throwable{
+        testBytecodes();
+    }
+
+    // Test that vload cannot load an integer.
+    public static void testBytecodes() throws Throwable {
+        try {
+            MethodHandles.Lookup lookup = MethodHandles.lookup();
+
+            Object array = MethodHandleBuilder.loadCode(
+                lookup,
+                "vloadAnInteger",
+                MethodType.methodType(Object.class, Integer.TYPE),
+                CODE->{
+                CODE
+                .vload(0)      // Attempt to vload an Integer
+                .aconst_null()
+                .areturn();
+            }).invoke(1000);
+        } catch (Throwable t) {
+            if (!t.getMessage().contains("java.lang.VerifyError: Bad local variable type")) {
+                throw t;
+            } else {
+                System.out.println("Successful detection of vload verification error");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/valhalla/valuetypes/verifier/VunboxErrorIndex.java	Thu Sep 07 13:52:56 2017 -0400
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+package runtime.valhalla.valuetypes.verifier;
+
+import java.lang.invoke.*;
+import jdk.experimental.value.*;
+
+import static jdk.test.lib.Asserts.*;
+
+/*
+ * @test VunboxErrorIndex
+ * @summary Exercise the verifier for vunbox bytecode with a non-value type CP index.
+ * @library /test/lib
+ * @build runtime.valhalla.valuetypes.verifier.ValueCapableClass
+ * @run main/othervm -Xint -verify -XX:+EnableMVT runtime.valhalla.valuetypes.verifier.VunboxErrorIndex
+ */
+public class VunboxErrorIndex {
+
+    public static void main(String[] args) {
+        testCorrectBoxing();
+        testIncorrectBoxing();
+    }
+
+    public static void testCorrectBoxing() {
+        Class<?> vcc = ValueCapableClass.class;
+        Class<?> dvt = ValueType.forClass(vcc).valueClass();
+
+        MethodHandle newDvt = newDvtMh(dvt);
+        MethodHandle box = boxMh(dvt, vcc);
+        MethodHandle unbox = unboxMh(vcc, dvt);
+
+        ValueCapableClass newObject = ValueCapableClass.create(3, (short)7, (short)11);
+        ValueCapableClass newBoxed = null;
+
+        try {
+            ValueCapableClass boxed = (ValueCapableClass) MethodHandles.filterReturnValue(newDvt, box).invokeExact();
+            // Assuming MVT1.0, where source has no way of holding an actual value at the language level, so: box(unbox(Object))
+            newBoxed = (ValueCapableClass) MethodHandles.filterReturnValue(unbox, box).invokeExact(newObject);
+        }
+        catch (Throwable t) { fail("Invokation Exception", t); }
+
+        assertTrue(newObject.getX() == newBoxed.getX());
+        assertTrue(newObject.getY() == newBoxed.getY());
+        assertTrue(newObject.getZ() == newBoxed.getZ());
+    }
+
+    public static void testIncorrectBoxing() {
+        Class<?> vcc = ValueCapableClass.class;
+        Class<?> dvt = ValueType.forClass(vcc).valueClass();
+
+        MethodHandle newDvt = newDvtMh(dvt);
+        MethodHandle box = boxMh(dvt, String.class); // Illegal box type
+        try {
+            MethodHandles.filterReturnValue(newDvt, box).invoke();
+            fail("Expected ClassCastException");
+        }
+        catch (ClassCastException cce) {}
+        catch (Throwable t) { fail("Invokation Exception", t); }
+
+        // With -verify, this test will yield a VerifyError
+        // since the constant pool entry at the index is not a
+        // symbolic reference to a direct value class type.
+        try {
+            MethodHandle unbox = unboxMh(vcc, String.class); // Illegal unbox type
+            unbox.invoke(ValueCapableClass.create());
+            fail("Expected VerifyError");
+        }
+        catch (Throwable t) {
+            if (!t.getMessage().contains("java.lang.VerifyError")) {
+                fail("Invokation Exception", t);
+            }
+        }
+    }
+
+    /*
+       Create new DVT via loading a value array element. Why this workaround:
+       1) to avoid "ValueType.defaultValueConstant()" which may or may not be implemented with vunbox
+    */
+    public static MethodHandle newDvtMh(Class<?> dvt) {
+        return MethodHandleBuilder.loadCode(MethodHandles.lookup(), "newDvt", MethodType.methodType(dvt), CODE->{
+                CODE.iconst_1().anewarray(dvt).iconst_0().vaload().vreturn();
+            });
+    }
+
+    public static MethodHandle boxMh(Class<?> inClass, Class<?> outClass) {
+        return MethodHandleBuilder.loadCode(MethodHandles.lookup(), "box", MethodType.methodType(outClass, inClass), CODE->{
+                CODE.vload(0).vbox(outClass).areturn();
+            });
+    }
+
+    public static MethodHandle unboxMh(Class<?> inClass, Class<?> outClass)  {
+        return MethodHandleBuilder.loadCode(MethodHandles.lookup(), "box", MethodType.methodType(outClass, inClass), CODE->{
+                CODE.aload(0).vunbox(outClass).vreturn();
+            });
+    }
+
+}