diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp
index f9436f67667..c74dcd154f9 100644
--- a/src/hotspot/share/opto/graphKit.cpp
+++ b/src/hotspot/share/opto/graphKit.cpp
@@ -2931,7 +2931,7 @@ Node* GraphKit::gen_subtype_check(Node* obj_or_subklass, Node* superklass) {
     MergeMemNode* mem = merged_memory();
     Node* ctrl = control();
     Node* subklass = obj_or_subklass;
-    if (!sub_t->isa_klassptr()) {
+    if (!sub_t->isa_klassptr() && !sub_t->isa_inlinetype()) {
       subklass = load_object_klass(obj_or_subklass);
     }
     Node* n = Phase::gen_subtype_check(subklass, superklass, &ctrl, mem, _gvn);
diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp
index 60714423ef0..c7245dea52e 100644
--- a/src/hotspot/share/opto/memnode.cpp
+++ b/src/hotspot/share/opto/memnode.cpp
@@ -2391,7 +2391,7 @@ const Type* LoadNode::klass_value_common(PhaseGVN* phase) const {
             return TypeKlassPtr::make(ak);
           }
         }
-        return TypeKlassPtr::make(TypePtr::NotNull, ak, Type::Offset(0));
+        return TypeKlassPtr::make(TypePtr::NotNull, ak, Type::Offset(0), false, tary->is_not_flat(), tary->is_not_null_free());
       } else if (ak->is_type_array_klass()) {
         return TypeKlassPtr::make(ak); // These are always precise
       }
diff --git a/src/hotspot/share/opto/parseHelper.cpp b/src/hotspot/share/opto/parseHelper.cpp
index 21e3db60033..fd842c9b619 100644
--- a/src/hotspot/share/opto/parseHelper.cpp
+++ b/src/hotspot/share/opto/parseHelper.cpp
@@ -219,20 +219,18 @@ Node* Parse::array_store_check() {
       reason = Deoptimization::Reason_array_check;
     }
     if (extak != NULL) {
-      always_see_exact_class = true;
       Node* con = makecon(extak);
-      Node* cmp = _gvn.transform(new CmpPNode( array_klass, con ));
-      Node* bol = _gvn.transform(new BoolNode( cmp, BoolTest::eq ));
-      Node* ctrl= control();
-      { BuildCutout unless(this, bol, PROB_MAX);
-        uncommon_trap(reason,
-                      Deoptimization::Action_maybe_recompile,
-                      tak->klass());
-      }
-      if (stopped()) {          // MUST uncommon-trap?
-        set_control(ctrl);      // Then Don't Do It, just fall into the normal checking
-      } else {                  // Cast array klass to exactness:
-        // Use the exact constant value we know it is.
+      Node* cmp = _gvn.transform(new CmpPNode(array_klass, con));
+      Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
+      // Only do it if the check does not always pass/fail
+      if (!bol->is_Con()) {
+        always_see_exact_class = true;
+        { BuildCutout unless(this, bol, PROB_MAX);
+          uncommon_trap(reason,
+                        Deoptimization::Action_maybe_recompile,
+                        tak->klass());
+        }
+        // Cast array klass to exactness
         replace_in_map(array_klass,con);
         Node* cast = _gvn.transform(new CheckCastPPNode(control(), ary, extak->as_instance_type()));
         replace_in_map(ary, cast);
@@ -242,7 +240,8 @@ Node* Parse::array_store_check() {
           log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'",
                     log->identify(tak->klass()));
         }
-        array_klass = con;      // Use cast value moving forward
+        // Use cast value moving forward
+        array_klass = con;
       }
     }
   }
diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp
index bfdf9a536fc..255ce81dbe2 100644
--- a/src/hotspot/share/opto/subnode.cpp
+++ b/src/hotspot/share/opto/subnode.cpp
@@ -977,6 +977,14 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const {
             (r1->flatten_array() && (!r0->can_be_inline_type() || (klass0->is_inlinetype() && !klass0->flatten_array())))) {
           // One type is flattened in arrays but the other type is not. Must be unrelated.
           unrelated_classes = true;
+        } else if ((r0->is_not_flat() && klass1->is_flat_array_klass()) ||
+                   (r1->is_not_flat() && klass0->is_flat_array_klass())) {
+          // One type is a non-flattened array and the other type is a flattened array. Must be unrelated.
+          unrelated_classes = true;
+        } else if ((r0->is_not_null_free() && klass1->is_obj_array_klass() && klass1->as_obj_array_klass()->element_klass()->is_inlinetype()) ||
+                   (r1->is_not_null_free() && klass0->is_obj_array_klass() && klass0->as_obj_array_klass()->element_klass()->is_inlinetype())) {
+          // One type is a non-null-free array and the other type is a null-free array. Must be unrelated.
+          unrelated_classes = true;
         }
       }
       if (unrelated_classes) {
diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp
index 1cd4315583c..b25c3814433 100644
--- a/src/hotspot/share/opto/type.cpp
+++ b/src/hotspot/share/opto/type.cpp
@@ -5376,32 +5376,35 @@ const TypeKlassPtr *TypeKlassPtr::OBJECT;
 const TypeKlassPtr *TypeKlassPtr::OBJECT_OR_NULL;
 
 //------------------------------TypeKlassPtr-----------------------------------
-TypeKlassPtr::TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array)
-  : TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant), _flatten_array(flatten_array) {
+TypeKlassPtr::TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array, bool not_flat, bool not_null_free)
+  : TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant),
+    _flatten_array(flatten_array), _not_flat(not_flat), _not_null_free(not_null_free) {
   assert(!klass->flatten_array() || flatten_array, "Should be flat in array");
   assert(!flatten_array || can_be_inline_type(), "Only inline types can be flat in array");
 }
 
 //------------------------------make-------------------------------------------
 // ptr to klass 'k', if Constant, or possibly to a sub-klass if not a Constant
-const TypeKlassPtr* TypeKlassPtr::make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array) {
+const TypeKlassPtr* TypeKlassPtr::make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array, bool not_flat, bool not_null_free) {
   assert(k == NULL || k->is_instance_klass() || k->is_array_klass(), "Incorrect type of klass oop");
   // Check if this type is known to be flat in arrays
   flatten_array = flatten_array || k->flatten_array();
-  return (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset, flatten_array))->hashcons();
+  return (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset, flatten_array, not_flat, not_null_free))->hashcons();
 }
 
 //------------------------------eq---------------------------------------------
 // Structural equality check for Type representations
 bool TypeKlassPtr::eq( const Type *t ) const {
   const TypeKlassPtr *p = t->is_klassptr();
-  return klass() == p->klass() && TypePtr::eq(p) && flatten_array() == p->flatten_array();
+  return klass() == p->klass() && TypePtr::eq(p) && flatten_array() == p->flatten_array() &&
+      is_not_flat() == p->is_not_flat() && is_not_null_free() == p->is_not_null_free();
 }
 
 //------------------------------hash-------------------------------------------
 // Type-specific hashing function.
 int TypeKlassPtr::hash(void) const {
-  return java_add(java_add(klass() != NULL ? klass()->hash() : (jint)0, (jint)TypePtr::hash()), (jint)flatten_array());
+  return java_add(java_add(java_add(java_add(klass() != NULL ? klass()->hash() : (jint)0, (jint)TypePtr::hash()),
+      (jint)flatten_array()), (jint)is_not_flat()), (jint)is_not_null_free());
 }
 
 //------------------------------singleton--------------------------------------
