< 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 >