< prev index next >

src/hotspot/share/opto/type.cpp

Print this page

        

@@ -592,13 +592,13 @@
 
   TypeInstPtr::NOTNULL = TypeInstPtr::make(TypePtr::NotNull, current->env()->Object_klass());
   TypeInstPtr::BOTTOM  = TypeInstPtr::make(TypePtr::BotPTR,  current->env()->Object_klass());
   TypeInstPtr::MIRROR  = TypeInstPtr::make(TypePtr::NotNull, current->env()->Class_klass());
   TypeInstPtr::MARK    = TypeInstPtr::make(TypePtr::BotPTR,  current->env()->Object_klass(),
-                                           false, 0, Offset(oopDesc::mark_offset_in_bytes()));
+                                           false, 0, Offset(oopDesc::mark_offset_in_bytes()), false);
   TypeInstPtr::KLASS   = TypeInstPtr::make(TypePtr::BotPTR,  current->env()->Object_klass(),
-                                           false, 0, Offset(oopDesc::klass_offset_in_bytes()));
+                                           false, 0, Offset(oopDesc::klass_offset_in_bytes()), false);
   TypeOopPtr::BOTTOM  = TypeOopPtr::make(TypePtr::BotPTR, Offset::bottom, TypeOopPtr::InstanceBot);
 
   TypeMetadataPtr::BOTTOM = TypeMetadataPtr::make(TypePtr::BotPTR, NULL, Offset::bottom);
 
   TypeValueType::BOTTOM = TypeValueType::make(NULL);

@@ -653,12 +653,12 @@
   TypeAryPtr::_array_body_type[T_INT]     = TypeAryPtr::INTS;
   TypeAryPtr::_array_body_type[T_LONG]    = TypeAryPtr::LONGS;
   TypeAryPtr::_array_body_type[T_FLOAT]   = TypeAryPtr::FLOATS;
   TypeAryPtr::_array_body_type[T_DOUBLE]  = TypeAryPtr::DOUBLES;
 
-  TypeKlassPtr::OBJECT = TypeKlassPtr::make(TypePtr::NotNull, current->env()->Object_klass(), Offset(0) );
-  TypeKlassPtr::OBJECT_OR_NULL = TypeKlassPtr::make(TypePtr::BotPTR, current->env()->Object_klass(), Offset(0) );
+  TypeKlassPtr::OBJECT = TypeKlassPtr::make(TypePtr::NotNull, current->env()->Object_klass(), Offset(0), false);
+  TypeKlassPtr::OBJECT_OR_NULL = TypeKlassPtr::make(TypePtr::BotPTR, current->env()->Object_klass(), Offset(0), false );
 
   const Type **fi2c = TypeTuple::fields(2);
   fi2c[TypeFunc::Parms+0] = TypeInstPtr::BOTTOM; // Method*
   fi2c[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // argument pointer
   TypeTuple::START_I2C = TypeTuple::make(TypeFunc::Parms+2, fi2c);

@@ -3346,11 +3346,11 @@
   ciKlass* k = klass();
   bool    xk = klass_is_exact();
   if (k == NULL)
     return TypeKlassPtr::OBJECT;
   else
-    return TypeKlassPtr::make(xk? Constant: NotNull, k, Offset(0));
+    return TypeKlassPtr::make(xk? Constant: NotNull, k, Offset(0), isa_instptr() && is_instptr()->flatten_array());
 }
 
 //------------------------------meet-------------------------------------------
 // Compute the MEET of two types.  It returns a new Type object.
 const Type *TypeOopPtr::xmeet_helper(const Type *t) const {

@@ -3460,11 +3460,11 @@
           deps->assert_leaf_type(ik);
           klass_is_exact = true;
         }
       }
     }