@@ -5535,21 +5538,21 @@ ciKlass* TypeAryPtr::klass() const {
 //------------------------------add_offset-------------------------------------
 // Access internals of klass object
 const TypePtr *TypeKlassPtr::add_offset( intptr_t offset ) const {
-  return make(_ptr, klass(), xadd_offset(offset), flatten_array());
+  return make(_ptr, klass(), xadd_offset(offset), flatten_array(), is_not_flat(), is_not_null_free());
 }
 
 //------------------------------cast_to_ptr_type-------------------------------
 const Type *TypeKlassPtr::cast_to_ptr_type(PTR ptr) const {
   assert(_base == KlassPtr, "subclass must override cast_to_ptr_type");
   if( ptr == _ptr ) return this;
-  return make(ptr, _klass, _offset, _flatten_array);
+  return make(ptr, _klass, _offset, _flatten_array, _not_flat, _not_null_free);
 }
 
 
 //-----------------------------cast_to_exactness-------------------------------
 const Type *TypeKlassPtr::cast_to_exactness(bool klass_is_exact) const {
   if( klass_is_exact == _klass_is_exact ) return this;
-  return make(klass_is_exact ? Constant : NotNull, _klass, _offset, _flatten_array);
+  return make(klass_is_exact ? Constant : NotNull, _klass, _offset, _flatten_array, _not_flat, _not_null_free);
 }
 
 
@@ -5560,12 +5563,15 @@ const TypeOopPtr* TypeKlassPtr::as_instance_type() const {
   ciKlass* k = klass();
   assert(k != NULL, "klass should not be NULL");
   bool    xk = klass_is_exact();
-  //return TypeInstPtr::make(TypePtr::NotNull, k, xk, NULL, 0);
   const TypeOopPtr* toop = TypeOopPtr::make_from_klass_raw(k);
   guarantee(toop != NULL, "need type for given klass");
   toop = toop->cast_to_ptr_type(TypePtr::NotNull)->is_oopptr();
   if (flatten_array() && !klass()->is_inlinetype()) {
     toop = toop->is_instptr()->cast_to_flatten_array();
+  } else if (is_not_null_free()) {
+    toop = toop->is_aryptr()->cast_to_not_null_free();
+  } else if (is_not_flat()) {
+    toop = toop->is_aryptr()->cast_to_not_flat();
   }
   return toop->cast_to_exactness(xk)->is_oopptr();
 }
@@ -5609,7 +5615,7 @@ const Type    *TypeKlassPtr::xmeet( const Type *t ) const {
     case Null:
       if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
     case AnyNull:
-      return make(ptr, klass(), offset, flatten_array());
+      return make(ptr, klass(), offset, flatten_array(), is_not_flat(), is_not_null_free());
     case BotPTR:
     case NotNull:
       return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
@@ -5657,8 +5663,8 @@ const Type    *TypeKlassPtr::xmeet( const Type *t ) const {
     // If we have constants, then we created oops so classes are loaded
     // and we can handle the constants further down.  This case handles
     // not-loaded classes
-    if (ptr != Constant && tkls->klass()->equals(klass()) && flatten_array() == tkls->flatten_array()) {
-      return make(ptr, klass(), off, flatten_array());
+    if (ptr != Constant && tkls->klass()->equals(klass()) && flatten_array() == tkls->flatten_array() && is_not_flat() == tkls->is_not_flat() && is_not_null_free() && tkls->is_not_null_free()) {
+      return make(ptr, klass(), off, flatten_array(), is_not_flat(), is_not_null_free());
     }
 
     // Classes require inspection in the Java klass hierarchy.  Must be loaded.
@@ -5666,9 +5672,9 @@ const Type    *TypeKlassPtr::xmeet( const Type *t ) const {
     ciKlass* this_klass = this->klass();
     assert( tkls_klass->is_loaded(), "This class should have been loaded.");
     assert( this_klass->is_loaded(), "This class should have been loaded.");
-    bool tkls_flatten_array = tkls->flatten_array();
-    bool this_flatten_array  = this->flatten_array();
-    bool flatten_array = below_centerline(ptr) ? (this_flatten_array && tkls_flatten_array) : (this_flatten_array || tkls_flatten_array);
+    bool flatten_array = below_centerline(ptr) ? (this->flatten_array() && tkls->flatten_array()) : (this->flatten_array() || tkls->flatten_array());
+    bool is_not_flat = this->is_not_flat() && tkls->is_not_flat();
+    bool is_not_null_free = this->is_not_null_free() && tkls->is_not_null_free();
 
     // If 'this' type is above the centerline and is a superclass of the
     // other, we can treat 'this' as having the same type as the other.
@@ -5696,7 +5702,7 @@ const Type    *TypeKlassPtr::xmeet( const Type *t ) const {
         else
           ptr = NotNull;
       }
-      return make(ptr, this_klass, off, flatten_array);
+      return make(ptr, this_klass, off, flatten_array, is_not_flat, is_not_null_free);
     } // Else classes are not equal
 
     // Since klasses are different, we require the LCA in the Java
@@ -5705,7 +5711,7 @@ const Type    *TypeKlassPtr::xmeet( const Type *t ) const {
       ptr = NotNull;
     // Now we find the LCA of Java classes
     ciKlass* k = this_klass->least_common_ancestor(tkls_klass);
-    return   make(ptr, k, off);
+    return make(ptr, k, off, false, is_not_flat, is_not_null_free);
   } // End of case KlassPtr
 
   } // End of switch
@@ -5715,7 +5721,7 @@ const Type    *TypeKlassPtr::xmeet( const Type *t ) const {
 //------------------------------xdual------------------------------------------
 // Dual: compute field-by-field dual
 const Type    *TypeKlassPtr::xdual() const {
-  return new TypeKlassPtr(dual_ptr(), klass(), dual_offset(), flatten_array());
+  return new TypeKlassPtr(dual_ptr(), klass(), dual_offset(), flatten_array(), !is_not_flat(), !is_not_null_free());
 }
 
 //------------------------------get_con----------------------------------------
@@ -5763,6 +5769,11 @@ void TypeKlassPtr::dump2( Dict & d, uint depth, outputStream *st ) const {
   default:
     break;
   }
+  if (Verbose) {
+    if (_flatten_array) st->print(":flatten array");
+    if (_not_flat) st->print(":not flat");
+    if (_not_null_free) st->print(":not null free");
+  }
 
   _offset.dump2(st);
 
diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp
index e9817b69158..5484a243243 100644
--- a/src/hotspot/share/opto/type.hpp
+++ b/src/hotspot/share/opto/type.hpp
@@ -1017,6 +1017,8 @@ class TypePtr : public Type {
 
   virtual bool can_be_inline_type() const { return false; }
   virtual bool flatten_array() const { return false; }
+  virtual bool is_not_flat() const { return false; }
+  virtual bool is_not_null_free() const { return false; }
 
   // Tests for relation to centerline of type lattice:
   static bool above_centerline(PTR ptr) { return (ptr <= AnyNull); }
@@ -1449,7 +1451,7 @@ class TypeMetadataPtr : public TypePtr {
 //------------------------------TypeKlassPtr-----------------------------------
 // Class of Java Klass pointers
 class TypeKlassPtr : public TypePtr {
-  TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array);
+  TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array, bool not_flat, bool not_null_free);
 
 protected:
   virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
@@ -1463,7 +1465,9 @@ class TypeKlassPtr : public TypePtr {
 
   // Does the type exclude subclasses of the klass?  (Inexact == polymorphic.)
   bool _klass_is_exact;
-  bool _flatten_array; // Type is flat in arrays
+  const bool _flatten_array; // Type is flat in arrays
+  const bool _not_flat;      // Array is never flattened
+  const bool _not_null_free; // Array is never null-free
 
 public:
   ciKlass* klass() const { return  _klass; }
@@ -1471,15 +1475,20 @@ class TypeKlassPtr : public TypePtr {
 
   virtual bool can_be_inline_type() const { return EnableValhalla && (_klass == NULL || _klass->can_be_inline_klass(_klass_is_exact)); }
   virtual bool flatten_array() const { return _flatten_array; }
+  virtual bool is_not_flat() const { return _not_flat; }
+  virtual bool is_not_null_free() const { return _not_null_free; }
 
   bool  is_loaded() const { return klass() != NULL && klass()->is_loaded(); }
 
   // ptr to klass 'k'
-  static const TypeKlassPtr* make(ciKlass* k) { return make( TypePtr::Constant, k, Offset(0)); }
-  // ptr to klass 'k' with offset
-  static const TypeKlassPtr* make(ciKlass* k, Offset offset) { return make( TypePtr::Constant, k, offset); }
+  static const TypeKlassPtr* make(ciKlass* k) {
+    bool not_null_free = k->is_array_klass() && ( k->as_array_klass()->element_klass() == NULL ||
+                                                 !k->as_array_klass()->element_klass()->can_be_inline_klass(true));
+    bool not_flat = k->is_array_klass() && !k->is_flat_array_klass();
+    return make( TypePtr::Constant, k, Offset(0), false, not_flat, not_null_free);
+  }
   // ptr to klass 'k' or sub-klass
-  static const TypeKlassPtr* make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array = false);
+  static const TypeKlassPtr* make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array = false, bool not_flat = false, bool not_null_free = false);
 
   virtual const Type *cast_to_ptr_type(PTR ptr) const;