/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "ci/ciTypeFlow.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "compiler/compileLog.hpp"
#include "memory/gcLocker.hpp"
#include "memory/oopFactory.hpp"
#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"
#include "opto/opcodes.hpp"
// Portions of code courtesy of Clifford Click
// Optimization - Graph Style
// Dictionary of types shared among compilations.
// Array which maps compiler types to Basic Types
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
};
// Map ideal registers (machine types) to ideal types
// Map basic types to canonical Type* pointers.
// Map basic types to constant-zero Types.
// Map basic types to array-body alias types.
//=============================================================================
// Convenience common pre-built types.
//------------------------------get_const_type---------------------------
return NULL;
} else if (type->is_primitive_type()) {
} else {
}
}
//---------------------------array_element_basic_type---------------------------------
// Mapping to the array element's basic type.
return T_VOID;
}
return bt;
}
//---------------------------get_typeflow_type---------------------------------
// Import a type produced by ciTypeFlow.
switch (type->basic_type()) {
// The ciTypeFlow pass pushes a long, then the half.
// We do the same.
// The ciTypeFlow pass pushes double, then the half.
// Our convention is the same.
case T_ADDRESS:
default:
// make sure we did not mix up the cases:
}
}
//------------------------------make-------------------------------------------
// Create a simple Type, with default empty symbol sets. Then hashcons it
// and look for an existing copy in the type dictionary.
}
//------------------------------cmp--------------------------------------------
return 1; // Missed badly
}
//------------------------------hash-------------------------------------------
return t->hash();
}
//--------------------------Initialize_shared----------------------------------
// This method does not need to be locked because the first system
// compilations (stub compilations) occur serially. If they are
// changed to proceed in parallel, then this section will need
// locking.
shared_type_arena, 128 );
// Make shared pre-built types.
// CmpL is overloaded both as the bytecode computation returning
// a trinary (-1,0,+1) integer result AND as an efficient long
// compare returning optimizer ideal-type flags.
false, 0, oopDesc::mark_offset_in_bytes());
false, 0, oopDesc::klass_offset_in_bytes());
TypeAryPtr::RANGE = TypeAryPtr::make( TypePtr::BotPTR, TypeAry::make(Type::BOTTOM,TypeInt::POS), NULL /* current->env()->Object_klass() */, false, arrayOopDesc::length_offset_in_bytes());
TypeAryPtr::NARROWOOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeNarrowOop::BOTTOM, TypeInt::POS), NULL /*ciArrayKlass::make(o)*/, false, Type::OffsetBot);
#ifdef _LP64
if (UseCompressedOops) {
} else
#endif
{
// There is no shared klass for Object[]. See note in TypeAryPtr::klass().
TypeAryPtr::OOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInstPtr::BOTTOM,TypeInt::POS), NULL /*ciArrayKlass::make(o)*/, false, Type::OffsetBot);
}
TypeAryPtr::BYTES = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::BYTE ,TypeInt::POS), ciTypeArrayKlass::make(T_BYTE), true, Type::OffsetBot);
TypeAryPtr::SHORTS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::SHORT ,TypeInt::POS), ciTypeArrayKlass::make(T_SHORT), true, Type::OffsetBot);
TypeAryPtr::CHARS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::CHAR ,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, Type::OffsetBot);
TypeAryPtr::INTS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::INT ,TypeInt::POS), ciTypeArrayKlass::make(T_INT), true, Type::OffsetBot);
TypeAryPtr::LONGS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeLong::LONG ,TypeInt::POS), ciTypeArrayKlass::make(T_LONG), true, Type::OffsetBot);
TypeAryPtr::FLOATS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::FLOAT ,TypeInt::POS), ciTypeArrayKlass::make(T_FLOAT), true, Type::OffsetBot);
TypeAryPtr::DOUBLES = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::DOUBLE ,TypeInt::POS), ciTypeArrayKlass::make(T_DOUBLE), true, Type::OffsetBot);
// Nobody should ask _array_body_type[T_NARROWOOP]. Use NULL as assert.
TypeKlassPtr::OBJECT_OR_NULL = TypeKlassPtr::make( TypePtr::BotPTR, current->env()->Object_klass(), 0 );
_const_basic_type[T_ADDRESS] = TypeRawPtr::BOTTOM; // both interpreter return addresses & random raw ptrs
// get_zero_type() should not happen for T_CONFLICT
// Vector predefined types, it needs initialized _const_basic_type[].
}
}
}
}
// Restore working type arena.
}
//------------------------------Initialize-------------------------------------
if (_shared_type_dict == NULL) {
}
// Create the hash-cons'ing dictionary with top-level storage allocation
// Transfer the shared types.
for( ; i.test(); ++i ) {
}
#ifdef ASSERT
#endif
}
//------------------------------hashcons---------------------------------------
// Do the hash-cons trick. If the Type already exists in the type table,
// delete the current Type and return the existing Type. Otherwise stick the
// current Type in the Type table.
// Look up the Type in the Type dictionary
if( old ) { // Pre-existing Type?
if( old != this ) // Yes, this guy is not the pre-existing?
delete this; // Yes, Nuke this guy
return old; // Return pre-existing
}
// Every type has a dual (to make my lattice symmetric).
// Since we just discovered a new Type, compute its dual right now.
_dual = this;
return this;
}
// New Type, insert into Type table
#ifdef ASSERT
delete dual_dual;
#endif
return this; // Return new Type
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
return true; // Nothing else can go wrong
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
return _base;
}
//------------------------------is_finite--------------------------------------
// Has a finite value
return false;
}
//------------------------------is_nan-----------------------------------------
// Is not a number (NaN)
return false;
}
//----------------------interface_vs_oop---------------------------------------
#ifdef ASSERT
bool result = false;
return result;
}
return result;
}
#endif
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. NOT virtual. It enforces that meet is
// commutative and the lattice is symmetric.
if (isa_narrowoop() && t->isa_narrowoop()) {
return result->make_narrowoop();
}
#ifdef ASSERT
// Interface meet Oop is Not Symmetric:
// Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull
fatal("meet not symmetric" );
}
#endif
return mt;
}
//------------------------------xmeet------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// Perform a fast test for common case; meeting the same types together.
if( this == t ) return this; // Meeting same type-rep?
// Meeting TOP with anything?
// Meeting BOTTOM with anything?
// Current "this->_base" is one of: Bad, Multi, Control, Top,
// Abio, Abstore, Floatxxx, Doublexxx, Bottom, lastype.
switch (t->base()) { // Switch on original type
// Cut in half the number of cases I must handle. Only need cases for when
// the given enum "t->type" is less than or equal to the local enum "type".
case FloatCon:
case DoubleCon:
case Int:
case Long:
return t->xmeet(this);
case OopPtr:
return t->xmeet(this);
case InstPtr:
return t->xmeet(this);
case KlassPtr:
return t->xmeet(this);
case AryPtr:
return t->xmeet(this);
case NarrowOop:
return t->xmeet(this);
case Bad: // Type check
default: // Bogus type not in lattice
typerr(t);
case Bottom: // Ye Olde Default
return t;
case FloatTop:
case FloatBot: // Float
typerr(t);
case DoubleTop:
case DoubleBot: // Double
typerr(t);
// These next few cases must match exactly or it is a compile-time error.
case Control: // Control of code
case Abio: // State of world outside of program
case Memory:
typerr(t);
case Top: // Top of the lattice
return this;
}
// The type is unchanged
return this;
}
//-----------------------------filter------------------------------------------
return ft;
}
//------------------------------xdual------------------------------------------
// Compute dual right now.
Bad, // Bad
Control, // Control
Bottom, // Top
Bad, // Int - handled in v-call
Bad, // Long - handled in v-call
Half, // Half
Bad, // NarrowOop - handled in v-call
Bad, // Tuple - handled in v-call
Bad, // Array - handled in v-call
Bad, // VectorS - handled in v-call
Bad, // VectorD - handled in v-call
Bad, // VectorX - handled in v-call
Bad, // VectorY - handled in v-call
Bad, // AnyPtr - handled in v-call
Bad, // RawPtr - handled in v-call
Bad, // OopPtr - handled in v-call
Bad, // InstPtr - handled in v-call
Bad, // AryPtr - handled in v-call
Bad, // KlassPtr - handled in v-call
Bad, // Function - handled in v-call
Abio, // Abio
Return_Address,// Return_Address
Memory, // Memory
FloatBot, // FloatTop
FloatCon, // FloatCon
FloatTop, // FloatBot
DoubleBot, // DoubleTop
DoubleCon, // DoubleCon
DoubleTop, // DoubleBot
Top // Bottom
};
// Note: the base() accessor asserts the sanity of _base.
}
//------------------------------has_memory-------------------------------------
}
}
return false;
}
#ifndef PRODUCT
//------------------------------dump2------------------------------------------
}
//------------------------------dump-------------------------------------------
if (is_ptr_to_narrowoop()) {
}
}
//------------------------------data-------------------------------------------
"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--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants (Ldi nodes). Singletons are integer, float or double constants.
}
//------------------------------empty------------------------------------------
// TRUE if Type is a type with no values, FALSE otherwise.
switch (_base) {
case DoubleTop:
case FloatTop:
case Top:
return true;
case Half:
case Abio:
case Return_Address:
case Memory:
case Bottom:
case FloatBot:
case DoubleBot:
return false; // never a singleton, therefore never empty
}
return false;
}
//------------------------------dump_stats-------------------------------------
// Dump collected statistics to stderr
#ifndef PRODUCT
}
#endif
//------------------------------typerr-----------------------------------------
#ifndef PRODUCT
dump();
t->dump();
#endif
}
//------------------------------isa_oop_ptr------------------------------------
// Return true if type is an oop pointer type. False for raw pointers.
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
};
return isa_oop_ptr_tbl[_base] != 0;
}
//------------------------------dump_stats-------------------------------------
// // Check that arrays match type enum
#ifndef PRODUCT
// Check that arrays match enumeration
// assert( PhiNode::tbl [Type::lastype - 1] == NULL, "did not update array");
}
#endif
//=============================================================================
// Convenience common pre-built types.
//------------------------------make-------------------------------------------
// Create a float constant
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 FloatCon
switch (t->base()) { // Switch on original type
case AnyPtr: // Mixing with oops happens when javac
case RawPtr: // reuses local variables
case OopPtr:
case InstPtr:
case KlassPtr:
case AryPtr:
case NarrowOop:
case Int:
case Long:
case DoubleTop:
case DoubleCon:
case DoubleBot:
case Bottom: // Ye Olde Default
case FloatBot:
return t;
default: // All else is a mistake
typerr(t);
case FloatCon: // Float-constant vs Float-constant?
// must compare bitwise as positive zero, negative zero and NaN have
// all the same representation in C++
return FLOAT; // Return generic float
// Equal constants
case Top:
case FloatTop:
break; // Return the float constant
}
return this; // Return the float constant
}
//------------------------------xdual------------------------------------------
// Dual: symmetric
return this;
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
// One or both are NANs. If both are NANs return true, else false.
}
// (NaN is impossible at this point, since it is not equal even to itself)
if (_f == 0.0) {
// difference between positive and negative zero
}
return true;
}
return false;
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
return *(int*)(&_f);
}
//------------------------------is_finite--------------------------------------
// Has a finite value
return g_isfinite(getf()) != 0;
}
//------------------------------is_nan-----------------------------------------
// Is not a number (NaN)
}
//------------------------------dump2------------------------------------------
// Dump float constant Type
#ifndef PRODUCT
}
#endif
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants (Ldi nodes). Singletons are integer, float or double constants
// or a single symbol.
return true; // Always a singleton
}
return false; // always exactly a singleton
}
//=============================================================================
// Convenience common pre-built types.
//------------------------------make-------------------------------------------
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 DoubleCon
switch (t->base()) { // Switch on original type
case AnyPtr: // Mixing with oops happens when javac
case RawPtr: // reuses local variables
case OopPtr:
case InstPtr:
case KlassPtr:
case AryPtr:
case NarrowOop:
case Int:
case Long:
case FloatTop:
case FloatCon:
case FloatBot:
case Bottom: // Ye Olde Default
case DoubleBot:
return t;
default: // All else is a mistake
typerr(t);
case DoubleCon: // Double-constant vs Double-constant?
return DOUBLE; // Return generic double
case Top:
case DoubleTop:
break;
}
return this; // Return the double constant
}
//------------------------------xdual------------------------------------------
// Dual: symmetric
return this;
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
// One or both are NANs. If both are NANs return true, else false.
}
// (NaN is impossible at this point, since it is not equal even to itself)
if (_d == 0.0) {
// difference between positive and negative zero
}
return true;
}
return false;
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
return *(int*)(&_d);
}
//------------------------------is_finite--------------------------------------
// Has a finite value
return g_isfinite(getd()) != 0;
}
//------------------------------is_nan-----------------------------------------
// Is not a number (NaN)
}
//------------------------------dump2------------------------------------------
// Dump double constant Type
#ifndef PRODUCT
}
#endif
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants (Ldi nodes). Singletons are integer, float or double constants
// or a single symbol.
return true; // Always a singleton
}
return false; // always exactly a singleton
}
//=============================================================================
// Convience common pre-built types.
//------------------------------TypeInt----------------------------------------
}
//------------------------------make-------------------------------------------
}
// Certain normalizations keep us sane when comparing types.
// The 'SMALLINT' covers constants and also CC and its relatives.
} else {
}
return w;
}
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type representation object
// with reference count equal to the number of Types pointing at it.
// Caller should wrap a Types around it.
// Perform a fast test for common case; meeting the same types together.
if( this == t ) return this; // Meeting same type?
// Currently "this->_base" is a TypeInt
switch (t->base()) { // Switch on original type
case AnyPtr: // Mixing with oops happens when javac
case RawPtr: // reuses local variables
case OopPtr:
case InstPtr:
case KlassPtr:
case AryPtr:
case NarrowOop:
case Long:
case FloatTop:
case FloatCon:
case FloatBot:
case DoubleTop:
case DoubleCon:
case DoubleBot:
case Bottom: // Ye Olde Default
default: // All else is a mistake
typerr(t);
case Top: // No change
return this;
case Int: // Int vs Int?
break;
}
// Expand covered set
}
//------------------------------xdual------------------------------------------
// Dual: reverse hi & lo; flip widen
}
//------------------------------widen------------------------------------------
// Only happens for optimistic top-down optimizations.
// Coming from TOP or such; no widening
// If new guy is equal to old guy, no widening
return old;
// If new guy contains old, then we widened
// New contains old
// If new guy is already wider than old, no widening
// If old guy was a constant, do not bother
// Now widen new guy.
// Check for widening too far
}
// If neither endpoint is extremal yet, push out the endpoint
// which is closer to its respective limit.
if (_lo >= 0 || // easy common case
// Try to widen to an unsigned range type of 31 bits:
} else {
}
}
}
// Returned widened new guy
}
// If old guy contains new, then we probably widened too far & dropped to
// bottom. Return the wider fellow.
return old;
//fatal("Integer value range is not subset");
//return this;
}
//------------------------------narrow---------------------------------------
// Only happens for pessimistic optimizations.
// If new guy is equal to old guy, no narrowing
// If old guy was maximum range, allow the narrowing
return this; // doesn't narrow; pretty wierd
// The new type narrows the old type, so look for a "death march".
// See comments on PhaseTransform::saturate.
// Use the new type only if the range shrinks a lot.
// We do not want the optimizer computing 2^31 point by point.
return old;
}
return this;
}
//-----------------------------filter------------------------------------------
// Do not allow the value of kill->_widen to affect the outcome.
// The widen bits must be allowed to run freely through the graph.
}
return ft;
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
}
//------------------------------is_finite--------------------------------------
// Has a finite value
return true;
}
//------------------------------dump2------------------------------------------
// Dump TypeInt
#ifndef PRODUCT
if (n == min_jint)
return "min";
else if (n < min_jint + 10000)
else if (n == max_jint)
return "max";
else if (n > max_jint - 10000)
else
return buf;
}
else if (is_con())
else
}
#endif
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants.
}
}
//=============================================================================
// Convenience common pre-built types.
//------------------------------TypeLong---------------------------------------
}
//------------------------------make-------------------------------------------
}
// Certain normalizations keep us sane when comparing types.
// The 'SMALLINT' covers constants.
} else {
}
return w;
}
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type representation object
// with reference count equal to the number of Types pointing at it.
// Caller should wrap a Types around it.
// Perform a fast test for common case; meeting the same types together.
if( this == t ) return this; // Meeting same type?
// Currently "this->_base" is a TypeLong
switch (t->base()) { // Switch on original type
case AnyPtr: // Mixing with oops happens when javac
case RawPtr: // reuses local variables
case OopPtr:
case InstPtr:
case KlassPtr:
case AryPtr:
case NarrowOop:
case Int:
case FloatTop:
case FloatCon:
case FloatBot:
case DoubleTop:
case DoubleCon:
case DoubleBot:
case Bottom: // Ye Olde Default
default: // All else is a mistake
typerr(t);
case Top: // No change
return this;
case Long: // Long vs Long?
break;
}
// Expand covered set
}
//------------------------------xdual------------------------------------------
// Dual: reverse hi & lo; flip widen
}
//------------------------------widen------------------------------------------
// Only happens for optimistic top-down optimizations.
// Coming from TOP or such; no widening
// If new guy is equal to old guy, no widening
return old;
// If new guy contains old, then we widened
// New contains old
// If new guy is already wider than old, no widening
// If old guy was a constant, do not bother
// Now widen new guy.
// Check for widening too far
}
// If neither endpoint is extremal yet, push out the endpoint
// which is closer to its respective limit.
if (_lo >= 0 || // easy common case
// Try to widen to an unsigned range type of 32/63 bits:
else
} else {
}
}
}
// Returned widened new guy
}
// If old guy contains new, then we probably widened too far & dropped to
// bottom. Return the wider fellow.
return old;
// fatal("Long value range is not subset");
// return this;
}
//------------------------------narrow----------------------------------------
// Only happens for pessimistic optimizations.
// If new guy is equal to old guy, no narrowing
// If old guy was maximum range, allow the narrowing
return this; // doesn't narrow; pretty wierd
// The new type narrows the old type, so look for a "death march".
// See comments on PhaseTransform::saturate.
// Use the new type only if the range shrinks a lot.
// We do not want the optimizer computing 2^31 point by point.
return old;
}
return this;
}
//-----------------------------filter------------------------------------------
// Do not allow the value of kill->_widen to affect the outcome.
// The widen bits must be allowed to run freely through the graph.
}
return ft;
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
}
//------------------------------is_finite--------------------------------------
// Has a finite value
return true;
}
//------------------------------dump2------------------------------------------
// Dump TypeLong
#ifndef PRODUCT
if (n > x) {
if (n >= x + 10000) return NULL;
} else if (n < x) {
if (n <= x - 10000) return NULL;
} else {
return xname;
}
return buf;
}
const char* str;
if (n == min_jlong)
return "min";
else if (n < min_jlong + 10000)
else if (n == max_jlong)
return "max";
else if (n > max_jlong - 10000)
return str;
return str;
return str;
else
return buf;
}
else if (is_con())
else
}
#endif
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants
}
}
//=============================================================================
// Convenience common pre-built types.
//------------------------------make-------------------------------------------
// Make a TypeTuple from the range of a method signature
switch (return_type->basic_type()) {
case T_LONG:
break;
case T_DOUBLE:
break;
case T_OBJECT:
case T_ARRAY:
case T_BOOLEAN:
case T_CHAR:
case T_FLOAT:
case T_BYTE:
case T_SHORT:
case T_INT:
break;
case T_VOID:
break;
default:
}
}
// Make a TypeTuple from the domain of a method signature
total_fields++;
// Use get_const_type here because it respects UseUniqueSubclasses:
} else {
}
int i = 0;
while (pos < total_fields) {
switch (type->basic_type()) {
case T_LONG:
break;
case T_DOUBLE:
break;
case T_OBJECT:
case T_ARRAY:
case T_BOOLEAN:
case T_CHAR:
case T_FLOAT:
case T_BYTE:
case T_SHORT:
case T_INT:
break;
default:
}
i++;
}
}
}
//------------------------------fields-----------------------------------------
// Subroutine call type with space allocated for argument types
const Type **flds = (const Type **)(Compile::current()->type_arena()->Amalloc_4((TypeFunc::Parms+arg_cnt)*sizeof(Type*) ));
return flds;
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 Tuple
switch (t->base()) { // switch on original type
case Bottom: // Ye Olde Default
return t;
default: // All else is a mistake
typerr(t);
case Tuple: { // Meeting 2 signatures?
const Type **fields = (const Type **)(Compile::current()->type_arena()->Amalloc_4( _cnt*sizeof(Type*) ));
}
case Top:
break;
}
return this; // Return the double constant
}
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
const Type **fields = (const Type **)(Compile::current()->type_arena()->Amalloc_4( _cnt*sizeof(Type*) ));
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
return false; // Missed
return true;
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
return sum;
}
//------------------------------dump2------------------------------------------
// Dump signature Type
#ifndef PRODUCT
if( !depth || d[this] ) { // Check for recursive print
return;
}
d.Insert((void*)this, (void*)this); // Stop recursion
if( _cnt ) {
uint i;
for( i=0; i<_cnt-1; i++ ) {
}
}
}
#endif
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants (Ldi nodes). Singletons are integer, float or double constants
// or a single symbol.
return false; // Never a singleton
}
}
return false;
}
//=============================================================================
// Convenience common pre-built types.
// Certain normalizations keep us sane when comparing types.
// We do not want arrayOop variables to differ only by the wideness
// of their index types. Pick minimum wideness, since that is the
// forced wideness of small ranges anyway.
else
return size;
}
//------------------------------make-------------------------------------------
}
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 Ary
switch (t->base()) { // switch on original type
case Bottom: // Ye Olde Default
return t;
default: // All else is a mistake
typerr(t);
case Array: { // Meeting 2 arrays?
}
case Top:
break;
}
return this; // Return the double constant
}
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
}
//----------------------interface_vs_oop---------------------------------------
#ifdef ASSERT
if (t_ary) {
}
return false;
}
#endif
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
}
#endif
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants (Ldi nodes). Singletons are integer, float or double constants
// or a single symbol.
return false; // Never a singleton
}
}
//--------------------------ary_must_be_exact----------------------------------
if (!UseExactTypes) return false;
// This logic looks at the element type of an array, and returns true
// if the element type is either a primitive or a final instance class.
// In such cases, an array built on this ary must have no subclasses.
} else {
}
if (!toop) return true; // a primitive type, like int
if (_elem->isa_narrowoop())
else
if (tinst)
if (_elem->isa_narrowoop())
else
if (tap)
return false;
}
//==============================TypeVect=======================================
// Convenience common pre-built types.
//------------------------------make-------------------------------------------
case Op_VecS:
case Op_VecD:
case Op_RegD:
case Op_VecX:
case Op_VecY:
}
return NULL;
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 Vector
switch (t->base()) { // switch on original type
case Bottom: // Ye Olde Default
return t;
default: // All else is a mistake
typerr(t);
case VectorS:
case VectorD:
case VectorX:
case VectorY: { // Meeting 2 vectors?
}
case Top:
break;
}
return this;
}
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
}
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants (Ldi nodes). Vector is singleton if all elements are the same
// constant value (when vector is created with Replicate code).
// There is no Con node for vectors yet.
// return _elem->singleton();
return false;
}
}
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
switch (base()) {
case VectorS:
case VectorD:
case VectorX:
case VectorY:
default:
}
}
#endif
//=============================================================================
// Convenience common pre-built types.
//------------------------------meet-------------------------------------------
// Meet over the PTR enum
// TopPTR, AnyNull, Constant, Null, NotNull, BotPTR,
};
//------------------------------make-------------------------------------------
}
//------------------------------cast_to_ptr_type-------------------------------
}
//------------------------------get_con----------------------------------------
return _offset;
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 AnyPtr
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
case Top:
return this;
case AnyPtr: { // Meeting to AnyPtrs
}
case RawPtr: // For these, flip the call around to cut down
case OopPtr:
case InstPtr: // on the cases I have to handle.
case KlassPtr:
case AryPtr:
return t->xmeet(this); // Call in reverse direction
default: // All else is a mistake
typerr(t);
}
return this;
}
//------------------------------meet_offset------------------------------------
// Either is 'TOP' offset? Return the other offset!
// If either is different, return 'BOTTOM' offset
return _offset;
}
//------------------------------dual_offset------------------------------------
return _offset; // Map everything else into self
}
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
};
}
//------------------------------xadd_offset------------------------------------
// Adding to 'TOP' offset? Return 'TOP'!
// Adding to 'BOTTOM' offset? Return 'BOTTOM'!
// Addition overflows or "accidentally" equals to OffsetTop? Return 'BOTTOM'!
// assert( _offset >= 0 && _offset+offset >= 0, "" );
// It is possible to construct a negative offset during PhaseCCP
return (int)offset; // Sum valid offsets
}
//------------------------------add_offset-------------------------------------
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
}
//------------------------------dump2------------------------------------------
"TopPTR","AnyNull","Constant","NULL","NotNull","BotPTR"
};
#ifndef PRODUCT
}
#endif
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants
// TopPTR, Null, AnyNull, Constant are all singletons
}
}
//=============================================================================
// Convenience common pre-built types.
//------------------------------make-------------------------------------------
}
}
//------------------------------cast_to_ptr_type-------------------------------
}
//------------------------------get_con----------------------------------------
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 RawPtr
switch( t->base() ) { // switch on original type
case Bottom: // Ye Olde Default
return t;
case Top:
return this;
case AnyPtr: // Meeting to AnyPtrs
break;
}
}
case OopPtr:
case InstPtr:
case KlassPtr:
case AryPtr:
default: // All else is a mistake
typerr(t);
}
// Found an AnyPtr type vs self-RawPtr type
return TypeRawPtr::BOTTOM;
case TypePtr::NotNull: return TypePtr::make( AnyPtr, meet_ptr(TypePtr::NotNull), tp->meet_offset(0) );
default: ShouldNotReachHere();
}
return this;
}
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
}
//------------------------------add_offset-------------------------------------
if( offset == 0 ) return this; // No change
switch (_ptr) {
return this;
}
default: ShouldNotReachHere();
}
return NULL; // Lint noise
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
const TypeRawPtr *a = (const TypeRawPtr*)t;
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
}
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
else
}
#endif
//=============================================================================
// Convenience common pre-built type.
//------------------------------TypeOopPtr-------------------------------------
TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id )
_const_oop(o), _klass(k),
_is_ptr_to_narrowoop(false),
#ifdef _LP64
if (UseCompressedOops && _offset != 0) {
_is_ptr_to_narrowoop = true;
_is_ptr_to_narrowoop = true;
} else if (this->isa_aryptr()) {
} else if (klass()->is_instance_klass()) {
if (this->isa_klassptr()) {
// Perm objects don't use compressed references
// unsafe access
_is_ptr_to_narrowoop = true;
} else { // exclude unsafe ops
// Special hidden fields from the Class.
_is_ptr_to_narrowoop = true;
// Static fields
basic_elem_type == T_ARRAY);
} else {
// Instance fields which contains a compressed oop references.
basic_elem_type == T_ARRAY);
// Compile::find_alias_type() cast exactness on all types to verify
// that it does not affect alias type.
_is_ptr_to_narrowoop = true;
} else {
// Type for the copy start in LibraryCallKit::inline_native_clone().
_is_ptr_to_narrowoop = true;
}
}
}
}
}
#endif
}
//------------------------------make-------------------------------------------
int offset, int instance_id) {
bool xk = false;
}
//------------------------------cast_to_ptr_type-------------------------------
}
//-----------------------------cast_to_instance_id----------------------------
// There are no instances of a general oop.
// Return self unchanged.
return this;
}
//-----------------------------cast_to_exactness-------------------------------
// There is no such thing as an exact general oop.
// Return self unchanged.
return this;
}
//------------------------------as_klass_type----------------------------------
// Return the klass type corresponding to this instance or array type.
// It is the type that is loaded from an object of this type.
if (k == NULL || !k->is_java_klass())
return TypeKlassPtr::OBJECT;
else
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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
case Top:
return this;
default: // All else is a mistake
typerr(t);
case RawPtr:
case AnyPtr: {
// Found an AnyPtr type vs self-OopPtr type
case Null:
// else fall through:
case TopPTR:
case AnyNull: {
}
case BotPTR:
case NotNull:
default: typerr(t);
}
}
case OopPtr: { // Meeting to other OopPtrs
}
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
} // End of switch
return this; // Return the double constant
}
//------------------------------xdual------------------------------------------
// Dual of a pure heap pointer. No relevant klass or oop information.
return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id() );
}
//--------------------------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) {
if (klass->is_instance_klass()) {
// Element is an instance
bool klass_is_exact = false;
// Try to set klass_is_exact.
if (!klass_is_exact && klass_change
}
}
if (!klass_is_exact && try_for_exact
// Add a dependence; if concrete subclass added we need to recompile
klass_is_exact = true;
}
}
}
} else if (klass->is_obj_array_klass()) {
// Element is an object array. Recursively call ourself.
const TypeOopPtr *etype = TypeOopPtr::make_from_klass_common(klass->as_obj_array_klass()->element_klass(), false, try_for_exact);
// 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
// slam NULLs down in the subarrays.
return arr;
} else if (klass->is_type_array_klass()) {
// Element is an typeArray
// We used to pass NotNull in here, asserting that the array pointer
// is not-null. That was not true in general.
return arr;
} else {
return NULL;
}
}
//------------------------------make_from_constant-----------------------------
// Make a java pointer from an oop constant
if (o->is_method_data() || o->is_method()) {
// Treat much like a typeArray of bytes, like below, but fake the type...
} else if (o->is_cpcache()) {
// Treat much like a objArray, like below, but fake the type...
} else {
if (klass->is_instance_klass()) {
// Element is an instance
if (require_constant) {
if (!o->can_be_constant()) return NULL;
} else if (!o->should_be_constant()) {
}
return TypeInstPtr::make(o);
} else if (klass->is_obj_array_klass()) {
// Element is an object array. Recursively call ourself.
// 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
// slam NULLs down in the subarrays.
if (require_constant) {
if (!o->can_be_constant()) return NULL;
} else if (!o->should_be_constant()) {
}
} else if (klass->is_type_array_klass()) {
// Element is an typeArray
// We used to pass NotNull in here, asserting that the array pointer
// is not-null. That was not true in general.
if (require_constant) {
if (!o->can_be_constant()) return NULL;
} else if (!o->should_be_constant()) {
}
}
}
fatal("unhandled object type");
return NULL;
}
//------------------------------get_con----------------------------------------
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.
}
}
//-----------------------------filter------------------------------------------
// Do not allow interface-vs.-noninterface joins to collapse to top.
// Check for evil case of 'this' being a class and 'kills' expecting an
// interface. This can happen because the bytecodes do not contain
// enough type info to distinguish a Java-level interface variable
// from a Java-level object variable. If we meet 2 classes which
// both implement interface I, but their meet is at 'j/l/O' which
// doesn't implement I, we have no way to tell if the result should
// be 'I' or 'j/l/O'. Thus we'll pick 'j/l/O'. If this then flows
// into a Phi which "knows" it's an Interface type we'll have to
// uplift the type.
return kills; // Uplift to interface
return kills; // Uplift to interface
}
// If we have an interface-typed Phi or cast and we narrow to a class type,
// class-typed Phi and an interface flows in, it's possible that the meet &
// join report an interface back out. This isn't possible but happens
// because the type system doesn't interact well with interfaces.
// Happens in a CTW of rt.jar, 320-341, no extra flags
}
// Interface klass type could be exact in opposite to interface type,
}
return ft;
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
const TypeOopPtr *a = (const TypeOopPtr*)t;
if (_klass_is_exact != a->_klass_is_exact ||
_instance_id != a->_instance_id) return false;
} else {
}
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
return
}
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
switch( _offset ) {
case 0: break;
}
if (_instance_id == InstanceTop)
else if (_instance_id != InstanceBot)
}
#endif
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants
// detune optimizer to not generate constant oop + constant offset as a constant!
// TopPTR, Null, AnyNull, Constant are all singletons
}
//------------------------------add_offset-------------------------------------
}
//------------------------------meet_instance_id--------------------------------
// Either is 'TOP' instance? Return the other instance!
// If either is different, return 'BOTTOM' instance
return _instance_id;
}
//------------------------------dual_instance_id--------------------------------
return _instance_id; // Map everything else into self
}
//=============================================================================
// Convenience common pre-built types.
//------------------------------TypeInstPtr-------------------------------------
"cannot have constants with non-loaded klass");
};
//------------------------------make-------------------------------------------
ciKlass* k,
bool xk,
ciObject* o,
int offset,
int instance_id) {
k->is_method_klass(), "Must be for instance or method");
// Either const_oop() is NULL or else ptr is Constant
"constant pointers must have a value supplied" );
// Ptr is never Null
if (!UseExactTypes) xk = false;
// Note: This case includes meta-object constants, such as methods.
xk = true;
} else if (k->is_loaded()) {
}
// Now hash this baby
return result;
}
//------------------------------cast_to_ptr_type-------------------------------
// Reconstruct _sig info here since not a problem with later lazy
// construction, _sig will show up on demand.
}
//-----------------------------cast_to_exactness-------------------------------
if( klass_is_exact == _klass_is_exact ) return this;
if (!UseExactTypes) return this;
}
//-----------------------------cast_to_instance_id----------------------------
if( instance_id == _instance_id ) return this;
}
//------------------------------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
//
//
// Meet
// | Unloaded Class
// Object | TOP | AnyNull | Constant | NotNull | BOTTOM |
// ===================================================================
// TOP | ..........................Unloaded......................|
// AnyNull | U-AN |................Unloaded......................|
// Constant | ... O-NN .................................. | O-BOT |
// NotNull | ... O-NN .................................. | O-BOT |
// BOTTOM | ........................Object-BOTTOM ..................|
//
//
else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make( ptr, unloaded->klass(), false, NULL, off, instance_id ); }
else { return TypeInstPtr::NOTNULL; }
}
}
// Both are unloaded, not the same class, not Object
return TypeInstPtr::NOTNULL;
}
return TypeInstPtr::BOTTOM;
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 Pointer
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
case Top:
return this;
default: // All else is a mistake
typerr(t);
case AryPtr: { // All arrays inherit from Object class
switch (ptr) {
case TopPTR:
case AnyNull: // Fall 'down' to dual of object klass
} else {
// cannot subclass, so the meet has to fall badly below the centerline
}
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
// If 'this' (InstPtr) is above the centerline and it is Object class
// then we can subclass in the Java class hierarchy.
// that is, tp's array type is a subtype of my klass
}
}
// The other case cannot happen, since I cannot be a subtype of an array.
// The meet falls down to Object class below centerline.
default: typerr(t);
}
}
case OopPtr: { // Meeting to OopPtrs
// Found a OopPtr type vs self-InstPtr type
case TopPTR:
case AnyNull: {
}
case NotNull:
case BotPTR: {
}
default: typerr(t);
}
}
case AnyPtr: { // Meeting to AnyPtrs
// Found an AnyPtr type vs self-InstPtr type
case Null:
// else fall through to AnyNull
case TopPTR:
case AnyNull: {
}
case NotNull:
case BotPTR:
default: typerr(t);
}
}
/*
A-top }
/ | \ } Tops
B-top A-any C-top }
| / | \ | } Any-nulls
B-any | C-any }
| | |
B-con A-con C-con } constants; not comparable across classes
| | |
B-not | C-not }
| \ | / | } not-nulls
B-bot A-not C-bot }
\ | / } Bottoms
A-bot }
*/
case InstPtr: { // Meeting 2 Oops?
// Found an InstPtr sub-type vs self-InstPtr type
// 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()) {
}
// Classes require inspection in the Java klass hierarchy. Must be loaded.
// One of these classes has not been loaded
#ifndef PRODUCT
}
#endif
return unloaded_meet;
}
// Handle mixing oops and interfaces first.
this_klass = tmp;
}
if (tinst_klass->is_interface() &&
!(this_klass->is_interface() ||
// because we need a bottom for the interface hierarchy.
// Oop meets interface!
// See if the oop subtypes (implements) interface.
ciKlass *k;
bool xk;
// 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.
// If we are keeping this_klass, keep its exactness too.
} 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)
// Watch out for Constant vs. AnyNull interface.
}
// Find out which constant.
}
}
// Either oop vs oop or interface vs interface or interface vs Object
// !!! Here's how the symmetry requirement breaks down into invariants:
// If we split one up & one down AND they subtype, take the down man.
// If we split one up & one down AND they do NOT subtype, "fall hard".
// If both are up and they subtype, take the subtype class.
// If both are up and they do NOT subtype, "fall hard".
// If both are down and they subtype, take the supertype class.
// If both are down and they do NOT subtype, "fall hard".
// Constants treated as down.
// Now, reorder the above list; observe that both-down+subtype is also
// "fall hard"; "fall hard" becomes the default case:
// If we split one up & one down AND they subtype, take the down man.
// If both are up and they subtype, take the subtype class.
// If both are down and they subtype, "fall hard".
// If both are down and they do NOT subtype, "fall hard".
// If both are up and they do NOT subtype, "fall hard".
// If we split one up & one down AND they do NOT subtype, "fall hard".
// If a proper subtype is exact, and we return it, we return it exactly.
// If a proper supertype is exact, there can be no subtyping relationship!
// If both types are equal to the subtype, exactness is and-ed below the
// centerline and or-ed above it. (N.B. Constants are always exact.)
// Check for subtyping:
bool subtype_exact = false;
}
if( subtype ) {
} else {
}
}
// Check for classes now being equal
// 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).
o = this_oop;
else if (above_centerline(this ->_ptr))
o = tinst_oop;
o = this_oop;
else
}
} // 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.
// Now we find the LCA of Java classes
} // End of case InstPtr
case KlassPtr:
return TypeInstPtr::BOTTOM;
} // End of switch
return this; // Return the double constant
}
//------------------------java_mirror_type--------------------------------------
// must be a singleton type
// must be of type java.lang.Class
}
//------------------------------xdual------------------------------------------
// Dual: do NOT dual on klasses. This means I do NOT understand the Java
// inheritance mechanism.
return new TypeInstPtr( dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id() );
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
const TypeInstPtr *p = t->is_instptr();
return
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
return hash;
}
//------------------------------dump2------------------------------------------
// Dump oop Type
#ifndef PRODUCT
// Print the name of the klass.
switch( _ptr ) {
case Constant:
// TO DO: Make CI print the hex address of the underlying oop.
if (WizardMode || Verbose) {
}
case BotPTR:
if (!WizardMode && !Verbose) {
break;
}
case TopPTR:
case AnyNull:
case NotNull:
break;
}
if( _offset ) { // Dump offset, if any
}
if (_instance_id == InstanceTop)
else if (_instance_id != InstanceBot)
}
#endif
//------------------------------add_offset-------------------------------------
}
//=============================================================================
// Convenience common pre-built types.
//------------------------------make-------------------------------------------
const TypeAryPtr *TypeAryPtr::make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id ) {
"integral arrays must be pre-equipped with a class");
}
//------------------------------make-------------------------------------------
const TypeAryPtr *TypeAryPtr::make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id ) {
"integral arrays must be pre-equipped with a class");
}
//------------------------------cast_to_ptr_type-------------------------------
}
//-----------------------------cast_to_exactness-------------------------------
if( klass_is_exact == _klass_is_exact ) return this;
if (!UseExactTypes) return this;
}
//-----------------------------cast_to_instance_id----------------------------
if( instance_id == _instance_id ) return this;
}
//-----------------------------narrow_size_type-------------------------------
// Local cache for arrayOopDesc::max_array_length(etype),
// which is kind of slow (and cached elsewhere by other users).
if (res == 0) {
switch (etype) {
case T_NARROWOOP:
break;
case T_CONFLICT:
case T_ILLEGAL:
case T_VOID:
}
}
return res;
}
// Narrow the given size type to the index range for the given array base type.
// Return NULL if the resulting int type becomes empty.
//if (index_not_size) --max_hi; // type of a valid array index, FTR
bool chg = false;
// Negative length arrays will produce weird intermediate dead fast-path code
if (!chg)
return size;
}
//-------------------------------cast_to_size----------------------------------
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
const TypeAryPtr *p = t->is_aryptr();
return
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 Pointer
switch (t->base()) { // switch on original type
// Mixing ints & oops happens when javac reuses local variables
case Int:
case Long:
case FloatTop:
case FloatCon:
case FloatBot:
case DoubleTop:
case DoubleCon:
case DoubleBot:
case NarrowOop:
case Bottom: // Ye Olde Default
case Top:
return this;
default: // All else is a mistake
typerr(t);
case OopPtr: { // Meeting to OopPtrs
// Found a OopPtr type vs self-AryPtr type
case TopPTR:
case AnyNull: {
}
case BotPTR:
case NotNull: {
}
default: ShouldNotReachHere();
}
}
case AnyPtr: { // Meeting two AnyPtrs
// Found an AnyPtr type vs self-AryPtr type
case TopPTR:
return this;
case BotPTR:
case NotNull:
case Null:
// else fall through to AnyNull
case AnyNull: {
}
default: ShouldNotReachHere();
}
}
case AryPtr: { // Meeting 2 references?
// Integral array element types have irrelevant lattice relations.
// It is the klass that determines array layout, not the element type.
lazy_klass = _klass;
} else {
// Something like byte[int+] meets char[int+].
// This must fall to bottom, not (int[-128..65535])[int+].
}
} else // Non integral arrays.
// Must fall to bottom if exact klasses in upper lattice
// are not equal or super klass is exact.
// meet with top[] and bottom[] are processed further down:
// both are exact and not equal:
// 'tap' is exact and super or unrelated:
// 'this' is exact and super or unrelated:
}
bool xk = false;
case AnyNull:
case TopPTR:
// Compute new klass on demand, do not use tap->_klass
case Constant: {
o = NULL;
} else {
xk = true;
}
} else if( above_centerline(_ptr) ) {
xk = true;
} else {
// Only precise for identical arrays
}
}
case NotNull:
case BotPTR:
// Compute new klass on demand, do not use tap->_klass
if (above_centerline(this->_ptr))
xk = this->_klass_is_exact;
default: ShouldNotReachHere();
}
}
// All arrays inherit from Object class
case InstPtr: {
switch (ptr) {
case TopPTR:
case AnyNull: // Fall 'down' to dual of object klass
} else {
// cannot subclass, so the meet has to fall badly below the centerline
}
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
// If 'tp' is above the centerline and it is Object class
// then we can subclass in the Java class hierarchy.
// that is, my array type is a subtype of 'tp' klass
}
}
// The other case cannot happen, since t cannot be a subtype of an array.
// The meet falls down to Object class below centerline.
default: typerr(t);
}
}
case KlassPtr:
return TypeInstPtr::BOTTOM;
}
return this; // Lint noise
}
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id() );
}
//----------------------interface_vs_oop---------------------------------------
#ifdef ASSERT
if (t_aryptr) {
}
return false;
}
#endif
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
switch( _ptr ) {
case Constant:
break;
case BotPTR:
if (!WizardMode && !Verbose) {
break;
}
case TopPTR:
case AnyNull:
case NotNull:
break;
}
if( _offset != 0 ) {
else {
}
}
if (_instance_id == InstanceTop)
else if (_instance_id != InstanceBot)
}
#endif
return TypeOopPtr::empty();
}
//------------------------------add_offset-------------------------------------
}
//=============================================================================
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
}
return false;
}
}
return false;
}
}
}
//------------------------------xmeet------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 AnyPtr:
case RawPtr:
case OopPtr:
case InstPtr:
case KlassPtr:
case AryPtr:
case Bottom: // Ye Olde Default
case Top:
return this;
case NarrowOop: {
}
return result;
}
default: // All else is a mistake
typerr(t);
} // End of switch
return this;
}
return new TypeNarrowOop(odual);
}
if (kills->isa_narrowoop()) {
}
return ft;
return ft;
} else {
}
}
}
#ifndef PRODUCT
}
#endif
//=============================================================================
// Convenience common pre-built types.
// Not-null object klass or below
//------------------------------TypeKlasPtr------------------------------------
}
//------------------------------make-------------------------------------------
// ptr to klass 'k', if Constant, or possibly to a sub-klass if not a Constant
k->is_method_klass(), "Incorrect type of klass oop");
TypeKlassPtr *r =
return r;
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
const TypeKlassPtr *p = t->is_klassptr();
return
TypeOopPtr::eq(p);
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
}
//----------------------compute_klass------------------------------------------
// Compute the defining klass for this class
// Compute _klass based on element type.
if (el->isa_narrowoop()) {
}
// Get element klass
// Compute array klass from element klass
// Compute array klass from element klass
// If element type is something like bottom[], k_elem will be null.
// element type of Bottom occurs from meet of basic type
// and object; Top occurs when doing join on Bottom.
// Leave k_ary at NULL.
} else {
// Cannot compute array klass directly from basic type,
// since subtypes of TypeInt all have basic type T_INT.
#ifdef ASSERT
// Check simple cases when verifying klass.
} else {
return _klass; // just return specified klass
}
}
#endif
"integral arrays must be pre-equipped with a class");
// Compute array klass directly from basic type
}
return k_ary;
}
//------------------------------klass------------------------------------------
// Return the defining klass for this class
// Oops, need to compute _klass and cache it
// The _klass field acts as a cache of the underlying
// ciKlass for this array type. In order to set the field,
// we need to cast away const-ness.
//
// IMPORTANT NOTE: we *never* set the _klass field for the
// type TypeAryPtr::OOPS. This Type is shared between all
// active compilations. However, the ciKlass which represents
// this Type is *not* shared between compilations, so caching
// this value would result in fetching a dangling pointer.
//
// Recomputing the underlying ciKlass for each request is
// a bit less efficient than caching, but calls to
// TypeAryPtr::OOPS->klass() are not common enough to matter.
((TypeAryPtr*)this)->_is_ptr_to_narrowoop = true;
}
}
return k_ary;
}
//------------------------------add_offset-------------------------------------
// Access internals of klass object
}
//------------------------------cast_to_ptr_type-------------------------------
}
//-----------------------------cast_to_exactness-------------------------------
if( klass_is_exact == _klass_is_exact ) return this;
if (!UseExactTypes) return this;
}
//-----------------------------as_instance_type--------------------------------
// Corresponding type for an instance of the given class.
// It will be NotNull, and exact if and only if the klass type is exact.
//return TypeInstPtr::make(TypePtr::NotNull, k, xk, NULL, 0);
}
//------------------------------xmeet------------------------------------------
// Compute the MEET of two types, return a new Type object.
// 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 Pointer
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
case Top:
return this;
default: // All else is a mistake
typerr(t);
case OopPtr: { // Meeting to OopPtrs
// Found a OopPtr type vs self-KlassPtr type
case TopPTR:
case AnyNull:
case BotPTR:
case NotNull:
default: typerr(t);
}
}
case AnyPtr: { // Meeting to AnyPtrs
// Found an AnyPtr type vs self-KlassPtr type
case TopPTR:
return this;
case Null:
case AnyNull:
case BotPTR:
case NotNull:
default: typerr(t);
}
}
case AryPtr: // Meet with AryPtr
case InstPtr: // Meet with InstPtr
return TypeInstPtr::BOTTOM;
//
// A-top }
// / | \ } Tops
// B-top A-any C-top }
// | / | \ | } Any-nulls
// B-any | C-any }
// | | |
// B-con A-con C-con } constants; not comparable across classes
// | | |
// B-not | C-not }
// | \ | / | } not-nulls
// B-bot A-not C-bot }
// \ | / } Bottoms
// A-bot }
//
case KlassPtr: { // Meet two KlassPtr types
// 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
}
// Classes require inspection in the Java klass hierarchy. Must be loaded.
// 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())) &&
}
// If 'tinst' type is above the centerline and is a superclass of the
// other, we can treat 'tinst' as having the same type as the other.
}
// Check for classes now being equal
// 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).
o = this_oop;
else if (above_centerline(this->ptr()))
o = tkls_oop;
o = this_oop;
else
}
} // 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.
// Now we find the LCA of Java classes
} // End of case KlassPtr
} // End of switch
return this; // Return the double constant
}
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
}
//------------------------------dump2------------------------------------------
// Dump Klass Type
#ifndef PRODUCT
switch( _ptr ) {
case Constant:
case NotNull:
{
if( name ) {
} else {
}
}
case BotPTR:
case TopPTR:
case AnyNull:
break;
}
if( _offset ) { // Dump offset, if any
}
}
#endif
//=============================================================================
// Convenience common pre-built types.
//------------------------------make-------------------------------------------
}
//------------------------------make-------------------------------------------
} else {
}
return tf;
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
// 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 Func
switch (t->base()) { // switch on original type
case Bottom: // Ye Olde Default
return t;
default: // All else is a mistake
typerr(t);
case Top:
break;
}
return this; // Return the double constant
}
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
return this;
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
}
//------------------------------dump2------------------------------------------
// Dump Function Type
#ifndef PRODUCT
else {
uint i;
}
}
if( !depth || d[this] ) { // Check for recursive dump
return;
}
d.Insert((void*)this,(void*)this); // Stop recursion
}
}
//------------------------------print_flattened--------------------------------
// Print a 'flattened' signature
"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"
};
else {
uint i;
}
}
#endif
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants (Ldi nodes). Singletons are integer, float or double constants
// or a single symbol.
return false; // Never a singleton
}
return false; // Never empty
}
return T_VOID;
}
}