diff a/src/hotspot/share/c1/c1_Instruction.cpp b/src/hotspot/share/c1/c1_Instruction.cpp
--- a/src/hotspot/share/c1/c1_Instruction.cpp
+++ b/src/hotspot/share/c1/c1_Instruction.cpp
@@ -25,10 +25,12 @@
 #include "precompiled.hpp"
 #include "c1/c1_IR.hpp"
 #include "c1/c1_Instruction.hpp"
 #include "c1/c1_InstructionPrinter.hpp"
 #include "c1/c1_ValueStack.hpp"
+#include "ci/ciFlatArrayKlass.hpp"
+#include "ci/ciInlineKlass.hpp"
 #include "ci/ciObjArrayKlass.hpp"
 #include "ci/ciTypeArrayKlass.hpp"
 #include "utilities/bitMap.inline.hpp"
 
 
@@ -104,17 +106,78 @@
     exception_state()->values_do(f);
   }
 }
 
 ciType* Instruction::exact_type() const {
-  ciType* t =  declared_type();
+  ciType* t = declared_type();
   if (t != nullptr && t->is_klass()) {
     return t->as_klass()->exact_klass();
   }
   return nullptr;
 }
 
+ciKlass* Instruction::as_loaded_klass_or_null() const {
+  ciType* type = declared_type();
+  if (type != nullptr && type->is_klass()) {
+    ciKlass* klass = type->as_klass();
+    if (klass->is_loaded()) {
+      return klass;
+    }
+  }
+  return nullptr;
+}
+
+bool Instruction::is_loaded_flat_array() const {
+  if (UseFlatArray) {
+    ciType* type = declared_type();
+    return type != nullptr && type->is_flat_array_klass();
+  }
+  return false;
+}
+
+bool Instruction::maybe_flat_array() {
+  if (UseFlatArray) {
+    ciType* type = declared_type();
+    if (type != nullptr) {
+      if (type->is_obj_array_klass()) {
+        // TODO 8325106 Fix comment
+        // The runtime type of [LMyValue might be [QMyValue due to [QMyValue <: [LMyValue.
+        ciKlass* element_klass = type->as_obj_array_klass()->element_klass();
+        if (element_klass->can_be_inline_klass() && (!element_klass->is_inlinetype() || element_klass->as_inline_klass()->flat_in_array())) {
+          return true;
+        }
+      } else if (type->is_flat_array_klass()) {
+        return true;
+      } else if (type->is_klass() && type->as_klass()->is_java_lang_Object()) {
+        // This can happen as a parameter to System.arraycopy()
+        return true;
+      }
+    } else {
+      // Type info gets lost during Phi merging (Phi, IfOp, etc), but we might be storing into a
+      // flat array, so we should do a runtime check.
+      return true;
+    }
+  }
+  return false;
+}
+
+bool Instruction::maybe_null_free_array() {
+  ciType* type = declared_type();
+  if (type != nullptr) {
+    if (type->is_obj_array_klass()) {
+      // Due to array covariance, the runtime type might be a null-free array.
+      if (type->as_obj_array_klass()->can_be_inline_array_klass()) {
+        return true;
+      }
+    }
+  } else {
+    // Type info gets lost during Phi merging (Phi, IfOp, etc), but we might be storing into a
+    // null-free array, so we should do a runtime check.
+    return true;
+  }
+  return false;
+}
 
 #ifndef PRODUCT
 void Instruction::check_state(ValueStack* state) {
   if (state != nullptr) {
     state->verify();
@@ -171,11 +234,11 @@
   return nullptr;
 }
 
 ciType* LoadIndexed::exact_type() const {
   ciType* array_type = array()->exact_type();
-  if (array_type != nullptr) {
+  if (delayed() == nullptr && array_type != nullptr) {
     assert(array_type->is_array_klass(), "what else?");
     ciArrayKlass* ak = (ciArrayKlass*)array_type;
 
     if (ak->element_type()->is_instance_klass()) {
       ciInstanceKlass* ik = (ciInstanceKlass*)ak->element_type();
@@ -185,21 +248,37 @@
     }
   }
   return Instruction::exact_type();
 }
 
-
 ciType* LoadIndexed::declared_type() const {
+  if (delayed() != nullptr) {
+    return delayed()->field()->type();
+  }
   ciType* array_type = array()->declared_type();
   if (array_type == nullptr || !array_type->is_loaded()) {
     return nullptr;
   }
   assert(array_type->is_array_klass(), "what else?");
   ciArrayKlass* ak = (ciArrayKlass*)array_type;
   return ak->element_type();
 }
 
+bool StoreIndexed::is_exact_flat_array_store() const {
+  if (array()->is_loaded_flat_array() && value()->as_Constant() == nullptr && value()->declared_type() != nullptr) {
+    ciKlass* element_klass = array()->declared_type()->as_flat_array_klass()->element_klass();
+    ciKlass* actual_klass = value()->declared_type()->as_klass();
+
+    // The following check can fail with inlining:
+    //     void test45_inline(Object[] oa, Object o, int index) { oa[index] = o; }
+    //     void test45(MyValue1[] va, int index, MyValue2 v) { test45_inline(va, v, index); }
+    if (element_klass == actual_klass) {
+      return true;
+    }
+  }
+  return false;
+}
 
 ciType* LoadField::declared_type() const {
   return field()->type();
 }
 
@@ -207,11 +286,15 @@
 ciType* NewTypeArray::exact_type() const {
   return ciTypeArrayKlass::make(elt_type());
 }
 
 ciType* NewObjectArray::exact_type() const {
-  return ciObjArrayKlass::make(klass());
+  return ciArrayKlass::make(klass());
+}
+
+ciType* NewMultiArray::exact_type() const {
+  return _klass;
 }
 
 ciType* NewArray::declared_type() const {
   return exact_type();
 }
@@ -317,10 +400,39 @@
     }
   }
 }
 
 
+StoreField::StoreField(Value obj, int offset, ciField* field, Value value, bool is_static,
+                       ValueStack* state_before, bool needs_patching)
+  : AccessField(obj, offset, field, is_static, state_before, needs_patching)
+  , _value(value)
+  , _enclosing_field(nullptr)
+{
+  set_flag(NeedsWriteBarrierFlag, as_ValueType(field_type())->is_object());
+#ifdef ASSERT
+  AssertValues assert_value;
+  values_do(&assert_value);
+#endif
+  pin();
+}
+
+StoreIndexed::StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value,
+                           ValueStack* state_before, bool check_boolean, bool mismatched)
+  : AccessIndexed(array, index, length, elt_type, state_before, mismatched)
+  , _value(value), _check_boolean(check_boolean)
+{
+  set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object()));
+  set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object()));
+#ifdef ASSERT
+  AssertValues assert_value;
+  values_do(&assert_value);
+#endif
+  pin();
+}
+
+
 // Implementation of Invoke
 
 
 Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
                ciMethod* target, ValueStack* state_before)
@@ -343,11 +455,12 @@
   _signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0));
   if (has_receiver()) {
     _signature->append(as_BasicType(receiver()->type()));
   }
   for (int i = 0; i < number_of_arguments(); i++) {
-    ValueType* t = argument_at(i)->type();
+    Value v = argument_at(i);
+    ValueType* t = v->type();
     BasicType bt = as_BasicType(t);
     _signature->append(bt);
   }
 }
 
@@ -986,5 +1099,6 @@
 }
 
 void ProfileInvoke::state_values_do(ValueVisitor* f) {
   if (state() != nullptr) state()->values_do(f);
 }
+
