duke@435: /* coleenp@5614: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_OPTO_TYPE_HPP stefank@2314: #define SHARE_VM_OPTO_TYPE_HPP stefank@2314: stefank@2314: #include "libadt/port.hpp" stefank@2314: #include "opto/adlcVMDeps.hpp" stefank@2314: #include "runtime/handles.hpp" stefank@2314: duke@435: // Portions of code courtesy of Clifford Click duke@435: duke@435: // Optimization - Graph Style duke@435: duke@435: duke@435: // This class defines a Type lattice. The lattice is used in the constant duke@435: // propagation algorithms, and for some type-checking of the iloc code. duke@435: // Basic types include RSD's (lower bound, upper bound, stride for integers), duke@435: // float & double precision constants, sets of data-labels and code-labels. duke@435: // The complete lattice is described below. Subtypes have no relationship to duke@435: // up or down in the lattice; that is entirely determined by the behavior of duke@435: // the MEET/JOIN functions. duke@435: duke@435: class Dict; duke@435: class Type; duke@435: class TypeD; duke@435: class TypeF; duke@435: class TypeInt; duke@435: class TypeLong; roland@4159: class TypeNarrowPtr; roland@4159: class TypeNarrowOop; roland@4159: class TypeNarrowKlass; duke@435: class TypeAry; duke@435: class TypeTuple; kvn@3882: class TypeVect; kvn@3882: class TypeVectS; kvn@3882: class TypeVectD; kvn@3882: class TypeVectX; kvn@3882: class TypeVectY; duke@435: class TypePtr; duke@435: class TypeRawPtr; duke@435: class TypeOopPtr; duke@435: class TypeInstPtr; duke@435: class TypeAryPtr; roland@6043: class TypeKlassPtr; coleenp@4037: class TypeMetadataPtr; duke@435: duke@435: //------------------------------Type------------------------------------------- duke@435: // Basic Type object, represents a set of primitive Values. duke@435: // Types are hash-cons'd into a private class dictionary, so only one of each duke@435: // different kind of Type exists. Types are never modified after creation, so duke@435: // all their interesting fields are constant. duke@435: class Type { never@3138: friend class VMStructs; never@3138: duke@435: public: duke@435: enum TYPES { duke@435: Bad=0, // Type check duke@435: Control, // Control of code (not in lattice) duke@435: Top, // Top of the lattice duke@435: Int, // Integer range (lo-hi) duke@435: Long, // Long integer range (lo-hi) duke@435: Half, // Placeholder half of doubleword coleenp@548: NarrowOop, // Compressed oop pointer roland@4159: NarrowKlass, // Compressed klass pointer duke@435: duke@435: Tuple, // Method signature or object layout duke@435: Array, // Array types kvn@3882: VectorS, // 32bit Vector types kvn@3882: VectorD, // 64bit Vector types kvn@3882: VectorX, // 128bit Vector types kvn@3882: VectorY, // 256bit Vector types duke@435: duke@435: AnyPtr, // Any old raw, klass, inst, or array pointer duke@435: RawPtr, // Raw (non-oop) pointers duke@435: OopPtr, // Any and all Java heap entities duke@435: InstPtr, // Instance pointers (non-array objects) duke@435: AryPtr, // Array pointers coleenp@4037: // (Ptr order matters: See is_ptr, isa_ptr, is_oopptr, isa_oopptr.) coleenp@4037: coleenp@4037: MetadataPtr, // Generic metadata duke@435: KlassPtr, // Klass pointers duke@435: duke@435: Function, // Function signature duke@435: Abio, // Abstract I/O duke@435: Return_Address, // Subroutine return address duke@435: Memory, // Abstract store duke@435: FloatTop, // No float value duke@435: FloatCon, // Floating point constant duke@435: FloatBot, // Any float value duke@435: DoubleTop, // No double value duke@435: DoubleCon, // Double precision constant duke@435: DoubleBot, // Any double value duke@435: Bottom, // Bottom of lattice duke@435: lastype // Bogus ending type (not in lattice) duke@435: }; duke@435: duke@435: // Signal values for offsets from a base pointer duke@435: enum OFFSET_SIGNALS { duke@435: OffsetTop = -2000000000, // undefined offset duke@435: OffsetBot = -2000000001 // any possible offset duke@435: }; duke@435: duke@435: // Min and max WIDEN values. duke@435: enum WIDEN { duke@435: WidenMin = 0, duke@435: WidenMax = 3 duke@435: }; duke@435: duke@435: private: coleenp@4037: typedef struct { coleenp@4037: const TYPES dual_type; coleenp@4037: const BasicType basic_type; coleenp@4037: const char* msg; coleenp@4037: const bool isa_oop; coleenp@4037: const int ideal_reg; coleenp@4037: const relocInfo::relocType reloc; coleenp@4037: } TypeInfo; coleenp@4037: duke@435: // Dictionary of types shared among compilations. duke@435: static Dict* _shared_type_dict; coleenp@4037: static TypeInfo _type_info[]; duke@435: duke@435: static int uhash( const Type *const t ); duke@435: // Structural equality check. Assumes that cmp() has already compared duke@435: // the _base types and thus knows it can cast 't' appropriately. duke@435: virtual bool eq( const Type *t ) const; duke@435: duke@435: // Top-level hash-table of types duke@435: static Dict *type_dict() { duke@435: return Compile::current()->type_dict(); duke@435: } duke@435: duke@435: // DUAL operation: reflect around lattice centerline. Used instead of duke@435: // join to ensure my lattice is symmetric up and down. Dual is computed duke@435: // lazily, on demand, and cached in _dual. duke@435: const Type *_dual; // Cached dual value duke@435: // Table for efficient dualing of base types duke@435: static const TYPES dual_type[lastype]; duke@435: roland@5991: #ifdef ASSERT roland@5991: // One type is interface, the other is oop roland@5991: virtual bool interface_vs_oop_helper(const Type *t) const; roland@5991: #endif roland@5991: roland@6313: const Type *meet_helper(const Type *t, bool include_speculative) const; roland@6313: duke@435: protected: duke@435: // Each class of type is also identified by its base. duke@435: const TYPES _base; // Enum of Types type duke@435: duke@435: Type( TYPES t ) : _dual(NULL), _base(t) {} // Simple types duke@435: // ~Type(); // Use fast deallocation duke@435: const Type *hashcons(); // Hash-cons the type roland@6313: virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; roland@6313: const Type *join_helper(const Type *t, bool include_speculative) const { roland@6313: return dual()->meet_helper(t->dual(), include_speculative)->dual(); roland@6313: } duke@435: duke@435: public: duke@435: coleenp@5614: inline void* operator new( size_t x ) throw() { duke@435: Compile* compile = Compile::current(); duke@435: compile->set_type_last_size(x); duke@435: void *temp = compile->type_arena()->Amalloc_D(x); duke@435: compile->set_type_hwm(temp); duke@435: return temp; duke@435: } duke@435: inline void operator delete( void* ptr ) { duke@435: Compile* compile = Compile::current(); duke@435: compile->type_arena()->Afree(ptr,compile->type_last_size()); duke@435: } duke@435: duke@435: // Initialize the type system for a particular compilation. duke@435: static void Initialize(Compile* compile); duke@435: duke@435: // Initialize the types shared by all compilations. duke@435: static void Initialize_shared(Compile* compile); duke@435: duke@435: TYPES base() const { duke@435: assert(_base > Bad && _base < lastype, "sanity"); duke@435: return _base; duke@435: } duke@435: duke@435: // Create a new hash-consd type duke@435: static const Type *make(enum TYPES); duke@435: // Test for equivalence of types duke@435: static int cmp( const Type *const t1, const Type *const t2 ); duke@435: // Test for higher or equal in lattice roland@6313: // Variant that drops the speculative part of the types roland@6313: int higher_equal(const Type *t) const { roland@6313: return !cmp(meet(t),t->remove_speculative()); roland@6313: } roland@6313: // Variant that keeps the speculative part of the types roland@6313: int higher_equal_speculative(const Type *t) const { roland@6313: return !cmp(meet_speculative(t),t); roland@6313: } duke@435: duke@435: // MEET operation; lower in lattice. roland@6313: // Variant that drops the speculative part of the types roland@6313: const Type *meet(const Type *t) const { roland@6313: return meet_helper(t, false); roland@6313: } roland@6313: // Variant that keeps the speculative part of the types roland@6313: const Type *meet_speculative(const Type *t) const { roland@6313: return meet_helper(t, true); roland@6313: } duke@435: // WIDEN: 'widens' for Ints and other range types never@1444: virtual const Type *widen( const Type *old, const Type* limit ) const { return this; } duke@435: // NARROW: complement for widen, used by pessimistic phases duke@435: virtual const Type *narrow( const Type *old ) const { return this; } duke@435: duke@435: // DUAL operation: reflect around lattice centerline. Used instead of duke@435: // join to ensure my lattice is symmetric up and down. duke@435: const Type *dual() const { return _dual; } duke@435: duke@435: // Compute meet dependent on base type duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: duke@435: // JOIN operation; higher in lattice. Done by finding the dual of the duke@435: // meet of the dual of the 2 inputs. roland@6313: // Variant that drops the speculative part of the types roland@6313: const Type *join(const Type *t) const { roland@6313: return join_helper(t, false); roland@6313: } roland@6313: // Variant that keeps the speculative part of the types roland@6313: const Type *join_speculative(const Type *t) const { roland@6313: return join_helper(t, true); roland@6313: } duke@435: duke@435: // Modified version of JOIN adapted to the needs Node::Value. duke@435: // Normalizes all empty values to TOP. Does not kill _widen bits. duke@435: // Currently, it also works around limitations involving interface types. roland@6313: // Variant that drops the speculative part of the types roland@6313: const Type *filter(const Type *kills) const { roland@6313: return filter_helper(kills, false); roland@6313: } roland@6313: // Variant that keeps the speculative part of the types roland@6313: const Type *filter_speculative(const Type *kills) const { roland@6313: return filter_helper(kills, true); roland@6313: } duke@435: kvn@1255: #ifdef ASSERT kvn@1255: // One type is interface, the other is oop kvn@1255: virtual bool interface_vs_oop(const Type *t) const; kvn@1255: #endif kvn@1255: coleenp@548: // Returns true if this pointer points at memory which contains a kvn@598: // compressed oop references. kvn@598: bool is_ptr_to_narrowoop() const; roland@4159: bool is_ptr_to_narrowklass() const; coleenp@548: kvn@5110: bool is_ptr_to_boxing_obj() const; kvn@5110: kvn@5110: duke@435: // Convenience access duke@435: float getf() const; duke@435: double getd() const; duke@435: duke@435: const TypeInt *is_int() const; duke@435: const TypeInt *isa_int() const; // Returns NULL if not an Int duke@435: const TypeLong *is_long() const; duke@435: const TypeLong *isa_long() const; // Returns NULL if not a Long twisti@4313: const TypeD *isa_double() const; // Returns NULL if not a Double{Top,Con,Bot} duke@435: const TypeD *is_double_constant() const; // Asserts it is a DoubleCon duke@435: const TypeD *isa_double_constant() const; // Returns NULL if not a DoubleCon twisti@4313: const TypeF *isa_float() const; // Returns NULL if not a Float{Top,Con,Bot} duke@435: const TypeF *is_float_constant() const; // Asserts it is a FloatCon duke@435: const TypeF *isa_float_constant() const; // Returns NULL if not a FloatCon duke@435: const TypeTuple *is_tuple() const; // Collection of fields, NOT a pointer duke@435: const TypeAry *is_ary() const; // Array, NOT array pointer kvn@3882: const TypeVect *is_vect() const; // Vector kvn@3882: const TypeVect *isa_vect() const; // Returns NULL if not a Vector duke@435: const TypePtr *is_ptr() const; // Asserts it is a ptr type duke@435: const TypePtr *isa_ptr() const; // Returns NULL if not ptr type coleenp@548: const TypeRawPtr *isa_rawptr() const; // NOT Java oop coleenp@548: const TypeRawPtr *is_rawptr() const; // Asserts is rawptr kvn@598: const TypeNarrowOop *is_narrowoop() const; // Java-style GC'd pointer kvn@598: const TypeNarrowOop *isa_narrowoop() const; // Returns NULL if not oop ptr type roland@4159: const TypeNarrowKlass *is_narrowklass() const; // compressed klass pointer roland@4159: const TypeNarrowKlass *isa_narrowklass() const;// Returns NULL if not oop ptr type coleenp@548: const TypeOopPtr *isa_oopptr() const; // Returns NULL if not oop ptr type coleenp@548: const TypeOopPtr *is_oopptr() const; // Java-style GC'd pointer coleenp@548: const TypeInstPtr *isa_instptr() const; // Returns NULL if not InstPtr coleenp@548: const TypeInstPtr *is_instptr() const; // Instance coleenp@548: const TypeAryPtr *isa_aryptr() const; // Returns NULL if not AryPtr coleenp@548: const TypeAryPtr *is_aryptr() const; // Array oop coleenp@4037: coleenp@4037: const TypeMetadataPtr *isa_metadataptr() const; // Returns NULL if not oop ptr type coleenp@4037: const TypeMetadataPtr *is_metadataptr() const; // Java-style GC'd pointer coleenp@4037: const TypeKlassPtr *isa_klassptr() const; // Returns NULL if not KlassPtr coleenp@4037: const TypeKlassPtr *is_klassptr() const; // assert if not KlassPtr coleenp@4037: duke@435: virtual bool is_finite() const; // Has a finite value duke@435: virtual bool is_nan() const; // Is not a number (NaN) duke@435: kvn@656: // Returns this ptr type or the equivalent ptr type for this compressed pointer. kvn@656: const TypePtr* make_ptr() const; never@1262: never@1262: // Returns this oopptr type or the equivalent oopptr type for this compressed pointer. never@1262: // Asserts if the underlying type is not an oopptr or narrowoop. never@1262: const TypeOopPtr* make_oopptr() const; never@1262: kvn@656: // Returns this compressed pointer or the equivalent compressed version kvn@656: // of this pointer type. kvn@656: const TypeNarrowOop* make_narrowoop() const; kvn@656: roland@4159: // Returns this compressed klass pointer or the equivalent roland@4159: // compressed version of this pointer type. roland@4159: const TypeNarrowKlass* make_narrowklass() const; roland@4159: duke@435: // Special test for register pressure heuristic duke@435: bool is_floatingpoint() const; // True if Float or Double base type duke@435: duke@435: // Do you have memory, directly or through a tuple? duke@435: bool has_memory( ) const; duke@435: duke@435: // TRUE if type is a singleton duke@435: virtual bool singleton(void) const; duke@435: duke@435: // TRUE if type is above the lattice centerline, and is therefore vacuous duke@435: virtual bool empty(void) const; duke@435: duke@435: // Return a hash for this type. The hash function is public so ConNode duke@435: // (constants) can hash on their constant, which is represented by a Type. duke@435: virtual int hash() const; duke@435: duke@435: // Map ideal registers (machine types) to ideal types duke@435: static const Type *mreg2type[]; duke@435: duke@435: // Printing, statistics duke@435: #ifndef PRODUCT duke@435: void dump_on(outputStream *st) const; duke@435: void dump() const { duke@435: dump_on(tty); duke@435: } duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; duke@435: static void dump_stats(); duke@435: #endif duke@435: void typerr(const Type *t) const; // Mixing types error duke@435: duke@435: // Create basic type duke@435: static const Type* get_const_basic_type(BasicType type) { duke@435: assert((uint)type <= T_CONFLICT && _const_basic_type[type] != NULL, "bad type"); duke@435: return _const_basic_type[type]; duke@435: } duke@435: duke@435: // Mapping to the array element's basic type. duke@435: BasicType array_element_basic_type() const; duke@435: duke@435: // Create standard type for a ciType: duke@435: static const Type* get_const_type(ciType* type); duke@435: duke@435: // Create standard zero value: duke@435: static const Type* get_zero_type(BasicType type) { duke@435: assert((uint)type <= T_CONFLICT && _zero_type[type] != NULL, "bad type"); duke@435: return _zero_type[type]; duke@435: } duke@435: duke@435: // Report if this is a zero value (not top). duke@435: bool is_zero_type() const { duke@435: BasicType type = basic_type(); duke@435: if (type == T_VOID || type >= T_CONFLICT) duke@435: return false; duke@435: else duke@435: return (this == _zero_type[type]); duke@435: } duke@435: duke@435: // Convenience common pre-built types. duke@435: static const Type *ABIO; duke@435: static const Type *BOTTOM; duke@435: static const Type *CONTROL; duke@435: static const Type *DOUBLE; duke@435: static const Type *FLOAT; duke@435: static const Type *HALF; duke@435: static const Type *MEMORY; duke@435: static const Type *MULTI; duke@435: static const Type *RETURN_ADDRESS; duke@435: static const Type *TOP; duke@435: duke@435: // Mapping from compiler type to VM BasicType coleenp@4037: BasicType basic_type() const { return _type_info[_base].basic_type; } coleenp@4037: int ideal_reg() const { return _type_info[_base].ideal_reg; } coleenp@4037: const char* msg() const { return _type_info[_base].msg; } coleenp@4037: bool isa_oop_ptr() const { return _type_info[_base].isa_oop; } coleenp@4037: relocInfo::relocType reloc() const { return _type_info[_base].reloc; } duke@435: duke@435: // Mapping from CI type system to compiler type: duke@435: static const Type* get_typeflow_type(ciType* type); duke@435: vlivanov@5658: static const Type* make_from_constant(ciConstant constant, vlivanov@5658: bool require_constant = false, vlivanov@5658: bool is_autobox_cache = false); vlivanov@5658: roland@5991: // Speculative type. See TypeInstPtr roland@6380: virtual const TypeOopPtr* speculative() const { return NULL; } roland@5991: virtual ciKlass* speculative_type() const { return NULL; } roland@6313: const Type* maybe_remove_speculative(bool include_speculative) const; roland@6313: virtual const Type* remove_speculative() const { return this; } roland@5991: roland@6380: virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const { roland@6380: return exact_kls != NULL; roland@6380: } roland@6380: duke@435: private: duke@435: // support arrays duke@435: static const BasicType _basic_type[]; duke@435: static const Type* _zero_type[T_CONFLICT+1]; duke@435: static const Type* _const_basic_type[T_CONFLICT+1]; duke@435: }; duke@435: duke@435: //------------------------------TypeF------------------------------------------ duke@435: // Class of Float-Constant Types. duke@435: class TypeF : public Type { duke@435: TypeF( float f ) : Type(FloatCon), _f(f) {}; duke@435: public: duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: virtual bool singleton(void) const; // TRUE if type is a singleton duke@435: virtual bool empty(void) const; // TRUE if type is vacuous duke@435: public: duke@435: const float _f; // Float constant duke@435: duke@435: static const TypeF *make(float f); duke@435: duke@435: virtual bool is_finite() const; // Has a finite value duke@435: virtual bool is_nan() const; // Is not a number (NaN) duke@435: duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: // Convenience common pre-built types. duke@435: static const TypeF *ZERO; // positive zero only duke@435: static const TypeF *ONE; duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------TypeD------------------------------------------ duke@435: // Class of Double-Constant Types. duke@435: class TypeD : public Type { duke@435: TypeD( double d ) : Type(DoubleCon), _d(d) {}; duke@435: public: duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: virtual bool singleton(void) const; // TRUE if type is a singleton duke@435: virtual bool empty(void) const; // TRUE if type is vacuous duke@435: public: duke@435: const double _d; // Double constant duke@435: duke@435: static const TypeD *make(double d); duke@435: duke@435: virtual bool is_finite() const; // Has a finite value duke@435: virtual bool is_nan() const; // Is not a number (NaN) duke@435: duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: // Convenience common pre-built types. duke@435: static const TypeD *ZERO; // positive zero only duke@435: static const TypeD *ONE; duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------TypeInt---------------------------------------- duke@435: // Class of integer ranges, the set of integers between a lower bound and an duke@435: // upper bound, inclusive. duke@435: class TypeInt : public Type { duke@435: TypeInt( jint lo, jint hi, int w ); roland@6313: protected: roland@6313: virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; roland@6313: duke@435: public: rbackman@6375: typedef jint NativeType; duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: virtual bool singleton(void) const; // TRUE if type is a singleton duke@435: virtual bool empty(void) const; // TRUE if type is vacuous duke@435: const jint _lo, _hi; // Lower bound, upper bound duke@435: const short _widen; // Limit on times we widen this sucker duke@435: duke@435: static const TypeInt *make(jint lo); duke@435: // must always specify w duke@435: static const TypeInt *make(jint lo, jint hi, int w); duke@435: duke@435: // Check for single integer duke@435: int is_con() const { return _lo==_hi; } duke@435: bool is_con(int i) const { return is_con() && _lo == i; } duke@435: jint get_con() const { assert( is_con(), "" ); return _lo; } duke@435: duke@435: virtual bool is_finite() const; // Has a finite value duke@435: duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. never@1444: virtual const Type *widen( const Type *t, const Type* limit_type ) const; duke@435: virtual const Type *narrow( const Type *t ) const; duke@435: // Do not kill _widen bits. duke@435: // Convenience common pre-built types. duke@435: static const TypeInt *MINUS_1; duke@435: static const TypeInt *ZERO; duke@435: static const TypeInt *ONE; duke@435: static const TypeInt *BOOL; duke@435: static const TypeInt *CC; duke@435: static const TypeInt *CC_LT; // [-1] == MINUS_1 duke@435: static const TypeInt *CC_GT; // [1] == ONE duke@435: static const TypeInt *CC_EQ; // [0] == ZERO duke@435: static const TypeInt *CC_LE; // [-1,0] duke@435: static const TypeInt *CC_GE; // [0,1] == BOOL (!) duke@435: static const TypeInt *BYTE; twisti@1059: static const TypeInt *UBYTE; duke@435: static const TypeInt *CHAR; duke@435: static const TypeInt *SHORT; duke@435: static const TypeInt *POS; duke@435: static const TypeInt *POS1; duke@435: static const TypeInt *INT; duke@435: static const TypeInt *SYMINT; // symmetric range [-max_jint..max_jint] rbackman@6375: static const TypeInt *TYPE_DOMAIN; // alias for TypeInt::INT rbackman@6375: rbackman@6375: static const TypeInt *as_self(const Type *t) { return t->is_int(); } duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: duke@435: //------------------------------TypeLong--------------------------------------- duke@435: // Class of long integer ranges, the set of integers between a lower bound and duke@435: // an upper bound, inclusive. duke@435: class TypeLong : public Type { duke@435: TypeLong( jlong lo, jlong hi, int w ); roland@6313: protected: roland@6313: // Do not kill _widen bits. roland@6313: virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; duke@435: public: rbackman@6375: typedef jlong NativeType; duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: virtual bool singleton(void) const; // TRUE if type is a singleton duke@435: virtual bool empty(void) const; // TRUE if type is vacuous duke@435: public: duke@435: const jlong _lo, _hi; // Lower bound, upper bound duke@435: const short _widen; // Limit on times we widen this sucker duke@435: duke@435: static const TypeLong *make(jlong lo); duke@435: // must always specify w duke@435: static const TypeLong *make(jlong lo, jlong hi, int w); duke@435: duke@435: // Check for single integer duke@435: int is_con() const { return _lo==_hi; } rasbold@580: bool is_con(int i) const { return is_con() && _lo == i; } duke@435: jlong get_con() const { assert( is_con(), "" ); return _lo; } duke@435: duke@435: virtual bool is_finite() const; // Has a finite value duke@435: rbackman@6375: duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. never@1444: virtual const Type *widen( const Type *t, const Type* limit_type ) const; duke@435: virtual const Type *narrow( const Type *t ) const; duke@435: // Convenience common pre-built types. duke@435: static const TypeLong *MINUS_1; duke@435: static const TypeLong *ZERO; duke@435: static const TypeLong *ONE; duke@435: static const TypeLong *POS; duke@435: static const TypeLong *LONG; duke@435: static const TypeLong *INT; // 32-bit subrange [min_jint..max_jint] duke@435: static const TypeLong *UINT; // 32-bit unsigned [0..max_juint] rbackman@6375: static const TypeLong *TYPE_DOMAIN; // alias for TypeLong::LONG rbackman@6375: rbackman@6375: // static convenience methods. rbackman@6375: static const TypeLong *as_self(const Type *t) { return t->is_long(); } rbackman@6375: duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint, outputStream *st ) const;// Specialized per-Type dumping duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------TypeTuple-------------------------------------- duke@435: // Class of Tuple Types, essentially type collections for function signatures duke@435: // and class layouts. It happens to also be a fast cache for the HotSpot duke@435: // signature types. duke@435: class TypeTuple : public Type { duke@435: TypeTuple( uint cnt, const Type **fields ) : Type(Tuple), _cnt(cnt), _fields(fields) { } duke@435: public: duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: virtual bool singleton(void) const; // TRUE if type is a singleton duke@435: virtual bool empty(void) const; // TRUE if type is vacuous duke@435: duke@435: public: duke@435: const uint _cnt; // Count of fields duke@435: const Type ** const _fields; // Array of field types duke@435: duke@435: // Accessors: duke@435: uint cnt() const { return _cnt; } duke@435: const Type* field_at(uint i) const { duke@435: assert(i < _cnt, "oob"); duke@435: return _fields[i]; duke@435: } duke@435: void set_field_at(uint i, const Type* t) { duke@435: assert(i < _cnt, "oob"); duke@435: _fields[i] = t; duke@435: } duke@435: duke@435: static const TypeTuple *make( uint cnt, const Type **fields ); duke@435: static const TypeTuple *make_range(ciSignature *sig); duke@435: static const TypeTuple *make_domain(ciInstanceKlass* recv, ciSignature *sig); duke@435: duke@435: // Subroutine call type with space allocated for argument types duke@435: static const Type **fields( uint arg_cnt ); duke@435: duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: // Convenience common pre-built types. duke@435: static const TypeTuple *IFBOTH; duke@435: static const TypeTuple *IFFALSE; duke@435: static const TypeTuple *IFTRUE; duke@435: static const TypeTuple *IFNEITHER; duke@435: static const TypeTuple *LOOPBODY; duke@435: static const TypeTuple *MEMBAR; duke@435: static const TypeTuple *STORECONDITIONAL; duke@435: static const TypeTuple *START_I2C; duke@435: static const TypeTuple *INT_PAIR; duke@435: static const TypeTuple *LONG_PAIR; rbackman@5791: static const TypeTuple *INT_CC_PAIR; rbackman@5997: static const TypeTuple *LONG_CC_PAIR; duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint, outputStream *st ) const; // Specialized per-Type dumping duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------TypeAry---------------------------------------- duke@435: // Class of Array Types duke@435: class TypeAry : public Type { vlivanov@5658: TypeAry(const Type* elem, const TypeInt* size, bool stable) : Type(Array), vlivanov@5658: _elem(elem), _size(size), _stable(stable) {} duke@435: public: duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: virtual bool singleton(void) const; // TRUE if type is a singleton duke@435: virtual bool empty(void) const; // TRUE if type is vacuous duke@435: duke@435: private: duke@435: const Type *_elem; // Element type of array duke@435: const TypeInt *_size; // Elements in array vlivanov@5658: const bool _stable; // Are elements @Stable? duke@435: friend class TypeAryPtr; duke@435: duke@435: public: vlivanov@5658: static const TypeAry* make(const Type* elem, const TypeInt* size, bool stable = false); duke@435: duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: bool ary_must_be_exact() const; // true if arrays of such are never generic roland@6313: virtual const Type* remove_speculative() const; kvn@1255: #ifdef ASSERT kvn@1255: // One type is interface, the other is oop kvn@1255: virtual bool interface_vs_oop(const Type *t) const; kvn@1255: #endif duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint, outputStream *st ) const; // Specialized per-Type dumping duke@435: #endif duke@435: }; duke@435: kvn@3882: //------------------------------TypeVect--------------------------------------- kvn@3882: // Class of Vector Types kvn@3882: class TypeVect : public Type { kvn@3882: const Type* _elem; // Vector's element type kvn@3882: const uint _length; // Elements in vector (power of 2) kvn@3882: kvn@3882: protected: kvn@3882: TypeVect(TYPES t, const Type* elem, uint length) : Type(t), kvn@3882: _elem(elem), _length(length) {} kvn@3882: kvn@3882: public: kvn@3882: const Type* element_type() const { return _elem; } kvn@3882: BasicType element_basic_type() const { return _elem->array_element_basic_type(); } kvn@3882: uint length() const { return _length; } kvn@3882: uint length_in_bytes() const { kvn@3882: return _length * type2aelembytes(element_basic_type()); kvn@3882: } kvn@3882: kvn@3882: virtual bool eq(const Type *t) const; kvn@3882: virtual int hash() const; // Type specific hashing kvn@3882: virtual bool singleton(void) const; // TRUE if type is a singleton kvn@3882: virtual bool empty(void) const; // TRUE if type is vacuous kvn@3882: kvn@3882: static const TypeVect *make(const BasicType elem_bt, uint length) { kvn@3882: // Use bottom primitive type. kvn@3882: return make(get_const_basic_type(elem_bt), length); kvn@3882: } kvn@3882: // Used directly by Replicate nodes to construct singleton vector. kvn@3882: static const TypeVect *make(const Type* elem, uint length); kvn@3882: kvn@3882: virtual const Type *xmeet( const Type *t) const; kvn@3882: virtual const Type *xdual() const; // Compute dual right now. kvn@3882: kvn@3882: static const TypeVect *VECTS; kvn@3882: static const TypeVect *VECTD; kvn@3882: static const TypeVect *VECTX; kvn@3882: static const TypeVect *VECTY; kvn@3882: kvn@3882: #ifndef PRODUCT kvn@3882: virtual void dump2(Dict &d, uint, outputStream *st) const; // Specialized per-Type dumping kvn@3882: #endif kvn@3882: }; kvn@3882: kvn@3882: class TypeVectS : public TypeVect { kvn@3882: friend class TypeVect; kvn@3882: TypeVectS(const Type* elem, uint length) : TypeVect(VectorS, elem, length) {} kvn@3882: }; kvn@3882: kvn@3882: class TypeVectD : public TypeVect { kvn@3882: friend class TypeVect; kvn@3882: TypeVectD(const Type* elem, uint length) : TypeVect(VectorD, elem, length) {} kvn@3882: }; kvn@3882: kvn@3882: class TypeVectX : public TypeVect { kvn@3882: friend class TypeVect; kvn@3882: TypeVectX(const Type* elem, uint length) : TypeVect(VectorX, elem, length) {} kvn@3882: }; kvn@3882: kvn@3882: class TypeVectY : public TypeVect { kvn@3882: friend class TypeVect; kvn@3882: TypeVectY(const Type* elem, uint length) : TypeVect(VectorY, elem, length) {} kvn@3882: }; kvn@3882: duke@435: //------------------------------TypePtr---------------------------------------- duke@435: // Class of machine Pointer Types: raw data, instances or arrays. duke@435: // If the _base enum is AnyPtr, then this refers to all of the above. duke@435: // Otherwise the _base will indicate which subset of pointers is affected, duke@435: // and the class will be inherited from. duke@435: class TypePtr : public Type { roland@4159: friend class TypeNarrowPtr; duke@435: public: duke@435: enum PTR { TopPTR, AnyNull, Constant, Null, NotNull, BotPTR, lastPTR }; duke@435: protected: duke@435: TypePtr( TYPES t, PTR ptr, int offset ) : Type(t), _ptr(ptr), _offset(offset) {} duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: static const PTR ptr_meet[lastPTR][lastPTR]; duke@435: static const PTR ptr_dual[lastPTR]; duke@435: static const char * const ptr_msg[lastPTR]; duke@435: duke@435: public: duke@435: const int _offset; // Offset into oop, with TOP & BOT duke@435: const PTR _ptr; // Pointer equivalence class duke@435: duke@435: const int offset() const { return _offset; } duke@435: const PTR ptr() const { return _ptr; } duke@435: duke@435: static const TypePtr *make( TYPES t, PTR ptr, int offset ); duke@435: duke@435: // Return a 'ptr' version of this type duke@435: virtual const Type *cast_to_ptr_type(PTR ptr) const; duke@435: duke@435: virtual intptr_t get_con() const; duke@435: kvn@741: int xadd_offset( intptr_t offset ) const; kvn@741: virtual const TypePtr *add_offset( intptr_t offset ) const; duke@435: duke@435: virtual bool singleton(void) const; // TRUE if type is a singleton duke@435: virtual bool empty(void) const; // TRUE if type is vacuous duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: int meet_offset( int offset ) const; duke@435: int dual_offset( ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: duke@435: // meet, dual and join over pointer equivalence sets duke@435: PTR meet_ptr( const PTR in_ptr ) const { return ptr_meet[in_ptr][ptr()]; } duke@435: PTR dual_ptr() const { return ptr_dual[ptr()]; } duke@435: duke@435: // This is textually confusing unless one recalls that duke@435: // join(t) == dual()->meet(t->dual())->dual(). duke@435: PTR join_ptr( const PTR in_ptr ) const { duke@435: return ptr_dual[ ptr_meet[ ptr_dual[in_ptr] ] [ dual_ptr() ] ]; duke@435: } duke@435: duke@435: // Tests for relation to centerline of type lattice: duke@435: static bool above_centerline(PTR ptr) { return (ptr <= AnyNull); } duke@435: static bool below_centerline(PTR ptr) { return (ptr >= NotNull); } duke@435: // Convenience common pre-built types. duke@435: static const TypePtr *NULL_PTR; duke@435: static const TypePtr *NOTNULL; duke@435: static const TypePtr *BOTTOM; duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------TypeRawPtr------------------------------------- duke@435: // Class of raw pointers, pointers to things other than Oops. Examples duke@435: // include the stack pointer, top of heap, card-marking area, handles, etc. duke@435: class TypeRawPtr : public TypePtr { duke@435: protected: duke@435: TypeRawPtr( PTR ptr, address bits ) : TypePtr(RawPtr,ptr,0), _bits(bits){} duke@435: public: duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: duke@435: const address _bits; // Constant value, if applicable duke@435: duke@435: static const TypeRawPtr *make( PTR ptr ); duke@435: static const TypeRawPtr *make( address bits ); duke@435: duke@435: // Return a 'ptr' version of this type duke@435: virtual const Type *cast_to_ptr_type(PTR ptr) const; duke@435: duke@435: virtual intptr_t get_con() const; duke@435: kvn@741: virtual const TypePtr *add_offset( intptr_t offset ) const; duke@435: duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: // Convenience common pre-built types. duke@435: static const TypeRawPtr *BOTTOM; duke@435: static const TypeRawPtr *NOTNULL; duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------TypeOopPtr------------------------------------- duke@435: // Some kind of oop (Java pointer), either klass or instance or array. duke@435: class TypeOopPtr : public TypePtr { duke@435: protected: roland@6380: TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth); duke@435: public: duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: virtual bool singleton(void) const; // TRUE if type is a singleton duke@435: enum { kvn@658: InstanceTop = -1, // undefined instance kvn@658: InstanceBot = 0 // any possible instance duke@435: }; duke@435: protected: duke@435: roland@6380: enum { roland@6380: InlineDepthBottom = INT_MAX, roland@6380: InlineDepthTop = -InlineDepthBottom roland@6380: }; duke@435: // Oop is NULL, unless this is a constant oop. duke@435: ciObject* _const_oop; // Constant oop duke@435: // If _klass is NULL, then so is _sig. This is an unloaded klass. duke@435: ciKlass* _klass; // Klass object duke@435: // Does the type exclude subclasses of the klass? (Inexact == polymorphic.) duke@435: bool _klass_is_exact; kvn@598: bool _is_ptr_to_narrowoop; roland@4159: bool _is_ptr_to_narrowklass; kvn@5110: bool _is_ptr_to_boxed_value; duke@435: kvn@658: // If not InstanceTop or InstanceBot, indicates that this is kvn@658: // a particular instance of this type which is distinct. kvn@658: // This is the the node index of the allocation node creating this instance. kvn@658: int _instance_id; duke@435: roland@5991: // Extra type information profiling gave us. We propagate it the roland@5991: // same way the rest of the type info is propagated. If we want to roland@5991: // use it, then we have to emit a guard: this part of the type is roland@5991: // not something we know but something we speculate about the type. roland@5991: const TypeOopPtr* _speculative; roland@6380: // For speculative types, we record at what inlining depth the roland@6380: // profiling point that provided the data is. We want to favor roland@6380: // profile data coming from outer scopes which are likely better for roland@6380: // the current compilation. roland@6380: int _inline_depth; roland@5991: duke@435: static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact); duke@435: kvn@658: int dual_instance_id() const; kvn@658: int meet_instance_id(int uid) const; duke@435: roland@5991: // utility methods to work on the speculative part of the type roland@5991: const TypeOopPtr* dual_speculative() const; roland@6313: const TypeOopPtr* xmeet_speculative(const TypeOopPtr* other) const; roland@5991: bool eq_speculative(const TypeOopPtr* other) const; roland@5991: int hash_speculative() const; roland@5991: const TypeOopPtr* add_offset_speculative(intptr_t offset) const; roland@5991: #ifndef PRODUCT roland@5991: void dump_speculative(outputStream *st) const; roland@5991: #endif roland@6380: // utility methods to work on the inline depth of the type roland@6380: int dual_inline_depth() const; roland@6380: int meet_inline_depth(int depth) const; roland@6380: #ifndef PRODUCT roland@6380: void dump_inline_depth(outputStream *st) const; roland@6380: #endif roland@5991: roland@6313: // Do not allow interface-vs.-noninterface joins to collapse to top. roland@6313: virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; roland@6313: duke@435: public: duke@435: // Creates a type given a klass. Correctly handles multi-dimensional arrays duke@435: // Respects UseUniqueSubclasses. duke@435: // If the klass is final, the resulting type will be exact. duke@435: static const TypeOopPtr* make_from_klass(ciKlass* klass) { duke@435: return make_from_klass_common(klass, true, false); duke@435: } duke@435: // Same as before, but will produce an exact type, even if duke@435: // the klass is not final, as long as it has exactly one implementation. duke@435: static const TypeOopPtr* make_from_klass_unique(ciKlass* klass) { duke@435: return make_from_klass_common(klass, true, true); duke@435: } duke@435: // Same as before, but does not respects UseUniqueSubclasses. duke@435: // Use this only for creating array element types. duke@435: static const TypeOopPtr* make_from_klass_raw(ciKlass* klass) { duke@435: return make_from_klass_common(klass, false, false); duke@435: } duke@435: // Creates a singleton type given an object. jrose@1424: // If the object cannot be rendered as a constant, jrose@1424: // may return a non-singleton type. jrose@1424: // If require_constant, produce a NULL if a singleton is not possible. kvn@5110: static const TypeOopPtr* make_from_constant(ciObject* o, kvn@5110: bool require_constant = false, kvn@5110: bool not_null_elements = false); duke@435: duke@435: // Make a generic (unclassed) pointer to an oop. roland@6380: static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); duke@435: duke@435: ciObject* const_oop() const { return _const_oop; } duke@435: virtual ciKlass* klass() const { return _klass; } duke@435: bool klass_is_exact() const { return _klass_is_exact; } kvn@598: kvn@598: // Returns true if this pointer points at memory which contains a kvn@598: // compressed oop references. kvn@598: bool is_ptr_to_narrowoop_nv() const { return _is_ptr_to_narrowoop; } roland@4159: bool is_ptr_to_narrowklass_nv() const { return _is_ptr_to_narrowklass; } kvn@5110: bool is_ptr_to_boxed_value() const { return _is_ptr_to_boxed_value; } kvn@658: bool is_known_instance() const { return _instance_id > 0; } kvn@658: int instance_id() const { return _instance_id; } kvn@658: bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; } roland@6380: virtual const TypeOopPtr* speculative() const { return _speculative; } duke@435: duke@435: virtual intptr_t get_con() const; duke@435: duke@435: virtual const Type *cast_to_ptr_type(PTR ptr) const; duke@435: duke@435: virtual const Type *cast_to_exactness(bool klass_is_exact) const; duke@435: kvn@658: virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const; duke@435: duke@435: // corresponding pointer to klass, for a given instance duke@435: const TypeKlassPtr* as_klass_type() const; duke@435: kvn@741: virtual const TypePtr *add_offset( intptr_t offset ) const; roland@5991: // Return same type without a speculative part roland@6313: virtual const Type* remove_speculative() const; duke@435: roland@5991: virtual const Type *xmeet(const Type *t) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. roland@5991: // the core of the computation of the meet for TypeOopPtr and for its subclasses roland@5991: virtual const Type *xmeet_helper(const Type *t) const; duke@435: duke@435: // Convenience common pre-built type. duke@435: static const TypeOopPtr *BOTTOM; duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; duke@435: #endif roland@5991: roland@5991: // Return the speculative type if any roland@5991: ciKlass* speculative_type() const { roland@5991: if (_speculative != NULL) { roland@5991: const TypeOopPtr* speculative = _speculative->join(this)->is_oopptr(); roland@5991: if (speculative->klass_is_exact()) { roland@6380: return speculative->klass(); roland@5991: } roland@5991: } roland@5991: return NULL; roland@5991: } roland@6380: int inline_depth() const { roland@6380: return _inline_depth; roland@6380: } roland@6380: virtual const TypeOopPtr* with_inline_depth(int depth) const; roland@6380: virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const; duke@435: }; duke@435: duke@435: //------------------------------TypeInstPtr------------------------------------ duke@435: // Class of Java object pointers, pointing either to non-array Java instances coleenp@4037: // or to a Klass* (including array klasses). duke@435: class TypeInstPtr : public TypeOopPtr { roland@6380: TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth); duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: duke@435: ciSymbol* _name; // class name duke@435: duke@435: public: duke@435: ciSymbol* name() const { return _name; } duke@435: duke@435: bool is_loaded() const { return _klass->is_loaded(); } duke@435: duke@435: // Make a pointer to a constant oop. duke@435: static const TypeInstPtr *make(ciObject* o) { roland@5991: return make(TypePtr::Constant, o->klass(), true, o, 0, InstanceBot); duke@435: } duke@435: // Make a pointer to a constant oop with offset. duke@435: static const TypeInstPtr *make(ciObject* o, int offset) { roland@5991: return make(TypePtr::Constant, o->klass(), true, o, offset, InstanceBot); duke@435: } duke@435: duke@435: // Make a pointer to some value of type klass. duke@435: static const TypeInstPtr *make(PTR ptr, ciKlass* klass) { roland@5991: return make(ptr, klass, false, NULL, 0, InstanceBot); duke@435: } duke@435: duke@435: // Make a pointer to some non-polymorphic value of exactly type klass. duke@435: static const TypeInstPtr *make_exact(PTR ptr, ciKlass* klass) { roland@5991: return make(ptr, klass, true, NULL, 0, InstanceBot); duke@435: } duke@435: duke@435: // Make a pointer to some value of type klass with offset. duke@435: static const TypeInstPtr *make(PTR ptr, ciKlass* klass, int offset) { roland@5991: return make(ptr, klass, false, NULL, offset, InstanceBot); duke@435: } duke@435: duke@435: // Make a pointer to an oop. roland@6380: static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); duke@435: kvn@5110: /** Create constant type for a constant boxed value */ kvn@5110: const Type* get_const_boxed_value() const; kvn@5110: duke@435: // If this is a java.lang.Class constant, return the type for it or NULL. duke@435: // Pass to Type::get_const_type to turn it to a type, which will usually duke@435: // be a TypeInstPtr, but may also be a TypeInt::INT for int.class, etc. duke@435: ciType* java_mirror_type() const; duke@435: duke@435: virtual const Type *cast_to_ptr_type(PTR ptr) const; duke@435: duke@435: virtual const Type *cast_to_exactness(bool klass_is_exact) const; duke@435: kvn@658: virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const; duke@435: kvn@741: virtual const TypePtr *add_offset( intptr_t offset ) const; roland@5991: // Return same type without a speculative part roland@6313: virtual const Type* remove_speculative() const; roland@6380: virtual const TypeOopPtr* with_inline_depth(int depth) const; duke@435: roland@5991: // the core of the computation of the meet of 2 types roland@5991: virtual const Type *xmeet_helper(const Type *t) const; duke@435: virtual const TypeInstPtr *xmeet_unloaded( const TypeInstPtr *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: duke@435: // Convenience common pre-built types. duke@435: static const TypeInstPtr *NOTNULL; duke@435: static const TypeInstPtr *BOTTOM; duke@435: static const TypeInstPtr *MIRROR; duke@435: static const TypeInstPtr *MARK; duke@435: static const TypeInstPtr *KLASS; duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------TypeAryPtr------------------------------------- duke@435: // Class of Java array pointers duke@435: class TypeAryPtr : public TypeOopPtr { kvn@5110: TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, roland@6380: int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative, int inline_depth) roland@6380: : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative, inline_depth), kvn@5110: _ary(ary), kvn@5110: _is_autobox_cache(is_autobox_cache) kvn@5110: { kvn@2116: #ifdef ASSERT kvn@2116: if (k != NULL) { kvn@2116: // Verify that specified klass and TypeAryPtr::klass() follow the same rules. kvn@2116: ciKlass* ck = compute_klass(true); kvn@2147: if (k != ck) { kvn@2116: this->dump(); tty->cr(); kvn@2116: tty->print(" k: "); kvn@2116: k->print(); tty->cr(); kvn@2116: tty->print("ck: "); kvn@2116: if (ck != NULL) ck->print(); kvn@2116: else tty->print(""); kvn@2116: tty->cr(); kvn@2116: assert(false, "unexpected TypeAryPtr::_klass"); kvn@2116: } kvn@2116: } kvn@2116: #endif kvn@2116: } duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: const TypeAry *_ary; // Array we point into kvn@5110: const bool _is_autobox_cache; duke@435: kvn@2116: ciKlass* compute_klass(DEBUG_ONLY(bool verify = false)) const; kvn@2116: duke@435: public: duke@435: // Accessors duke@435: ciKlass* klass() const; duke@435: const TypeAry* ary() const { return _ary; } duke@435: const Type* elem() const { return _ary->_elem; } duke@435: const TypeInt* size() const { return _ary->_size; } vlivanov@5658: bool is_stable() const { return _ary->_stable; } duke@435: kvn@5110: bool is_autobox_cache() const { return _is_autobox_cache; } kvn@5110: roland@6380: static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); duke@435: // Constant pointer to array roland@6380: static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom, bool is_autobox_cache= false); duke@435: duke@435: // Return a 'ptr' version of this type duke@435: virtual const Type *cast_to_ptr_type(PTR ptr) const; duke@435: duke@435: virtual const Type *cast_to_exactness(bool klass_is_exact) const; duke@435: kvn@658: virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const; duke@435: duke@435: virtual const TypeAryPtr* cast_to_size(const TypeInt* size) const; rasbold@801: virtual const TypeInt* narrow_size_type(const TypeInt* size) const; duke@435: duke@435: virtual bool empty(void) const; // TRUE if type is vacuous kvn@741: virtual const TypePtr *add_offset( intptr_t offset ) const; roland@5991: // Return same type without a speculative part roland@6313: virtual const Type* remove_speculative() const; roland@6380: virtual const TypeOopPtr* with_inline_depth(int depth) const; duke@435: roland@5991: // the core of the computation of the meet of 2 types roland@5991: virtual const Type *xmeet_helper(const Type *t) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: vlivanov@5658: const TypeAryPtr* cast_to_stable(bool stable, int stable_dimension = 1) const; vlivanov@5658: int stable_dimension() const; vlivanov@5658: duke@435: // Convenience common pre-built types. duke@435: static const TypeAryPtr *RANGE; duke@435: static const TypeAryPtr *OOPS; kvn@598: static const TypeAryPtr *NARROWOOPS; duke@435: static const TypeAryPtr *BYTES; duke@435: static const TypeAryPtr *SHORTS; duke@435: static const TypeAryPtr *CHARS; duke@435: static const TypeAryPtr *INTS; duke@435: static const TypeAryPtr *LONGS; duke@435: static const TypeAryPtr *FLOATS; duke@435: static const TypeAryPtr *DOUBLES; duke@435: // selects one of the above: duke@435: static const TypeAryPtr *get_array_body_type(BasicType elem) { duke@435: assert((uint)elem <= T_CONFLICT && _array_body_type[elem] != NULL, "bad elem type"); duke@435: return _array_body_type[elem]; duke@435: } duke@435: static const TypeAryPtr *_array_body_type[T_CONFLICT+1]; duke@435: // sharpen the type of an int which is used as an array size kvn@1255: #ifdef ASSERT kvn@1255: // One type is interface, the other is oop kvn@1255: virtual bool interface_vs_oop(const Type *t) const; kvn@1255: #endif duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping duke@435: #endif duke@435: }; duke@435: coleenp@4037: //------------------------------TypeMetadataPtr------------------------------------- coleenp@4037: // Some kind of metadata, either Method*, MethodData* or CPCacheOop coleenp@4037: class TypeMetadataPtr : public TypePtr { coleenp@4037: protected: coleenp@4037: TypeMetadataPtr(PTR ptr, ciMetadata* metadata, int offset); roland@6313: // Do not allow interface-vs.-noninterface joins to collapse to top. roland@6313: virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; coleenp@4037: public: coleenp@4037: virtual bool eq( const Type *t ) const; coleenp@4037: virtual int hash() const; // Type specific hashing coleenp@4037: virtual bool singleton(void) const; // TRUE if type is a singleton coleenp@4037: coleenp@4037: private: coleenp@4037: ciMetadata* _metadata; coleenp@4037: coleenp@4037: public: coleenp@4037: static const TypeMetadataPtr* make(PTR ptr, ciMetadata* m, int offset); coleenp@4037: coleenp@4037: static const TypeMetadataPtr* make(ciMethod* m); coleenp@4037: static const TypeMetadataPtr* make(ciMethodData* m); coleenp@4037: coleenp@4037: ciMetadata* metadata() const { return _metadata; } coleenp@4037: coleenp@4037: virtual const Type *cast_to_ptr_type(PTR ptr) const; coleenp@4037: coleenp@4037: virtual const TypePtr *add_offset( intptr_t offset ) const; coleenp@4037: coleenp@4037: virtual const Type *xmeet( const Type *t ) const; coleenp@4037: virtual const Type *xdual() const; // Compute dual right now. coleenp@4037: coleenp@4037: virtual intptr_t get_con() const; coleenp@4037: coleenp@4037: // Convenience common pre-built types. coleenp@4037: static const TypeMetadataPtr *BOTTOM; coleenp@4037: coleenp@4037: #ifndef PRODUCT coleenp@4037: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; coleenp@4037: #endif coleenp@4037: }; coleenp@4037: duke@435: //------------------------------TypeKlassPtr----------------------------------- duke@435: // Class of Java Klass pointers coleenp@4037: class TypeKlassPtr : public TypePtr { duke@435: TypeKlassPtr( PTR ptr, ciKlass* klass, int offset ); duke@435: roland@6313: protected: roland@6313: virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; coleenp@4037: public: duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing coleenp@4037: virtual bool singleton(void) const; // TRUE if type is a singleton coleenp@4037: private: coleenp@4037: coleenp@4037: static const TypeKlassPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact); coleenp@4037: coleenp@4037: ciKlass* _klass; coleenp@4037: coleenp@4037: // Does the type exclude subclasses of the klass? (Inexact == polymorphic.) coleenp@4037: bool _klass_is_exact; duke@435: duke@435: public: coleenp@4037: ciSymbol* name() const { return klass()->name(); } duke@435: coleenp@4037: ciKlass* klass() const { return _klass; } coleenp@4037: bool klass_is_exact() const { return _klass_is_exact; } coleenp@4037: coleenp@4037: bool is_loaded() const { return klass()->is_loaded(); } coleenp@4037: coleenp@4037: // Creates a type given a klass. Correctly handles multi-dimensional arrays coleenp@4037: // Respects UseUniqueSubclasses. coleenp@4037: // If the klass is final, the resulting type will be exact. coleenp@4037: static const TypeKlassPtr* make_from_klass(ciKlass* klass) { coleenp@4037: return make_from_klass_common(klass, true, false); coleenp@4037: } coleenp@4037: // Same as before, but will produce an exact type, even if coleenp@4037: // the klass is not final, as long as it has exactly one implementation. coleenp@4037: static const TypeKlassPtr* make_from_klass_unique(ciKlass* klass) { coleenp@4037: return make_from_klass_common(klass, true, true); coleenp@4037: } coleenp@4037: // Same as before, but does not respects UseUniqueSubclasses. coleenp@4037: // Use this only for creating array element types. coleenp@4037: static const TypeKlassPtr* make_from_klass_raw(ciKlass* klass) { coleenp@4037: return make_from_klass_common(klass, false, false); coleenp@4037: } coleenp@4037: coleenp@4037: // Make a generic (unclassed) pointer to metadata. coleenp@4037: static const TypeKlassPtr* make(PTR ptr, int offset); never@990: duke@435: // ptr to klass 'k' duke@435: static const TypeKlassPtr *make( ciKlass* k ) { return make( TypePtr::Constant, k, 0); } duke@435: // ptr to klass 'k' with offset duke@435: static const TypeKlassPtr *make( ciKlass* k, int offset ) { return make( TypePtr::Constant, k, offset); } duke@435: // ptr to klass 'k' or sub-klass duke@435: static const TypeKlassPtr *make( PTR ptr, ciKlass* k, int offset); duke@435: duke@435: virtual const Type *cast_to_ptr_type(PTR ptr) const; duke@435: duke@435: virtual const Type *cast_to_exactness(bool klass_is_exact) const; duke@435: duke@435: // corresponding pointer to instance, for a given class duke@435: const TypeOopPtr* as_instance_type() const; duke@435: kvn@741: virtual const TypePtr *add_offset( intptr_t offset ) const; duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: coleenp@4037: virtual intptr_t get_con() const; coleenp@4037: duke@435: // Convenience common pre-built types. duke@435: static const TypeKlassPtr* OBJECT; // Not-null object klass or below duke@435: static const TypeKlassPtr* OBJECT_OR_NULL; // Maybe-null version of same duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping duke@435: #endif duke@435: }; duke@435: roland@4159: class TypeNarrowPtr : public Type { coleenp@548: protected: never@1262: const TypePtr* _ptrtype; // Could be TypePtr::NULL_PTR coleenp@548: roland@4159: TypeNarrowPtr(TYPES t, const TypePtr* ptrtype): _ptrtype(ptrtype), roland@4159: Type(t) { never@1262: assert(ptrtype->offset() == 0 || never@1262: ptrtype->offset() == OffsetBot || never@1262: ptrtype->offset() == OffsetTop, "no real offsets"); coleenp@548: } roland@4159: roland@4159: virtual const TypeNarrowPtr *isa_same_narrowptr(const Type *t) const = 0; roland@4159: virtual const TypeNarrowPtr *is_same_narrowptr(const Type *t) const = 0; roland@4159: virtual const TypeNarrowPtr *make_same_narrowptr(const TypePtr *t) const = 0; roland@4159: virtual const TypeNarrowPtr *make_hash_same_narrowptr(const TypePtr *t) const = 0; roland@6313: // Do not allow interface-vs.-noninterface joins to collapse to top. roland@6313: virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; coleenp@548: public: coleenp@548: virtual bool eq( const Type *t ) const; coleenp@548: virtual int hash() const; // Type specific hashing coleenp@548: virtual bool singleton(void) const; // TRUE if type is a singleton coleenp@548: coleenp@548: virtual const Type *xmeet( const Type *t ) const; coleenp@548: virtual const Type *xdual() const; // Compute dual right now. coleenp@548: coleenp@548: virtual intptr_t get_con() const; coleenp@548: coleenp@548: virtual bool empty(void) const; // TRUE if type is vacuous coleenp@548: roland@4159: // returns the equivalent ptr type for this compressed pointer roland@4159: const TypePtr *get_ptrtype() const { roland@4159: return _ptrtype; roland@4159: } roland@4159: roland@4159: #ifndef PRODUCT roland@4159: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; roland@4159: #endif roland@4159: }; roland@4159: roland@4159: //------------------------------TypeNarrowOop---------------------------------- roland@4159: // A compressed reference to some kind of Oop. This type wraps around roland@4159: // a preexisting TypeOopPtr and forwards most of it's operations to roland@4159: // the underlying type. It's only real purpose is to track the roland@4159: // oopness of the compressed oop value when we expose the conversion roland@4159: // between the normal and the compressed form. roland@4159: class TypeNarrowOop : public TypeNarrowPtr { roland@4159: protected: roland@4159: TypeNarrowOop( const TypePtr* ptrtype): TypeNarrowPtr(NarrowOop, ptrtype) { roland@4159: } roland@4159: roland@4159: virtual const TypeNarrowPtr *isa_same_narrowptr(const Type *t) const { roland@4159: return t->isa_narrowoop(); roland@4159: } roland@4159: roland@4159: virtual const TypeNarrowPtr *is_same_narrowptr(const Type *t) const { roland@4159: return t->is_narrowoop(); roland@4159: } roland@4159: roland@4159: virtual const TypeNarrowPtr *make_same_narrowptr(const TypePtr *t) const { roland@4159: return new TypeNarrowOop(t); roland@4159: } roland@4159: roland@4159: virtual const TypeNarrowPtr *make_hash_same_narrowptr(const TypePtr *t) const { roland@4159: return (const TypeNarrowPtr*)((new TypeNarrowOop(t))->hashcons()); roland@4159: } roland@4159: roland@4159: public: roland@4159: coleenp@548: static const TypeNarrowOop *make( const TypePtr* type); coleenp@548: jcoomes@2661: static const TypeNarrowOop* make_from_constant(ciObject* con, bool require_constant = false) { jcoomes@2661: return make(TypeOopPtr::make_from_constant(con, require_constant)); coleenp@548: } coleenp@548: roland@4159: static const TypeNarrowOop *BOTTOM; roland@4159: static const TypeNarrowOop *NULL_PTR; roland@4159: roland@6313: virtual const Type* remove_speculative() const { roland@6313: return make(_ptrtype->remove_speculative()->is_ptr()); roland@6313: } roland@6313: roland@4159: #ifndef PRODUCT roland@4159: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; roland@4159: #endif roland@4159: }; roland@4159: roland@4159: //------------------------------TypeNarrowKlass---------------------------------- roland@4159: // A compressed reference to klass pointer. This type wraps around a roland@4159: // preexisting TypeKlassPtr and forwards most of it's operations to roland@4159: // the underlying type. roland@4159: class TypeNarrowKlass : public TypeNarrowPtr { roland@4159: protected: roland@4159: TypeNarrowKlass( const TypePtr* ptrtype): TypeNarrowPtr(NarrowKlass, ptrtype) { coleenp@548: } coleenp@548: roland@4159: virtual const TypeNarrowPtr *isa_same_narrowptr(const Type *t) const { roland@4159: return t->isa_narrowklass(); roland@4159: } roland@4159: roland@4159: virtual const TypeNarrowPtr *is_same_narrowptr(const Type *t) const { roland@4159: return t->is_narrowklass(); roland@4159: } roland@4159: roland@4159: virtual const TypeNarrowPtr *make_same_narrowptr(const TypePtr *t) const { roland@4159: return new TypeNarrowKlass(t); roland@4159: } roland@4159: roland@4159: virtual const TypeNarrowPtr *make_hash_same_narrowptr(const TypePtr *t) const { roland@4159: return (const TypeNarrowPtr*)((new TypeNarrowKlass(t))->hashcons()); roland@4159: } roland@4159: roland@4159: public: roland@4159: static const TypeNarrowKlass *make( const TypePtr* type); roland@4159: roland@4159: // static const TypeNarrowKlass *BOTTOM; roland@4159: static const TypeNarrowKlass *NULL_PTR; coleenp@548: coleenp@548: #ifndef PRODUCT coleenp@548: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; coleenp@548: #endif coleenp@548: }; coleenp@548: duke@435: //------------------------------TypeFunc--------------------------------------- duke@435: // Class of Array Types duke@435: class TypeFunc : public Type { duke@435: TypeFunc( const TypeTuple *domain, const TypeTuple *range ) : Type(Function), _domain(domain), _range(range) {} duke@435: virtual bool eq( const Type *t ) const; duke@435: virtual int hash() const; // Type specific hashing duke@435: virtual bool singleton(void) const; // TRUE if type is a singleton duke@435: virtual bool empty(void) const; // TRUE if type is vacuous duke@435: public: duke@435: // Constants are shared among ADLC and VM duke@435: enum { Control = AdlcVMDeps::Control, duke@435: I_O = AdlcVMDeps::I_O, duke@435: Memory = AdlcVMDeps::Memory, duke@435: FramePtr = AdlcVMDeps::FramePtr, duke@435: ReturnAdr = AdlcVMDeps::ReturnAdr, duke@435: Parms = AdlcVMDeps::Parms duke@435: }; duke@435: duke@435: const TypeTuple* const _domain; // Domain of inputs duke@435: const TypeTuple* const _range; // Range of results duke@435: duke@435: // Accessors: duke@435: const TypeTuple* domain() const { return _domain; } duke@435: const TypeTuple* range() const { return _range; } duke@435: duke@435: static const TypeFunc *make(ciMethod* method); duke@435: static const TypeFunc *make(ciSignature signature, const Type* extra); duke@435: static const TypeFunc *make(const TypeTuple* domain, const TypeTuple* range); duke@435: duke@435: virtual const Type *xmeet( const Type *t ) const; duke@435: virtual const Type *xdual() const; // Compute dual right now. duke@435: duke@435: BasicType return_type() const; duke@435: duke@435: #ifndef PRODUCT duke@435: virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping duke@435: #endif duke@435: // Convenience common pre-built types. duke@435: }; duke@435: duke@435: //------------------------------accessors-------------------------------------- kvn@598: inline bool Type::is_ptr_to_narrowoop() const { kvn@598: #ifdef _LP64 kvn@598: return (isa_oopptr() != NULL && is_oopptr()->is_ptr_to_narrowoop_nv()); kvn@598: #else kvn@598: return false; kvn@598: #endif kvn@598: } kvn@598: roland@4159: inline bool Type::is_ptr_to_narrowklass() const { roland@4159: #ifdef _LP64 roland@4159: return (isa_oopptr() != NULL && is_oopptr()->is_ptr_to_narrowklass_nv()); roland@4159: #else roland@4159: return false; roland@4159: #endif roland@4159: } roland@4159: duke@435: inline float Type::getf() const { duke@435: assert( _base == FloatCon, "Not a FloatCon" ); duke@435: return ((TypeF*)this)->_f; duke@435: } duke@435: duke@435: inline double Type::getd() const { duke@435: assert( _base == DoubleCon, "Not a DoubleCon" ); duke@435: return ((TypeD*)this)->_d; duke@435: } duke@435: duke@435: inline const TypeInt *Type::is_int() const { duke@435: assert( _base == Int, "Not an Int" ); duke@435: return (TypeInt*)this; duke@435: } duke@435: duke@435: inline const TypeInt *Type::isa_int() const { duke@435: return ( _base == Int ? (TypeInt*)this : NULL); duke@435: } duke@435: duke@435: inline const TypeLong *Type::is_long() const { duke@435: assert( _base == Long, "Not a Long" ); duke@435: return (TypeLong*)this; duke@435: } duke@435: duke@435: inline const TypeLong *Type::isa_long() const { duke@435: return ( _base == Long ? (TypeLong*)this : NULL); duke@435: } duke@435: twisti@4313: inline const TypeF *Type::isa_float() const { twisti@4313: return ((_base == FloatTop || twisti@4313: _base == FloatCon || twisti@4313: _base == FloatBot) ? (TypeF*)this : NULL); twisti@4313: } twisti@4313: twisti@4313: inline const TypeF *Type::is_float_constant() const { twisti@4313: assert( _base == FloatCon, "Not a Float" ); twisti@4313: return (TypeF*)this; twisti@4313: } twisti@4313: twisti@4313: inline const TypeF *Type::isa_float_constant() const { twisti@4313: return ( _base == FloatCon ? (TypeF*)this : NULL); twisti@4313: } twisti@4313: twisti@4313: inline const TypeD *Type::isa_double() const { twisti@4313: return ((_base == DoubleTop || twisti@4313: _base == DoubleCon || twisti@4313: _base == DoubleBot) ? (TypeD*)this : NULL); twisti@4313: } twisti@4313: twisti@4313: inline const TypeD *Type::is_double_constant() const { twisti@4313: assert( _base == DoubleCon, "Not a Double" ); twisti@4313: return (TypeD*)this; twisti@4313: } twisti@4313: twisti@4313: inline const TypeD *Type::isa_double_constant() const { twisti@4313: return ( _base == DoubleCon ? (TypeD*)this : NULL); twisti@4313: } twisti@4313: duke@435: inline const TypeTuple *Type::is_tuple() const { duke@435: assert( _base == Tuple, "Not a Tuple" ); duke@435: return (TypeTuple*)this; duke@435: } duke@435: duke@435: inline const TypeAry *Type::is_ary() const { duke@435: assert( _base == Array , "Not an Array" ); duke@435: return (TypeAry*)this; duke@435: } duke@435: kvn@3882: inline const TypeVect *Type::is_vect() const { kvn@3882: assert( _base >= VectorS && _base <= VectorY, "Not a Vector" ); kvn@3882: return (TypeVect*)this; kvn@3882: } kvn@3882: kvn@3882: inline const TypeVect *Type::isa_vect() const { kvn@3882: return (_base >= VectorS && _base <= VectorY) ? (TypeVect*)this : NULL; kvn@3882: } kvn@3882: duke@435: inline const TypePtr *Type::is_ptr() const { duke@435: // AnyPtr is the first Ptr and KlassPtr the last, with no non-ptrs between. duke@435: assert(_base >= AnyPtr && _base <= KlassPtr, "Not a pointer"); duke@435: return (TypePtr*)this; duke@435: } duke@435: duke@435: inline const TypePtr *Type::isa_ptr() const { duke@435: // AnyPtr is the first Ptr and KlassPtr the last, with no non-ptrs between. duke@435: return (_base >= AnyPtr && _base <= KlassPtr) ? (TypePtr*)this : NULL; duke@435: } duke@435: duke@435: inline const TypeOopPtr *Type::is_oopptr() const { duke@435: // OopPtr is the first and KlassPtr the last, with no non-oops between. coleenp@4037: assert(_base >= OopPtr && _base <= AryPtr, "Not a Java pointer" ) ; duke@435: return (TypeOopPtr*)this; duke@435: } duke@435: duke@435: inline const TypeOopPtr *Type::isa_oopptr() const { duke@435: // OopPtr is the first and KlassPtr the last, with no non-oops between. coleenp@4037: return (_base >= OopPtr && _base <= AryPtr) ? (TypeOopPtr*)this : NULL; duke@435: } duke@435: coleenp@548: inline const TypeRawPtr *Type::isa_rawptr() const { coleenp@548: return (_base == RawPtr) ? (TypeRawPtr*)this : NULL; coleenp@548: } coleenp@548: duke@435: inline const TypeRawPtr *Type::is_rawptr() const { duke@435: assert( _base == RawPtr, "Not a raw pointer" ); duke@435: return (TypeRawPtr*)this; duke@435: } duke@435: duke@435: inline const TypeInstPtr *Type::isa_instptr() const { duke@435: return (_base == InstPtr) ? (TypeInstPtr*)this : NULL; duke@435: } duke@435: duke@435: inline const TypeInstPtr *Type::is_instptr() const { duke@435: assert( _base == InstPtr, "Not an object pointer" ); duke@435: return (TypeInstPtr*)this; duke@435: } duke@435: duke@435: inline const TypeAryPtr *Type::isa_aryptr() const { duke@435: return (_base == AryPtr) ? (TypeAryPtr*)this : NULL; duke@435: } duke@435: duke@435: inline const TypeAryPtr *Type::is_aryptr() const { duke@435: assert( _base == AryPtr, "Not an array pointer" ); duke@435: return (TypeAryPtr*)this; duke@435: } duke@435: coleenp@548: inline const TypeNarrowOop *Type::is_narrowoop() const { coleenp@548: // OopPtr is the first and KlassPtr the last, with no non-oops between. coleenp@548: assert(_base == NarrowOop, "Not a narrow oop" ) ; coleenp@548: return (TypeNarrowOop*)this; coleenp@548: } coleenp@548: coleenp@548: inline const TypeNarrowOop *Type::isa_narrowoop() const { coleenp@548: // OopPtr is the first and KlassPtr the last, with no non-oops between. coleenp@548: return (_base == NarrowOop) ? (TypeNarrowOop*)this : NULL; coleenp@548: } coleenp@548: roland@4159: inline const TypeNarrowKlass *Type::is_narrowklass() const { roland@4159: assert(_base == NarrowKlass, "Not a narrow oop" ) ; roland@4159: return (TypeNarrowKlass*)this; roland@4159: } roland@4159: roland@4159: inline const TypeNarrowKlass *Type::isa_narrowklass() const { roland@4159: return (_base == NarrowKlass) ? (TypeNarrowKlass*)this : NULL; roland@4159: } roland@4159: coleenp@4037: inline const TypeMetadataPtr *Type::is_metadataptr() const { coleenp@4037: // MetadataPtr is the first and CPCachePtr the last coleenp@4037: assert(_base == MetadataPtr, "Not a metadata pointer" ) ; coleenp@4037: return (TypeMetadataPtr*)this; coleenp@4037: } coleenp@4037: coleenp@4037: inline const TypeMetadataPtr *Type::isa_metadataptr() const { coleenp@4037: return (_base == MetadataPtr) ? (TypeMetadataPtr*)this : NULL; coleenp@4037: } coleenp@4037: duke@435: inline const TypeKlassPtr *Type::isa_klassptr() const { duke@435: return (_base == KlassPtr) ? (TypeKlassPtr*)this : NULL; duke@435: } duke@435: duke@435: inline const TypeKlassPtr *Type::is_klassptr() const { duke@435: assert( _base == KlassPtr, "Not a klass pointer" ); duke@435: return (TypeKlassPtr*)this; duke@435: } duke@435: kvn@656: inline const TypePtr* Type::make_ptr() const { never@1262: return (_base == NarrowOop) ? is_narrowoop()->get_ptrtype() : roland@4159: ((_base == NarrowKlass) ? is_narrowklass()->get_ptrtype() : roland@4159: (isa_ptr() ? is_ptr() : NULL)); kvn@656: } kvn@656: never@1262: inline const TypeOopPtr* Type::make_oopptr() const { never@1262: return (_base == NarrowOop) ? is_narrowoop()->get_ptrtype()->is_oopptr() : is_oopptr(); never@1262: } never@1262: kvn@656: inline const TypeNarrowOop* Type::make_narrowoop() const { kvn@656: return (_base == NarrowOop) ? is_narrowoop() : kvn@656: (isa_ptr() ? TypeNarrowOop::make(is_ptr()) : NULL); kvn@656: } kvn@656: roland@4159: inline const TypeNarrowKlass* Type::make_narrowklass() const { roland@4159: return (_base == NarrowKlass) ? is_narrowklass() : roland@4159: (isa_ptr() ? TypeNarrowKlass::make(is_ptr()) : NULL); roland@4159: } roland@4159: duke@435: inline bool Type::is_floatingpoint() const { duke@435: if( (_base == FloatCon) || (_base == FloatBot) || duke@435: (_base == DoubleCon) || (_base == DoubleBot) ) duke@435: return true; duke@435: return false; duke@435: } duke@435: kvn@5110: inline bool Type::is_ptr_to_boxing_obj() const { kvn@5110: const TypeInstPtr* tp = isa_instptr(); kvn@5110: return (tp != NULL) && (tp->offset() == 0) && kvn@5110: tp->klass()->is_instance_klass() && kvn@5110: tp->klass()->as_instance_klass()->is_box_klass(); kvn@5110: } kvn@5110: duke@435: duke@435: // =============================================================== duke@435: // Things that need to be 64-bits in the 64-bit build but duke@435: // 32-bits in the 32-bit build. Done this way to get full duke@435: // optimization AND strong typing. duke@435: #ifdef _LP64 duke@435: duke@435: // For type queries and asserts duke@435: #define is_intptr_t is_long duke@435: #define isa_intptr_t isa_long duke@435: #define find_intptr_t_type find_long_type duke@435: #define find_intptr_t_con find_long_con duke@435: #define TypeX TypeLong duke@435: #define Type_X Type::Long duke@435: #define TypeX_X TypeLong::LONG duke@435: #define TypeX_ZERO TypeLong::ZERO duke@435: // For 'ideal_reg' machine registers duke@435: #define Op_RegX Op_RegL duke@435: // For phase->intcon variants duke@435: #define MakeConX longcon duke@435: #define ConXNode ConLNode duke@435: // For array index arithmetic duke@435: #define MulXNode MulLNode duke@435: #define AndXNode AndLNode duke@435: #define OrXNode OrLNode duke@435: #define CmpXNode CmpLNode duke@435: #define SubXNode SubLNode duke@435: #define LShiftXNode LShiftLNode duke@435: // For object size computation: duke@435: #define AddXNode AddLNode never@452: #define RShiftXNode RShiftLNode duke@435: // For card marks and hashcodes duke@435: #define URShiftXNode URShiftLNode kvn@855: // UseOptoBiasInlining kvn@855: #define XorXNode XorLNode kvn@855: #define StoreXConditionalNode StoreLConditionalNode duke@435: // Opcodes duke@435: #define Op_LShiftX Op_LShiftL duke@435: #define Op_AndX Op_AndL duke@435: #define Op_AddX Op_AddL duke@435: #define Op_SubX Op_SubL kvn@1286: #define Op_XorX Op_XorL kvn@1286: #define Op_URShiftX Op_URShiftL duke@435: // conversions duke@435: #define ConvI2X(x) ConvI2L(x) duke@435: #define ConvL2X(x) (x) duke@435: #define ConvX2I(x) ConvL2I(x) duke@435: #define ConvX2L(x) (x) poonam@6425: #define ConvX2UL(x) (x) duke@435: duke@435: #else duke@435: duke@435: // For type queries and asserts duke@435: #define is_intptr_t is_int duke@435: #define isa_intptr_t isa_int duke@435: #define find_intptr_t_type find_int_type duke@435: #define find_intptr_t_con find_int_con duke@435: #define TypeX TypeInt duke@435: #define Type_X Type::Int duke@435: #define TypeX_X TypeInt::INT duke@435: #define TypeX_ZERO TypeInt::ZERO duke@435: // For 'ideal_reg' machine registers duke@435: #define Op_RegX Op_RegI duke@435: // For phase->intcon variants duke@435: #define MakeConX intcon duke@435: #define ConXNode ConINode duke@435: // For array index arithmetic duke@435: #define MulXNode MulINode duke@435: #define AndXNode AndINode duke@435: #define OrXNode OrINode duke@435: #define CmpXNode CmpINode duke@435: #define SubXNode SubINode duke@435: #define LShiftXNode LShiftINode duke@435: // For object size computation: duke@435: #define AddXNode AddINode never@452: #define RShiftXNode RShiftINode duke@435: // For card marks and hashcodes duke@435: #define URShiftXNode URShiftINode kvn@855: // UseOptoBiasInlining kvn@855: #define XorXNode XorINode kvn@855: #define StoreXConditionalNode StoreIConditionalNode duke@435: // Opcodes duke@435: #define Op_LShiftX Op_LShiftI duke@435: #define Op_AndX Op_AndI duke@435: #define Op_AddX Op_AddI duke@435: #define Op_SubX Op_SubI kvn@1286: #define Op_XorX Op_XorI kvn@1286: #define Op_URShiftX Op_URShiftI duke@435: // conversions duke@435: #define ConvI2X(x) (x) duke@435: #define ConvL2X(x) ConvL2I(x) duke@435: #define ConvX2I(x) (x) duke@435: #define ConvX2L(x) ConvI2L(x) poonam@6425: #define ConvX2UL(x) ConvI2UL(x) duke@435: duke@435: #endif stefank@2314: stefank@2314: #endif // SHARE_VM_OPTO_TYPE_HPP