-    return TypeInstPtr::make(TypePtr::BotPTR, klass, klass_is_exact, NULL, Offset(0));
+    return TypeInstPtr::make(TypePtr::BotPTR, klass, klass_is_exact, NULL, Offset(0), klass->flatten_array());
   } else if (klass->is_obj_array_klass()) {
     // Element is an object or value array. Recursively call ourself.
     const TypeOopPtr* etype = TypeOopPtr::make_from_klass_common(klass->as_array_klass()->element_klass(), false, try_for_exact);
     bool null_free = klass->is_loaded() && klass->as_array_klass()->storage_properties().is_null_free();
     if (null_free) {

@@ -3512,11 +3512,11 @@
   if (klass->is_instance_klass() || klass->is_valuetype()) {
     // Element is an instance or value type
     if (make_constant) {
       return TypeInstPtr::make(o);
     } else {
-      return TypeInstPtr::make(TypePtr::NotNull, klass, true, NULL, Offset(0));
+      return TypeInstPtr::make(TypePtr::NotNull, klass, true, NULL, Offset(0), klass->flatten_array());
     }
   } else if (klass->is_obj_array_klass()) {
     // Element is an object array. Recursively call ourself.
     const TypeOopPtr* etype = TypeOopPtr::make_from_klass_raw(klass->as_array_klass()->element_klass());
     bool null_free = klass->is_loaded() && klass->as_array_klass()->storage_properties().is_null_free();

@@ -3769,24 +3769,28 @@
 const TypeInstPtr *TypeInstPtr::MARK;
 const TypeInstPtr *TypeInstPtr::KLASS;
 
 //------------------------------TypeInstPtr-------------------------------------
 TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, Offset off,
-                         int instance_id, const TypePtr* speculative, int inline_depth)
+                         bool flatten_array, int instance_id, const TypePtr* speculative,
+                         int inline_depth)
   : TypeOopPtr(InstPtr, ptr, k, xk, o, off, Offset::bottom, instance_id, speculative, inline_depth),
-    _name(k->name()) {
+    _name(k->name()), _flatten_array(flatten_array) {
    assert(k != NULL &&
           (k->is_loaded() || o == NULL),
           "cannot have constants with non-loaded klass");
+   assert(!klass()->is_valuetype() || !klass()->flatten_array() || flatten_array, "incorrect flatten array bit");
+   assert(!flatten_array || can_be_value_type(), "incorrect flatten array bit");
 };
 
 //------------------------------make-------------------------------------------
 const TypeInstPtr *TypeInstPtr::make(PTR ptr,
                                      ciKlass* k,
                                      bool xk,
                                      ciObject* o,
                                      Offset offset,
+                                     bool flatten_array,
                                      int instance_id,
                                      const TypePtr* speculative,
                                      int inline_depth) {
   assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance");
   // Either const_oop() is NULL or else ptr is Constant

@@ -3806,11 +3810,11 @@
     if (xk && ik->is_interface())  xk = false;  // no exact interface
   }
 
   // Now hash this baby
   TypeInstPtr *result =
-    (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id, speculative, inline_depth))->hashcons();
+    (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, flatten_array, instance_id, speculative, inline_depth))->hashcons();
 
   return result;
 }
 
 /**

@@ -3839,11 +3843,11 @@
 //------------------------------cast_to_ptr_type-------------------------------
 const Type *TypeInstPtr::cast_to_ptr_type(PTR ptr) const {
   if( ptr == _ptr ) return this;
   // Reconstruct _sig info here since not a problem with later lazy
   // construction, _sig will show up on demand.
-  return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, _inline_depth);
+  return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _flatten_array, _instance_id, _speculative, _inline_depth);
 }
 
 
 //-----------------------------cast_to_exactness-------------------------------
 const Type *TypeInstPtr::cast_to_exactness(bool klass_is_exact) const {

@@ -3851,22 +3855,22 @@
   if (!UseExactTypes)  return this;
   if (!_klass->is_loaded())  return this;
   ciInstanceKlass* ik = _klass->as_instance_klass();
   if( (ik->is_final() || _const_oop) )  return this;  // cannot clear xk
   if( ik->is_interface() )              return this;  // cannot set xk
-  return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id, _speculative, _inline_depth);
+  return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _flatten_array, _instance_id, _speculative, _inline_depth);
 }
 
 //-----------------------------cast_to_instance_id----------------------------
 const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const {
   if( instance_id == _instance_id ) return this;
-  return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative, _inline_depth);
+  return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, _flatten_array, instance_id, _speculative, _inline_depth);
 }
 
 const TypeOopPtr *TypeInstPtr::cast_to_nonconst() const {
   if (const_oop() == NULL) return this;
-  return make(NotNull, klass(), _klass_is_exact, NULL, _offset, _instance_id, _speculative, _inline_depth);
+  return make(NotNull, klass(), _klass_is_exact, NULL, _offset, _flatten_array, _instance_id, _speculative, _inline_depth);
 }
 
 //------------------------------xmeet_unloaded---------------------------------
 // Compute the MEET of two InstPtrs when at least one is unloaded.
 // Assume classes are different since called after check for same name/class-loader

@@ -3894,11 +3898,11 @@
       //  BOTTOM  | ........................Object-BOTTOM ..................|
       //
       assert(loaded->ptr() != TypePtr::Null, "insanity check");
       //
       if(      loaded->ptr() == TypePtr::TopPTR ) { return unloaded; }
-      else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make(ptr, unloaded->klass(), false, NULL, off, instance_id, speculative, depth); }
+      else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make(ptr, unloaded->klass(), false, NULL, off, false, instance_id, speculative, depth); }
       else if (loaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; }
       else if (loaded->ptr() == TypePtr::Constant || loaded->ptr() == TypePtr::NotNull) {
         if (unloaded->ptr() == TypePtr::BotPTR  ) { return TypeInstPtr::BOTTOM;  }
         else                                      { return TypeInstPtr::NOTNULL; }
       }

@@ -3964,11 +3968,11 @@
         return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, tp->field_offset(), instance_id, speculative, depth);
       } else {
         // cannot subclass, so the meet has to fall badly below the centerline
         ptr = NotNull;
         instance_id = InstanceBot;
-        return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth);
+        return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, false, instance_id, speculative, depth);
       }
     case Constant:
     case NotNull:
     case BotPTR:                // Fall down to object klass
       // LCA is object_klass, but if we subclass from the top we can do better

@@ -3987,11 +3991,11 @@
       // The other case cannot happen, since I cannot be a subtype of an array.
       // The meet falls down to Object class below centerline.
       if( ptr == Constant )
          ptr = NotNull;
       instance_id = InstanceBot;
-      return make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth);
+      return make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, false, instance_id, speculative, depth);
     default: typerr(t);
     }
   }
 
   case OopPtr: {                // Meeting to OopPtrs

@@ -4004,11 +4008,11 @@
     case AnyNull: {
       int instance_id = meet_instance_id(InstanceTop);
       const TypePtr* speculative = xmeet_speculative(tp);
       int depth = meet_inline_depth(tp->inline_depth());
       return make(ptr, klass(), klass_is_exact(),
-                  (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth);
+                  (ptr == Constant ? const_oop() : NULL), offset, flatten_array(), instance_id, speculative, depth);
     }
     case NotNull:
     case BotPTR: {
       int instance_id = meet_instance_id(tp->instance_id());
       const TypePtr* speculative = xmeet_speculative(tp);

@@ -4032,11 +4036,11 @@
       if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, speculative, depth);
       // else fall through to AnyNull
     case TopPTR:
     case AnyNull: {
       return make(ptr, klass(), klass_is_exact(),
-                  (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth);
+                  (ptr == Constant ? const_oop() : NULL), offset, flatten_array(), instance_id, speculative, depth);
     }
     case NotNull:
     case BotPTR:
       return TypePtr::make(AnyPtr, ptr, offset, speculative,depth);
     default: typerr(t);

@@ -4070,19 +4074,22 @@
 
     // Check for easy case; klasses are equal (and perhaps not loaded!)
     // If we have constants, then we created oops so classes are loaded
     // and we can handle the constants further down.  This case handles
     // both-not-loaded or both-loaded classes
-    if (ptr != Constant && klass()->equals(tinst->klass()) && klass_is_exact() == tinst->klass_is_exact()) {
-      return make(ptr, klass(), klass_is_exact(), NULL, off, instance_id, speculative, depth);
+    if (ptr != Constant && klass()->equals(tinst->klass()) && klass_is_exact() == tinst->klass_is_exact() &&
+        flatten_array() == tinst->flatten_array()) {
+      return make(ptr, klass(), klass_is_exact(), NULL, off, flatten_array(), instance_id, speculative, depth);
     }
 
     // Classes require inspection in the Java klass hierarchy.  Must be loaded.
     ciKlass* tinst_klass = tinst->klass();
     ciKlass* this_klass  = this->klass();
     bool tinst_xk = tinst->klass_is_exact();
     bool this_xk  = this->klass_is_exact();
+    bool tinst_flatten_array = tinst->flatten_array();
+    bool this_flatten_array  = this->flatten_array();
     if (!tinst_klass->is_loaded() || !this_klass->is_loaded() ) {
       // One of these classes has not been loaded
       const TypeInstPtr *unloaded_meet = xmeet_unloaded(tinst);
 #ifndef PRODUCT
       if( PrintOpto && Verbose ) {

@@ -4101,10 +4108,13 @@
       tinst_klass = this_klass;
       this_klass = tmp;
       bool tmp2 = tinst_xk;
       tinst_xk = this_xk;
       this_xk = tmp2;
+      tmp2 = tinst_flatten_array;
+      tinst_flatten_array = this_flatten_array;
+      this_flatten_array = tmp2;
     }
     if (tinst_klass->is_interface() &&
         !(this_klass->is_interface() ||
           // Treat java/lang/Object as an honorary interface,
           // because we need a bottom for the interface hierarchy.

@@ -4112,34 +4122,37 @@
       // Oop meets interface!
 
       // See if the oop subtypes (implements) interface.
       ciKlass *k;
       bool xk;
+      bool value;
       if( this_klass->is_subtype_of( tinst_klass ) ) {
         // Oop indeed subtypes.  Now keep oop or interface depending
         // on whether we are both above the centerline or either is
         // below the centerline.  If we are on the centerline
         // (e.g., Constant vs. AnyNull interface), use the constant.
         k  = below_centerline(ptr) ? tinst_klass : this_klass;
         // If we are keeping this_klass, keep its exactness too.
         xk = below_centerline(ptr) ? tinst_xk    : this_xk;
+        value = below_centerline(ptr) ? tinst_flatten_array    : this_flatten_array;
       } else {                  // Does not implement, fall to Object
         // Oop does not implement interface, so mixing falls to Object
         // just like the verifier does (if both are above the
         // centerline fall to interface)
         k = above_centerline(ptr) ? tinst_klass : ciEnv::current()->Object_klass();
         xk = above_centerline(ptr) ? tinst_xk : false;
+        value = above_centerline(ptr) ? tinst_flatten_array : false;
         // Watch out for Constant vs. AnyNull interface.
         if (ptr == Constant)  ptr = NotNull;   // forget it was a constant
         instance_id = InstanceBot;
       }
       ciObject* o = NULL;  // the Constant value, if any
       if (ptr == Constant) {
         // Find out which constant.
         o = (this_klass == klass()) ? const_oop() : tinst->const_oop();
       }
-      return make(ptr, k, xk, o, off, instance_id, speculative, depth);
+      return make(ptr, k, xk, o, off, value, instance_id, speculative, depth);
     }
 
     // Either oop vs oop or interface vs interface or interface vs Object
 
     // !!! Here's how the symmetry requirement breaks down into invariants:

@@ -4167,33 +4180,41 @@
     // centerline and or-ed above it.  (N.B. Constants are always exact.)
 
     // Check for subtyping:
     ciKlass *subtype = NULL;
     bool subtype_exact = false;
+    bool flatten_array = false;
     if( tinst_klass->equals(this_klass) ) {
       subtype = this_klass;
       subtype_exact = below_centerline(ptr) ? (this_xk && tinst_xk) : (this_xk || tinst_xk);
+      flatten_array = below_centerline(ptr) ? (this_flatten_array && tinst_flatten_array) : (this_flatten_array || tinst_flatten_array);
     } else if( !tinst_xk && this_klass->is_subtype_of( tinst_klass ) ) {
       subtype = this_klass;     // Pick subtyping class
       subtype_exact = this_xk;
+      flatten_array = this_flatten_array;
     } else if( !this_xk && tinst_klass->is_subtype_of( this_klass ) ) {
       subtype = tinst_klass;    // Pick subtyping class
       subtype_exact = tinst_xk;
+      flatten_array = tinst_flatten_array;
     }
 
     if( subtype ) {
       if( above_centerline(ptr) ) { // both are up?
         this_klass = tinst_klass = subtype;
         this_xk = tinst_xk = subtype_exact;
+        this_flatten_array = tinst_flatten_array = flatten_array;
       } else if( above_centerline(this ->_ptr) && !above_centerline(tinst->_ptr) ) {
         this_klass = tinst_klass; // tinst is down; keep down man
         this_xk = tinst_xk;
+        this_flatten_array = tinst_flatten_array;
       } else if( above_centerline(tinst->_ptr) && !above_centerline(this ->_ptr) ) {
         tinst_klass = this_klass; // this is down; keep down man
         tinst_xk = this_xk;
+        tinst_flatten_array = this_flatten_array;
       } else {
         this_xk = subtype_exact;  // either they are equal, or we'll do an LCA
+        this_flatten_array = flatten_array;
       }
     }
 
     // Check for classes now being equal
     if (tinst_klass->equals(this_klass)) {

@@ -4212,11 +4233,11 @@
         else if (above_centerline(tinst ->_ptr))
           o = this_oop;
         else
           ptr = NotNull;
       }
-      return make(ptr, this_klass, this_xk, o, off, instance_id, speculative, depth);
+      return make(ptr, this_klass, this_xk, o, off, this_flatten_array, instance_id, speculative, depth);
     } // Else classes are not equal
 
     // Since klasses are different, we require a LCA in the Java
     // class hierarchy - which means we have to fall to at least NotNull.
     if( ptr == TopPTR || ptr == AnyNull || ptr == Constant )

@@ -4224,11 +4245,11 @@
 
     instance_id = InstanceBot;
 
     // Now we find the LCA of Java classes
     ciKlass* k = this_klass->least_common_ancestor(tinst_klass);
-    return make(ptr, k, false, NULL, off, instance_id, speculative, depth);
+    return make(ptr, k, false, NULL, off, false, instance_id, speculative, depth);
   } // End of case InstPtr
 
   case ValueType: {
     const TypeValueType* tv = t->is_valuetype();
     if (above_centerline(ptr())) {

@@ -4269,26 +4290,27 @@
 
 //------------------------------xdual------------------------------------------
 // Dual: do NOT dual on klasses.  This means I do NOT understand the Java
 // inheritance mechanism.
 const Type *TypeInstPtr::xdual() const {
-  return new TypeInstPtr(dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative(), dual_inline_depth());
+  return new TypeInstPtr(dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), flatten_array(), dual_instance_id(), dual_speculative(), dual_inline_depth());
 }
 
 //------------------------------eq---------------------------------------------
 // Structural equality check for Type representations
 bool TypeInstPtr::eq( const Type *t ) const {
   const TypeInstPtr *p = t->is_instptr();
   return
     klass()->equals(p->klass()) &&
+    flatten_array() == p->flatten_array() &&
     TypeOopPtr::eq(p);          // Check sub-type stuff
 }
 
 //------------------------------hash-------------------------------------------
 // Type-specific hashing function.
 int TypeInstPtr::hash(void) const {
-  int hash = java_add((jint)klass()->hash(), (jint)TypeOopPtr::hash());
+  int hash = java_add(java_add((jint)klass()->hash(), (jint)TypeOopPtr::hash()), (jint)flatten_array());
   return hash;
 }
 
 //------------------------------dump2------------------------------------------
 // Dump oop Type

@@ -4319,10 +4341,15 @@
   }
 
   _offset.dump2(st);
 
   st->print(" *");
+  
+  if (flatten_array() && !klass()->is_valuetype()) {
+    st->print(" (flatten array)");
+  }
+  
   if (_instance_id == InstanceTop)
     st->print(",iid=top");
   else if (_instance_id != InstanceBot)
     st->print(",iid=%d",_instance_id);
 

@@ -4331,35 +4358,40 @@
 }
 #endif
 
 //------------------------------add_offset-------------------------------------
 const TypePtr *TypeInstPtr::add_offset(intptr_t offset) const {
-  return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset),
+  return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset), flatten_array(), 
               _instance_id, add_offset_speculative(offset), _inline_depth);
 }
 
 const Type *TypeInstPtr::remove_speculative() const {
   if (_speculative == NULL) {
     return this;
   }
   assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth");
-  return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset,
+  return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, flatten_array(),
               _instance_id, NULL, _inline_depth);
 }
 
 const TypePtr *TypeInstPtr::with_inline_depth(int depth) const {
   if (!UseInlineDepthForSpeculativeTypes) {
     return this;
   }
-  return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, depth);
+  return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, flatten_array(), _instance_id, _speculative, depth);
 }
 
 const TypePtr *TypeInstPtr::with_instance_id(int instance_id) const {
   assert(is_known_instance(), "should be known");
-  return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, instance_id, _speculative, _inline_depth);
+  return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, flatten_array(), instance_id, _speculative, _inline_depth);
 }
 
+const TypeInstPtr *TypeInstPtr::cast_to_flatten_array() const {
+  return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, true, _instance_id, _speculative, _inline_depth);
+}
+
+
 //=============================================================================
 // Convenience common pre-built types.
 const TypeAryPtr *TypeAryPtr::RANGE;
 const TypeAryPtr *TypeAryPtr::OOPS;
 const TypeAryPtr *TypeAryPtr::NARROWOOPS;

@@ -4763,11 +4795,11 @@
         return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, _field_offset, instance_id, speculative, depth);
       } else {
         // cannot subclass, so the meet has to fall badly below the centerline
         ptr = NotNull;
         instance_id = InstanceBot;
-        return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth);
+        return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, false, instance_id, speculative, depth);
       }
     case Constant:
     case NotNull:
     case BotPTR:                // Fall down to object klass
       // LCA is object_klass, but if we subclass from the top we can do better

@@ -4786,11 +4818,11 @@
       // The other case cannot happen, since t cannot be a subtype of an array.
       // The meet falls down to Object class below centerline.
       if( ptr == Constant )
          ptr = NotNull;
       instance_id = InstanceBot;
-      return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth);
+      return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, false, instance_id, speculative, depth);
     default: typerr(t);
     }
   }
 
   case ValueType: {

@@ -5324,32 +5356,34 @@
 // Not-null object klass or below
 const TypeKlassPtr *TypeKlassPtr::OBJECT;
 const TypeKlassPtr *TypeKlassPtr::OBJECT_OR_NULL;
 
 //------------------------------TypeKlassPtr-----------------------------------
-TypeKlassPtr::TypeKlassPtr( PTR ptr, ciKlass* klass, Offset offset )
-  : TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant) {
+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) {
+   assert(!klass->is_valuetype() || !klass->flatten_array() || flatten_array, "incorrect flatten array bit");
+   assert(!flatten_array || can_be_value_type(), "incorrect flatten array bit");
 }
 
 //------------------------------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) {
+const TypeKlassPtr* TypeKlassPtr::make(PTR ptr, ciKlass* k, Offset offset, bool value) {
   assert(k == NULL || k->is_instance_klass() || k->is_array_klass(), "Incorrect type of klass oop");
-  return (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset))->hashcons();
+  return (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset, value))->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);
+  return klass() == p->klass() && TypePtr::eq(p) && flatten_array() == p->flatten_array();
 }
 
 //------------------------------hash-------------------------------------------
 // Type-specific hashing function.
 int TypeKlassPtr::hash(void) const {
-  return java_add(klass() != NULL ? klass()->hash() : (jint)0, (jint)TypePtr::hash());
+  return java_add(java_add(klass() != NULL ? klass()->hash() : (jint)0, (jint)TypePtr::hash()), (jint)flatten_array());
 }
 
 //------------------------------singleton--------------------------------------
 // TRUE if Type is a singleton type, FALSE otherwise.   Singletons are simple
 // constants

@@ -5479,26 +5513,26 @@
 
 
 //------------------------------add_offset-------------------------------------
 // Access internals of klass object
 const TypePtr *TypeKlassPtr::add_offset( intptr_t offset ) const {
-  return make( _ptr, klass(), xadd_offset(offset) );
+  return make(_ptr, klass(), xadd_offset(offset), flatten_array());
 }
 
 //------------------------------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);
+  return make(ptr, _klass, _offset, _flatten_array);
 }
 
 
 //-----------------------------cast_to_exactness-------------------------------
 const Type *TypeKlassPtr::cast_to_exactness(bool klass_is_exact) const {
   if( klass_is_exact == _klass_is_exact ) return this;
   if (!UseExactTypes)  return this;
-  return make(klass_is_exact ? Constant : NotNull, _klass, _offset);
+  return make(klass_is_exact ? Constant : NotNull, _klass, _offset, _flatten_array);
 }
 
 
 //-----------------------------as_instance_type--------------------------------
 // Corresponding type for an instance of the given class.

@@ -5509,10 +5543,13 @@
   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_valuetype()) {
+    toop = toop->is_instptr()->cast_to_flatten_array();
+  }
   return toop->cast_to_exactness(xk)->is_oopptr();
 }
 
 
 //------------------------------xmeet------------------------------------------

@@ -5551,11 +5588,11 @@
     case TopPTR:
       return this;
     case Null:
       if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
     case AnyNull:
-      return make( ptr, klass(), offset );
+      return make(ptr, klass(), offset, klass()->flatten_array());
     case BotPTR:
     case NotNull:
       return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
     default: typerr(t);
     }

@@ -5592,26 +5629,29 @@
     if (klass() == NULL || tkls->klass() == NULL) {
       ciKlass* k = NULL;
       if (ptr == Constant) {
         k = (klass() == NULL) ? tkls->klass() : klass();
       }
-      return make(ptr, k, off);
+      return make(ptr, k, off, false);
     }
 
     // Check for easy case; klasses are equal (and perhaps not loaded!)
     // 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()) ) {
-      return make( ptr, klass(), off );
+    if (ptr != Constant && tkls->klass()->equals(klass()) && flatten_array() == tkls->flatten_array()) {
+      return make(ptr, klass(), off, flatten_array());
     }
 
     // Classes require inspection in the Java klass hierarchy.  Must be loaded.
     ciKlass* tkls_klass = tkls->klass();
     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);
 
     // 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.
     if ((above_centerline(this->ptr())) &&
         tkls_klass->is_subtype_of(this_klass)) {

@@ -5635,30 +5675,30 @@
         else if (above_centerline(this->ptr()));
         else if (above_centerline(tkls->ptr()));
         else
           ptr = NotNull;
       }
-      return make( ptr, this_klass, off );
+      return make(ptr, this_klass, off, flatten_array);
     } // Else classes are not equal
 
     // Since klasses are different, we require the LCA in the Java
     // class hierarchy - which means we have to fall to at least NotNull.
     if( ptr == TopPTR || ptr == AnyNull || ptr == Constant )
       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, k->is_valuetype() && k->flatten_array());
   } // End of case KlassPtr
 
   } // End of switch
   return this;                  // Return the double constant
 }
 
 //------------------------------xdual------------------------------------------
 // Dual: compute field-by-field dual
 const Type    *TypeKlassPtr::xdual() const {
-  return new TypeKlassPtr( dual_ptr(), klass(), dual_offset() );
+  return new TypeKlassPtr(dual_ptr(), klass(), dual_offset(), flatten_array());
 }
 
 //------------------------------get_con----------------------------------------
 intptr_t TypeKlassPtr::get_con() const {
   assert( _ptr == Null || _ptr == Constant, "" );
< prev index next >