--- a/hotspot/src/share/vm/opto/type.cpp Fri Aug 31 16:39:35 2012 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp Sat Sep 01 13:25:18 2012 -0400
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "ci/ciMethodData.hpp"
#include "ci/ciTypeFlow.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
@@ -33,7 +34,6 @@
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
-#include "oops/klassKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/typeArrayKlass.hpp"
#include "opto/matcher.hpp"
@@ -49,40 +49,46 @@
Dict* Type::_shared_type_dict = NULL;
// Array which maps compiler types to Basic Types
-const BasicType Type::_basic_type[Type::lastype] = {
- T_ILLEGAL, // Bad
- T_ILLEGAL, // Control
- T_VOID, // Top
- T_INT, // Int
- T_LONG, // Long
- T_VOID, // Half
- T_NARROWOOP, // NarrowOop
-
- T_ILLEGAL, // Tuple
- T_ARRAY, // Array
- T_ILLEGAL, // VectorS
- T_ILLEGAL, // VectorD
- T_ILLEGAL, // VectorX
- T_ILLEGAL, // VectorY
-
- T_ADDRESS, // AnyPtr // shows up in factory methods for NULL_PTR
- T_ADDRESS, // RawPtr
- T_OBJECT, // OopPtr
- T_OBJECT, // InstPtr
- T_OBJECT, // AryPtr
- T_OBJECT, // KlassPtr
-
- T_OBJECT, // Function
- T_ILLEGAL, // Abio
- T_ADDRESS, // Return_Address
- T_ILLEGAL, // Memory
- T_FLOAT, // FloatTop
- T_FLOAT, // FloatCon
- T_FLOAT, // FloatBot
- T_DOUBLE, // DoubleTop
- T_DOUBLE, // DoubleCon
- T_DOUBLE, // DoubleBot
- T_ILLEGAL, // Bottom
+Type::TypeInfo Type::_type_info[Type::lastype] = {
+ { Bad, T_ILLEGAL, "bad", false, Node::NotAMachineReg, relocInfo::none }, // Bad
+ { Control, T_ILLEGAL, "control", false, 0, relocInfo::none }, // Control
+ { Bottom, T_VOID, "top", false, 0, relocInfo::none }, // Top
+ { Bad, T_INT, "int:", false, Op_RegI, relocInfo::none }, // Int
+ { Bad, T_LONG, "long:", false, Op_RegL, relocInfo::none }, // Long
+ { Half, T_VOID, "half", false, 0, relocInfo::none }, // Half
+ { Bad, T_NARROWOOP, "narrowoop:", false, Op_RegN, relocInfo::none }, // NarrowOop
+ { Bad, T_ILLEGAL, "tuple:", false, Node::NotAMachineReg, relocInfo::none }, // Tuple
+ { Bad, T_ARRAY, "array:", false, Node::NotAMachineReg, relocInfo::none }, // Array
+
+#if defined(IA32) || defined(AMD64)
+ { Bad, T_ILLEGAL, "vectors:", false, Op_VecS, relocInfo::none }, // VectorS
+ { Bad, T_ILLEGAL, "vectord:", false, Op_VecD, relocInfo::none }, // VectorD
+ { Bad, T_ILLEGAL, "vectorx:", false, Op_VecX, relocInfo::none }, // VectorX
+ { Bad, T_ILLEGAL, "vectory:", false, Op_VecY, relocInfo::none }, // VectorY
+#else
+ { Bad, T_ILLEGAL, "vectors:", false, 0, relocInfo::none }, // VectorS
+ { Bad, T_ILLEGAL, "vectord:", false, Op_RegD, relocInfo::none }, // VectorD
+ { Bad, T_ILLEGAL, "vectorx:", false, 0, relocInfo::none }, // VectorX
+ { Bad, T_ILLEGAL, "vectory:", false, 0, relocInfo::none }, // VectorY
+#endif // IA32 || AMD64
+ { Bad, T_ADDRESS, "anyptr:", false, Op_RegP, relocInfo::none }, // AnyPtr
+ { Bad, T_ADDRESS, "rawptr:", false, Op_RegP, relocInfo::none }, // RawPtr
+ { Bad, T_OBJECT, "oop:", true, Op_RegP, relocInfo::oop_type }, // OopPtr
+ { Bad, T_OBJECT, "inst:", true, Op_RegP, relocInfo::oop_type }, // InstPtr
+ { Bad, T_OBJECT, "ary:", true, Op_RegP, relocInfo::oop_type }, // AryPtr
+ { Bad, T_METADATA, "metadata:", false, Op_RegP, relocInfo::metadata_type }, // MetadataPtr
+ { Bad, T_METADATA, "klass:", false, Op_RegP, relocInfo::metadata_type }, // KlassPtr
+ { Bad, T_OBJECT, "func", false, 0, relocInfo::none }, // Function
+ { Abio, T_ILLEGAL, "abIO", false, 0, relocInfo::none }, // Abio
+ { Return_Address, T_ADDRESS, "return_address",false, Op_RegP, relocInfo::none }, // Return_Address
+ { Memory, T_ILLEGAL, "memory", false, 0, relocInfo::none }, // Memory
+ { FloatBot, T_FLOAT, "float_top", false, Op_RegF, relocInfo::none }, // FloatTop
+ { FloatCon, T_FLOAT, "ftcon:", false, Op_RegF, relocInfo::none }, // FloatCon
+ { FloatTop, T_FLOAT, "float", false, Op_RegF, relocInfo::none }, // FloatBot
+ { DoubleBot, T_DOUBLE, "double_top", false, Op_RegD, relocInfo::none }, // DoubleTop
+ { DoubleCon, T_DOUBLE, "dblcon:", false, Op_RegD, relocInfo::none }, // DoubleCon
+ { DoubleTop, T_DOUBLE, "double", false, Op_RegD, relocInfo::none }, // DoubleBot
+ { Top, T_ILLEGAL, "bottom", false, 0, relocInfo::none } // Bottom
};
// Map ideal registers (machine types) to ideal types
@@ -321,6 +327,8 @@
false, 0, oopDesc::klass_offset_in_bytes());
TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot);
+ TypeMetadataPtr::BOTTOM = TypeMetadataPtr::make(TypePtr::BotPTR, NULL, OffsetBot);
+
TypeNarrowOop::NULL_PTR = TypeNarrowOop::make( TypePtr::NULL_PTR );
TypeNarrowOop::BOTTOM = TypeNarrowOop::make( TypeInstPtr::BOTTOM );
@@ -340,6 +348,7 @@
#ifdef _LP64
if (UseCompressedOops) {
+ assert(TypeAryPtr::NARROWOOPS->is_ptr_to_narrowoop(), "array of narrow oops must be ptr to narrow oop");
TypeAryPtr::OOPS = TypeAryPtr::NARROWOOPS;
} else
#endif
@@ -372,7 +381,7 @@
TypeKlassPtr::OBJECT_OR_NULL = TypeKlassPtr::make( TypePtr::BotPTR, current->env()->Object_klass(), 0 );
const Type **fi2c = TypeTuple::fields(2);
- fi2c[TypeFunc::Parms+0] = TypeInstPtr::BOTTOM; // methodOop
+ fi2c[TypeFunc::Parms+0] = TypeInstPtr::BOTTOM; // Method*
fi2c[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // argument pointer
TypeTuple::START_I2C = TypeTuple::make(TypeFunc::Parms+2, fi2c);
@@ -461,10 +470,6 @@
Type* t = (Type*)i._value;
tdic->Insert(t,t); // New Type, insert into Type table
}
-
-#ifdef ASSERT
- verify_lastype();
-#endif
}
//------------------------------hashcons---------------------------------------
@@ -620,6 +625,7 @@
case InstPtr:
return t->xmeet(this);
+ case MetadataPtr:
case KlassPtr:
return t->xmeet(this);
@@ -700,6 +706,8 @@
Bad, // OopPtr - handled in v-call
Bad, // InstPtr - handled in v-call
Bad, // AryPtr - handled in v-call
+
+ Bad, // MetadataPtr - handled in v-call
Bad, // KlassPtr - handled in v-call
Bad, // Function - handled in v-call
@@ -717,8 +725,8 @@
const Type *Type::xdual() const {
// Note: the base() accessor asserts the sanity of _base.
- assert(dual_type[base()] != Bad, "implement with v-call");
- return new Type(dual_type[_base]);
+ assert(_type_info[base()].dual_type != Bad, "implement with v-call");
+ return new Type(_type_info[_base].dual_type);
}
//------------------------------has_memory-------------------------------------
@@ -738,7 +746,7 @@
#ifndef PRODUCT
//------------------------------dump2------------------------------------------
void Type::dump2( Dict &d, uint depth, outputStream *st ) const {
- st->print(msg[_base]);
+ st->print(_type_info[_base].msg);
}
//------------------------------dump-------------------------------------------
@@ -750,17 +758,6 @@
st->print(" [narrow]");
}
}
-
-//------------------------------data-------------------------------------------
-const char * const Type::msg[Type::lastype] = {
- "bad","control","top","int:","long:","half", "narrowoop:",
- "tuple:", "array:", "vectors:", "vectord:", "vectorx:", "vectory:",
- "anyptr:", "rawptr:", "java:", "inst:", "aryptr:", "klass:",
- "func", "abIO", "return_address", "memory",
- "float_top", "ftcon:", "float",
- "double_top", "dblcon:", "double",
- "bottom"
-};
#endif
//------------------------------singleton--------------------------------------
@@ -813,31 +810,6 @@
ShouldNotReachHere();
}
-//------------------------------isa_oop_ptr------------------------------------
-// Return true if type is an oop pointer type. False for raw pointers.
-static char isa_oop_ptr_tbl[Type::lastype] = {
- 0,0,0,0,0,0,0/*narrowoop*/,0/*tuple*/, 0/*array*/, 0, 0, 0, 0/*vector*/,
- 0/*anyptr*/,0/*rawptr*/,1/*OopPtr*/,1/*InstPtr*/,1/*AryPtr*/,1/*KlassPtr*/,
- 0/*func*/,0,0/*return_address*/,0,
- /*floats*/0,0,0, /*doubles*/0,0,0,
- 0
-};
-bool Type::isa_oop_ptr() const {
- return isa_oop_ptr_tbl[_base] != 0;
-}
-
-//------------------------------dump_stats-------------------------------------
-// // Check that arrays match type enum
-#ifndef PRODUCT
-void Type::verify_lastype() {
- // Check that arrays match enumeration
- assert( Type::dual_type [Type::lastype - 1] == Type::Top, "did not update array");
- assert( strcmp(Type::msg [Type::lastype - 1],"bottom") == 0, "did not update array");
- // assert( PhiNode::tbl [Type::lastype - 1] == NULL, "did not update array");
- assert( Matcher::base2reg[Type::lastype - 1] == 0, "did not update array");
- assert( isa_oop_ptr_tbl [Type::lastype - 1] == (char)0, "did not update array");
-}
-#endif
//=============================================================================
// Convenience common pre-built types.
@@ -862,8 +834,9 @@
case RawPtr: // reuses local variables
case OopPtr:
case InstPtr:
+ case AryPtr:
+ case MetadataPtr:
case KlassPtr:
- case AryPtr:
case NarrowOop:
case Int:
case Long:
@@ -978,8 +951,9 @@
case RawPtr: // reuses local variables
case OopPtr:
case InstPtr:
+ case AryPtr:
+ case MetadataPtr:
case KlassPtr:
- case AryPtr:
case NarrowOop:
case Int:
case Long:
@@ -1131,8 +1105,9 @@
case RawPtr: // reuses local variables
case OopPtr:
case InstPtr:
+ case AryPtr:
+ case MetadataPtr:
case KlassPtr:
- case AryPtr:
case NarrowOop:
case Long:
case FloatTop:
@@ -1387,8 +1362,9 @@
case RawPtr: // reuses local variables
case OopPtr:
case InstPtr:
+ case AryPtr:
+ case MetadataPtr:
case KlassPtr:
- case AryPtr:
case NarrowOop:
case Int:
case FloatTop:
@@ -2132,8 +2108,9 @@
case RawPtr: // For these, flip the call around to cut down
case OopPtr:
case InstPtr: // on the cases I have to handle.
+ case AryPtr:
+ case MetadataPtr:
case KlassPtr:
- case AryPtr:
return t->xmeet(this); // Call in reverse direction
default: // All else is a mistake
typerr(t);
@@ -2288,8 +2265,9 @@
case OopPtr:
case InstPtr:
+ case AryPtr:
+ case MetadataPtr:
case KlassPtr:
- case AryPtr:
return TypePtr::BOTTOM; // Oop meet raw is not well defined
default: // All else is a mistake
typerr(t);
@@ -2375,11 +2353,12 @@
_instance_id(instance_id) {
#ifdef _LP64
if (UseCompressedOops && _offset != 0) {
- if (klass() == NULL) {
+ if (_offset == oopDesc::klass_offset_in_bytes()) {
+ _is_ptr_to_narrowoop = UseCompressedKlassPointers;
+ } else if (klass() == NULL) {
+ // Array with unknown body type
assert(this->isa_aryptr(), "only arrays without klass");
_is_ptr_to_narrowoop = true;
- } else if (_offset == oopDesc::klass_offset_in_bytes()) {
- _is_ptr_to_narrowoop = true;
} else if (this->isa_aryptr()) {
_is_ptr_to_narrowoop = (klass()->is_obj_array_klass() &&
_offset != arrayOopDesc::length_offset_in_bytes());
@@ -2399,7 +2378,7 @@
_offset == java_lang_Class::array_klass_offset_in_bytes())) {
// Special hidden fields from the Class.
assert(this->isa_instptr(), "must be an instance ptr.");
- _is_ptr_to_narrowoop = true;
+ _is_ptr_to_narrowoop = false;
} else if (klass() == ciEnv::current()->Class_klass() &&
_offset >= instanceMirrorKlass::offset_of_static_fields()) {
// Static fields
@@ -2423,7 +2402,6 @@
_is_ptr_to_narrowoop = true;
} else {
// Type for the copy start in LibraryCallKit::inline_native_clone().
- assert(!klass_is_exact(), "only non-exact klass");
_is_ptr_to_narrowoop = true;
}
}
@@ -2437,7 +2415,7 @@
const TypeOopPtr *TypeOopPtr::make(PTR ptr,
int offset, int instance_id) {
assert(ptr != Constant, "no constant generic pointers");
- ciKlass* k = ciKlassKlass::make();
+ ciKlass* k = Compile::current()->env()->Object_klass();
bool xk = false;
ciObject* o = NULL;
return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id))->hashcons();
@@ -2472,7 +2450,7 @@
const TypeKlassPtr* TypeOopPtr::as_klass_type() const {
ciKlass* k = klass();
bool xk = klass_is_exact();
- if (k == NULL || !k->is_java_klass())
+ if (k == NULL)
return TypeKlassPtr::OBJECT;
else
return TypeKlassPtr::make(xk? Constant: NotNull, k, 0);
@@ -2506,6 +2484,8 @@
typerr(t);
case RawPtr:
+ case MetadataPtr:
+ case KlassPtr:
return TypePtr::BOTTOM; // Oop meet raw is not well defined
case AnyPtr: {
@@ -2536,7 +2516,6 @@
}
case InstPtr: // For these, flip the call around to cut down
- case KlassPtr: // on the cases I have to handle.
case AryPtr:
return t->xmeet(this); // Call in reverse direction
@@ -2548,7 +2527,7 @@
//------------------------------xdual------------------------------------------
// Dual of a pure heap pointer. No relevant klass or oop information.
const Type *TypeOopPtr::xdual() const {
- assert(klass() == ciKlassKlass::make(), "no klasses here");
+ assert(klass() == Compile::current()->env()->Object_klass(), "no klasses here");
assert(const_oop() == NULL, "no constants here");
return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id() );
}
@@ -2556,7 +2535,6 @@
//--------------------------make_from_klass_common-----------------------------
// Computes the element-type given a klass.
const TypeOopPtr* TypeOopPtr::make_from_klass_common(ciKlass *klass, bool klass_change, bool try_for_exact) {
- assert(klass->is_java_klass(), "must be java language klass");
if (klass->is_instance_klass()) {
Compile* C = Compile::current();
Dependencies* deps = C->dependencies();
@@ -2613,24 +2591,6 @@
//------------------------------make_from_constant-----------------------------
// Make a java pointer from an oop constant
const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_constant) {
- if (o->is_method_data() || o->is_method()) {
- // Treat much like a typeArray of bytes, like below, but fake the type...
- const BasicType bt = T_BYTE;
- const Type* etype = get_const_basic_type(bt);
- const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS);
- ciKlass* klass = ciArrayKlass::make(ciType::make(bt));
- assert(o->can_be_constant(), "should be tenured");
- return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
- } else if (o->is_cpcache()) {
- // Treat much like a objArray, like below, but fake the type...
- const BasicType bt = T_OBJECT;
- const Type* etype = get_const_basic_type(bt);
- const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS);
- ciKlass* klass = ciArrayKlass::make(ciType::make(bt));
- assert(o->can_be_constant(), "should be tenured");
- return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
- } else {
- assert(o->is_java_object(), "must be java language object");
assert(!o->is_null_object(), "null object not yet handled here.");
ciKlass* klass = o->klass();
if (klass->is_instance_klass()) {
@@ -2643,7 +2603,8 @@
return TypeInstPtr::make(o);
} else if (klass->is_obj_array_klass()) {
// Element is an object array. Recursively call ourself.
- const Type *etype = make_from_klass_raw(klass->as_obj_array_klass()->element_klass());
+ const Type *etype =
+ TypeOopPtr::make_from_klass_raw(klass->as_obj_array_klass()->element_klass());
const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()));
// We used to pass NotNull in here, asserting that the sub-arrays
// are all not-null. This is not true in generally, as code can
@@ -2653,10 +2614,12 @@
} else if (!o->should_be_constant()) {
return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0);
}
- return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
+ const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
+ return arr;
} else if (klass->is_type_array_klass()) {
// Element is an typeArray
- const Type* etype = get_const_basic_type(klass->as_type_array_klass()->element_type());
+ const Type* etype =
+ (Type*)get_const_basic_type(klass->as_type_array_klass()->element_type());
const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()));
// We used to pass NotNull in here, asserting that the array pointer
// is not-null. That was not true in general.
@@ -2665,8 +2628,8 @@
} else if (!o->should_be_constant()) {
return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0);
}
- return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
- }
+ const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
+ return arr;
}
fatal("unhandled object type");
@@ -2845,8 +2808,7 @@
ciObject* o,
int offset,
int instance_id) {
- assert( !k->is_loaded() || k->is_instance_klass() ||
- k->is_method_klass(), "Must be for instance or method");
+ assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance");
// Either const_oop() is NULL or else ptr is Constant
assert( (!o && ptr != Constant) || (o && ptr == Constant),
"constant pointers must have a value supplied" );
@@ -2971,6 +2933,8 @@
default: // All else is a mistake
typerr(t);
+ case MetadataPtr:
+ case KlassPtr:
case RawPtr: return TypePtr::BOTTOM;
case AryPtr: { // All arrays inherit from Object class
@@ -3237,9 +3201,6 @@
return make( ptr, k, false, NULL, off, instance_id );
} // End of case InstPtr
- case KlassPtr:
- return TypeInstPtr::BOTTOM;
-
} // End of switch
return this; // Return the double constant
}
@@ -3516,6 +3477,8 @@
}
}
+ case MetadataPtr:
+ case KlassPtr:
case RawPtr: return TypePtr::BOTTOM;
case AryPtr: { // Meeting 2 references?
@@ -3634,10 +3597,6 @@
default: typerr(t);
}
}
-
- case KlassPtr:
- return TypeInstPtr::BOTTOM;
-
}
return this; // Lint noise
}
@@ -3768,8 +3727,9 @@
case RawPtr:
case OopPtr:
case InstPtr:
+ case AryPtr:
+ case MetadataPtr:
case KlassPtr:
- case AryPtr:
case Bottom: // Ye Olde Default
return Type::BOTTOM;
@@ -3829,6 +3789,183 @@
#endif
+
+//------------------------------eq---------------------------------------------
+// Structural equality check for Type representations
+bool TypeMetadataPtr::eq( const Type *t ) const {
+ const TypeMetadataPtr *a = (const TypeMetadataPtr*)t;
+ ciMetadata* one = metadata();
+ ciMetadata* two = a->metadata();
+ if (one == NULL || two == NULL) {
+ return (one == two) && TypePtr::eq(t);
+ } else {
+ return one->equals(two) && TypePtr::eq(t);
+ }
+}
+
+//------------------------------hash-------------------------------------------
+// Type-specific hashing function.
+int TypeMetadataPtr::hash(void) const {
+ return
+ (metadata() ? metadata()->hash() : 0) +
+ TypePtr::hash();
+}
+
+//------------------------------singleton--------------------------------------
+// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
+// constants
+bool TypeMetadataPtr::singleton(void) const {
+ // detune optimizer to not generate constant metadta + constant offset as a constant!
+ // TopPTR, Null, AnyNull, Constant are all singletons
+ return (_offset == 0) && !below_centerline(_ptr);
+}
+
+//------------------------------add_offset-------------------------------------
+const TypePtr *TypeMetadataPtr::add_offset( intptr_t offset ) const {
+ return make( _ptr, _metadata, xadd_offset(offset));
+}
+
+//-----------------------------filter------------------------------------------
+// Do not allow interface-vs.-noninterface joins to collapse to top.
+const Type *TypeMetadataPtr::filter( const Type *kills ) const {
+ const TypeMetadataPtr* ft = join(kills)->isa_metadataptr();
+ if (ft == NULL || ft->empty())
+ return Type::TOP; // Canonical empty value
+ return ft;
+}
+
+ //------------------------------get_con----------------------------------------
+intptr_t TypeMetadataPtr::get_con() const {
+ assert( _ptr == Null || _ptr == Constant, "" );
+ assert( _offset >= 0, "" );
+
+ if (_offset != 0) {
+ // After being ported to the compiler interface, the compiler no longer
+ // directly manipulates the addresses of oops. Rather, it only has a pointer
+ // to a handle at compile time. This handle is embedded in the generated
+ // code and dereferenced at the time the nmethod is made. Until that time,
+ // it is not reasonable to do arithmetic with the addresses of oops (we don't
+ // have access to the addresses!). This does not seem to currently happen,
+ // but this assertion here is to help prevent its occurence.
+ tty->print_cr("Found oop constant with non-zero offset");
+ ShouldNotReachHere();
+ }
+
+ return (intptr_t)metadata()->constant_encoding();
+}
+
+//------------------------------cast_to_ptr_type-------------------------------
+const Type *TypeMetadataPtr::cast_to_ptr_type(PTR ptr) const {
+ if( ptr == _ptr ) return this;
+ return make(ptr, metadata(), _offset);
+}
+
+//------------------------------meet-------------------------------------------
+// Compute the MEET of two types. It returns a new Type object.
+const Type *TypeMetadataPtr::xmeet( const Type *t ) const {
+ // Perform a fast test for common case; meeting the same types together.
+ if( this == t ) return this; // Meeting same type-rep?
+
+ // Current "this->_base" is OopPtr
+ switch (t->base()) { // switch on original type
+
+ case Int: // Mixing ints & oops happens when javac
+ case Long: // reuses local variables
+ case FloatTop:
+ case FloatCon:
+ case FloatBot:
+ case DoubleTop:
+ case DoubleCon:
+ case DoubleBot:
+ case NarrowOop:
+ case Bottom: // Ye Olde Default
+ return Type::BOTTOM;
+ case Top:
+ return this;
+
+ default: // All else is a mistake
+ typerr(t);
+
+ case AnyPtr: {
+ // Found an AnyPtr type vs self-OopPtr type
+ const TypePtr *tp = t->is_ptr();
+ int offset = meet_offset(tp->offset());
+ PTR ptr = meet_ptr(tp->ptr());
+ switch (tp->ptr()) {
+ case Null:
+ if (ptr == Null) return TypePtr::make(AnyPtr, ptr, offset);
+ // else fall through:
+ case TopPTR:
+ case AnyNull: {
+ return make(ptr, NULL, offset);
+ }
+ case BotPTR:
+ case NotNull:
+ return TypePtr::make(AnyPtr, ptr, offset);
+ default: typerr(t);
+ }
+ }
+
+ case RawPtr:
+ case KlassPtr:
+ case OopPtr:
+ case InstPtr:
+ case AryPtr:
+ return TypePtr::BOTTOM; // Oop meet raw is not well defined
+
+ case MetadataPtr:
+ ShouldNotReachHere();
+ break;
+
+ } // End of switch
+ return this; // Return the double constant
+}
+
+
+//------------------------------xdual------------------------------------------
+// Dual of a pure metadata pointer.
+const Type *TypeMetadataPtr::xdual() const {
+ return new TypeMetadataPtr(dual_ptr(), metadata(), dual_offset());
+}
+
+//------------------------------dump2------------------------------------------
+#ifndef PRODUCT
+void TypeMetadataPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
+ st->print("metadataptr:%s", ptr_msg[_ptr]);
+ if( metadata() ) st->print(INTPTR_FORMAT, metadata());
+ switch( _offset ) {
+ case OffsetTop: st->print("+top"); break;
+ case OffsetBot: st->print("+any"); break;
+ case 0: break;
+ default: st->print("+%d",_offset); break;
+ }
+}
+#endif
+
+
+//=============================================================================
+// Convenience common pre-built type.
+const TypeMetadataPtr *TypeMetadataPtr::BOTTOM;
+
+TypeMetadataPtr::TypeMetadataPtr(PTR ptr, ciMetadata* metadata, int offset):
+ TypePtr(MetadataPtr, ptr, offset), _metadata(metadata) {
+}
+
+const TypeMetadataPtr* TypeMetadataPtr::make(ciMethod* m) {
+ return make(Constant, m, 0);
+}
+const TypeMetadataPtr* TypeMetadataPtr::make(ciMethodData* m) {
+ return make(Constant, m, 0);
+}
+
+//------------------------------make-------------------------------------------
+// Create a meta data constant
+const TypeMetadataPtr *TypeMetadataPtr::make(PTR ptr, ciMetadata* m, int offset) {
+ assert(m == NULL || !m->is_klass(), "wrong type");
+ return (TypeMetadataPtr*)(new TypeMetadataPtr(ptr, m, offset))->hashcons();
+}
+
+
//=============================================================================
// Convenience common pre-built types.
@@ -3836,17 +3973,16 @@
const TypeKlassPtr *TypeKlassPtr::OBJECT;
const TypeKlassPtr *TypeKlassPtr::OBJECT_OR_NULL;
-//------------------------------TypeKlasPtr------------------------------------
+//------------------------------TypeKlassPtr-----------------------------------
TypeKlassPtr::TypeKlassPtr( PTR ptr, ciKlass* klass, int offset )
- : TypeOopPtr(KlassPtr, ptr, klass, (ptr==Constant), (ptr==Constant ? klass : NULL), offset, 0) {
+ : TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant) {
}
//------------------------------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, int offset ) {
assert( k != NULL, "Expect a non-NULL klass");
- assert(k->is_instance_klass() || k->is_array_klass() ||
- k->is_method_klass(), "Incorrect type of klass oop");
+ assert(k->is_instance_klass() || k->is_array_klass(), "Incorrect type of klass oop");
TypeKlassPtr *r =
(TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset))->hashcons();
@@ -3859,15 +3995,23 @@
const TypeKlassPtr *p = t->is_klassptr();
return
klass()->equals(p->klass()) &&
- TypeOopPtr::eq(p);
+ TypePtr::eq(p);
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
int TypeKlassPtr::hash(void) const {
- return klass()->hash() + TypeOopPtr::hash();
-}
-
+ return klass()->hash() + TypePtr::hash();
+}
+
+//------------------------------singleton--------------------------------------
+// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
+// constants
+bool TypeKlassPtr::singleton(void) const {
+ // detune optimizer to not generate constant klass + constant offset as a constant!
+ // TopPTR, Null, AnyNull, Constant are all singletons
+ return (_offset == 0) && !below_centerline(_ptr);
+}
//----------------------compute_klass------------------------------------------
// Compute the defining klass for this class
@@ -4018,24 +4162,6 @@
default: // All else is a mistake
typerr(t);
- case RawPtr: return TypePtr::BOTTOM;
-
- case OopPtr: { // Meeting to OopPtrs
- // Found a OopPtr type vs self-KlassPtr type
- const TypePtr *tp = t->is_oopptr();
- int offset = meet_offset(tp->offset());
- PTR ptr = meet_ptr(tp->ptr());
- switch (tp->ptr()) {
- case TopPTR:
- case AnyNull:
- return make(ptr, klass(), offset);
- case BotPTR:
- case NotNull:
- return TypePtr::make(AnyPtr, ptr, offset);
- default: typerr(t);
- }
- }
-
case AnyPtr: { // Meeting to AnyPtrs
// Found an AnyPtr type vs self-KlassPtr type
const TypePtr *tp = t->is_ptr();
@@ -4055,9 +4181,12 @@
}
}
+ case RawPtr:
+ case MetadataPtr:
+ case OopPtr:
case AryPtr: // Meet with AryPtr
case InstPtr: // Meet with InstPtr
- return TypeInstPtr::BOTTOM;
+ return TypePtr::BOTTOM;
//
// A-top }
@@ -4112,17 +4241,11 @@
// If the klasses are equal, the constants may still differ. Fall to
// NotNull if they do (neither constant is NULL; that is a special case
// handled elsewhere).
- ciObject* o = NULL; // Assume not constant when done
- ciObject* this_oop = const_oop();
- ciObject* tkls_oop = tkls->const_oop();
if( ptr == Constant ) {
- if (this_oop != NULL && tkls_oop != NULL &&
- this_oop->equals(tkls_oop) )
- o = this_oop;
- else if (above_centerline(this->ptr()))
- o = tkls_oop;
- else if (above_centerline(tkls->ptr()))
- o = this_oop;
+ if (this->_ptr == Constant && tkls->_ptr == Constant &&
+ this->klass()->equals(tkls->klass()));
+ else if (above_centerline(this->ptr()));
+ else if (above_centerline(tkls->ptr()));
else
ptr = NotNull;
}
@@ -4148,6 +4271,25 @@
return new TypeKlassPtr( dual_ptr(), klass(), dual_offset() );
}
+//------------------------------get_con----------------------------------------
+intptr_t TypeKlassPtr::get_con() const {
+ assert( _ptr == Null || _ptr == Constant, "" );
+ assert( _offset >= 0, "" );
+
+ if (_offset != 0) {
+ // After being ported to the compiler interface, the compiler no longer
+ // directly manipulates the addresses of oops. Rather, it only has a pointer
+ // to a handle at compile time. This handle is embedded in the generated
+ // code and dereferenced at the time the nmethod is made. Until that time,
+ // it is not reasonable to do arithmetic with the addresses of oops (we don't
+ // have access to the addresses!). This does not seem to currently happen,
+ // but this assertion here is to help prevent its occurence.
+ tty->print_cr("Found oop constant with non-zero offset");
+ ShouldNotReachHere();
+ }
+
+ return (intptr_t)klass()->constant_encoding();
+}
//------------------------------dump2------------------------------------------
// Dump Klass Type
#ifndef PRODUCT
@@ -4280,35 +4422,6 @@
}
st->print(" )");
}
-
-//------------------------------print_flattened--------------------------------
-// Print a 'flattened' signature
-static const char * const flat_type_msg[Type::lastype] = {
- "bad","control","top","int","long","_", "narrowoop",
- "tuple:", "array:", "vectors:", "vectord:", "vectorx:", "vectory:",
- "ptr", "rawptr", "ptr", "ptr", "ptr", "ptr",
- "func", "abIO", "return_address", "mem",
- "float_top", "ftcon:", "flt",
- "double_top", "dblcon:", "dbl",
- "bottom"
-};
-
-void TypeFunc::print_flattened() const {
- if( _range->_cnt <= Parms )
- tty->print("void");
- else {
- uint i;
- for (i = Parms; i < _range->_cnt-1; i++)
- tty->print("%s/",flat_type_msg[_range->field_at(i)->base()]);
- tty->print("%s",flat_type_msg[_range->field_at(i)->base()]);
- }
- tty->print(" ( ");
- if (Parms < _domain->_cnt)
- tty->print("%s",flat_type_msg[_domain->field_at(Parms)->base()]);
- for (uint i = Parms+1; i < _domain->_cnt; i++)
- tty->print(", %s",flat_type_msg[_domain->field_at(i)->base()]);
- tty->print(" )");
-}
#endif
//------------------------------singleton--------------------------------------