< prev index next >

src/hotspot/share/c1/c1_LIRGenerator.cpp

Print this page

@@ -1657,16 +1657,36 @@
   __ shift_right(layout, Klass::_lh_array_tag_shift, layout);
   __ cmp(lir_cond_equal, layout, LIR_OprFact::intConst(Klass::_lh_array_tag_vt_value));
   __ branch(lir_cond_equal, T_ILLEGAL, slow_path);
 }
 
+bool LIRGenerator::needs_flattened_array_store_check(StoreIndexed* x) {
+  if (ValueArrayFlatten && x->elt_type() == T_OBJECT && x->array()->maybe_flattened_array()) {
+    ciType* type = x->value()->declared_type();
+    if (type != NULL && type->is_klass()) {
+      ciKlass* klass = type->as_klass();
+      if (klass->is_loaded() &&
+          !(klass->is_valuetype() && klass->as_value_klass()->flatten_array()) &&
+          !klass->is_java_lang_Object() &&
+          !klass->is_interface()) {
+        // This is known to be a non-flattenable object. If the array is flattened,
+        // it will be caught by the code generated by array_store_check().
+        return false;
+      }
+    }
+    // We're not 100% sure, so let's do the flattened_array_store_check.
+    return true;
+  }
+  return false;
+}
+
 void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
   assert(x->is_pinned(),"");
   bool is_loaded_flattened_array = x->array()->is_loaded_flattened_array();
   bool needs_range_check = x->compute_needs_range_check();
   bool use_length = x->length() != NULL;
-  bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
+  bool obj_store = x->elt_type() == T_OBJECT; assert(x->elt_type() != T_ARRAY, "never used");
   bool needs_store_check = obj_store && !is_loaded_flattened_array &&
                                         (x->value()->as_Constant() == NULL ||
                                          !get_jobject_constant(x->value())->is_null_object() ||
                                          x->should_profile());
 

@@ -1682,11 +1702,11 @@
     length.set_instruction(x->length());
     length.load_item();
   }
 
   if (needs_store_check || x->check_boolean()
-      || is_loaded_flattened_array || x->array()->maybe_flattened_array()) {
+      || is_loaded_flattened_array || needs_flattened_array_store_check(x)) {
     value.load_item();
   } else {
     value.load_for_store(x->elt_type());
   }
 

@@ -1727,11 +1747,11 @@
     }
     access_flattened_array(false, array, index, value);
   } else {
     StoreFlattenedArrayStub* slow_path = NULL;
 
-    if (x->array()->maybe_flattened_array()) {
+    if (needs_flattened_array_store_check(x)) {
       // Check if we indeed have a flattened array
       index.load_item();
       slow_path = new StoreFlattenedArrayStub(array.result(), index.result(), value.result(), state_for(x));
       check_flattened_array(array, slow_path);
     }

@@ -2044,13 +2064,13 @@
     set_no_result(x);
   } else {
     LIR_Opr result = rlock_result(x, x->elt_type());
     LoadFlattenedArrayStub* slow_path = NULL;
 
-    if (x->array()->maybe_flattened_array()) {
+    if (x->elt_type() == T_OBJECT && x->array()->maybe_flattened_array()) {
       index.load_item();
-      // Check if we indeed have a flattened array
+      // if we are loading from flattened array, load it using a runtime call
       slow_path = new LoadFlattenedArrayStub(array.result(), index.result(), result, state_for(x));
       check_flattened_array(array, slow_path);
     }
 
     DecoratorSet decorators = IN_HEAP | IS_ARRAY;
< prev index next >