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