< prev index next > src/hotspot/share/opto/type.hpp
Print this page
*/
#ifndef SHARE_OPTO_TYPE_HPP
#define SHARE_OPTO_TYPE_HPP
+ #include "ci/ciInlineKlass.hpp"
#include "opto/adlcVMDeps.hpp"
#include "runtime/handles.hpp"
+ #include "runtime/sharedRuntime.hpp"
// Portions of code courtesy of Clifford Click
// Optimization - Graph Style
class TypeNarrowPtr;
class TypeNarrowOop;
class TypeNarrowKlass;
class TypeAry;
class TypeTuple;
+ class TypeInlineType;
class TypeVect;
class TypeVectA;
class TypeVectS;
class TypeVectD;
class TypeVectX;
VectorS, // 32bit Vector types
VectorD, // 64bit Vector types
VectorX, // 128bit Vector types
VectorY, // 256bit Vector types
VectorZ, // 512bit Vector types
+ InlineType, // Inline type
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)
enum OFFSET_SIGNALS {
OffsetTop = -2000000000, // undefined offset
OffsetBot = -2000000001 // any possible offset
};
+ class Offset {
+ private:
+ int _offset;
+
+ public:
+ explicit Offset(int offset) : _offset(offset) {}
+
+ const Offset meet(const Offset other) const;
+ const Offset dual() const;
+ const Offset add(intptr_t offset) const;
+ bool operator==(const Offset& other) const {
+ return _offset == other._offset;
+ }
+ bool operator!=(const Offset& other) const {
+ return _offset != other._offset;
+ }
+ int get() const { return _offset; }
+
+ void dump2(outputStream *st) const;
+
+ static const Offset top;
+ static const Offset bottom;
+ };
+
// Min and max WIDEN values.
enum WIDEN {
WidenMin = 0,
WidenMax = 3
};
// 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 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 TypeInlineType* isa_inlinetype() const; // Returns NULL if not Inline Type
+ const TypeInlineType* is_inlinetype() const; // Inline Type
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
const TypeAryKlassPtr *is_aryklassptr() const; // assert if not AryKlassPtr
virtual bool is_finite() const; // Has a finite value
virtual bool is_nan() const; // Is not a number (NaN)
+ bool is_inlinetypeptr() const;
+ virtual ciInlineKlass* inline_klass() const;
+
// 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.
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
// Memory for Control, I_O, Memory, FramePtr, and ReturnAdr is allocated implicitly
static const Type **fields( uint arg_cnt );
assert(i < _cnt, "oob");
_fields[i] = t;
}
static const TypeTuple *make( uint cnt, const Type **fields );
! static const TypeTuple *make_range(ciSignature* sig, bool ret_vt_fields = false);
! static const TypeTuple *make_domain(ciMethod* method, bool vt_fields_as_args = false);
// Subroutine call type with space allocated for argument types
// Memory for Control, I_O, Memory, FramePtr, and ReturnAdr is allocated implicitly
static const Type **fields( uint arg_cnt );
};
//------------------------------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;
virtual const Type* cleanup_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)
};
//------------------------------TypeAry----------------------------------------
// Class of Array Types
class TypeAry : public Type {
! TypeAry(const Type* elem, const TypeInt* size, bool stable, bool not_flat, bool not_null_free) : Type(Array),
! _elem(elem), _size(size), _stable(stable), _not_flat(not_flat), _not_null_free(not_null_free) {}
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?
+
+ // Inline type array properties
+ const bool _not_flat; // Array is never flattened
+ const bool _not_null_free; // Array is never null-free
+
friend class TypeAryPtr;
public:
! static const TypeAry* make(const Type* elem, const TypeInt* size, bool stable = false,
+ bool not_flat = false, bool not_null_free = 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;
virtual const Type* cleanup_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
};
+
+ //------------------------------TypeValue---------------------------------------
+ // Class of Inline Type Types
+ class TypeInlineType : public Type {
+ private:
+ ciInlineKlass* _vk;
+ bool _larval;
+
+ protected:
+ TypeInlineType(ciInlineKlass* vk, bool larval)
+ : Type(InlineType),
+ _vk(vk), _larval(larval) {
+ }
+
+ public:
+ static const TypeInlineType* make(ciInlineKlass* vk, bool larval = false);
+ virtual ciInlineKlass* inline_klass() const { return _vk; }
+ bool larval() const { return _larval; }
+
+ 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
+
+ virtual const Type* xmeet(const Type* t) const;
+ virtual const Type* xdual() const; // Compute dual right now.
+
+ virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const { return false; }
+ virtual bool would_improve_ptr(ProfilePtrKind ptr_kind) const { return false; }
+
+ virtual bool maybe_null() const { return false; }
+
+ static const TypeInlineType* BOTTOM;
+
+ #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)
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,
const TypePtr* speculative = NULL,
int inline_depth = InlineDepthBottom) :
Type(t), _speculative(speculative), _inline_depth(inline_depth), _offset(offset),
_ptr(ptr) {}
static const PTR ptr_meet[lastPTR][lastPTR];
class TypePtr : public Type {
friend class TypeNarrowPtr;
public:
enum PTR { TopPTR, AnyNull, Constant, Null, NotNull, BotPTR, lastPTR };
protected:
! TypePtr(TYPES t, PTR ptr, Offset offset,
const TypePtr* speculative = NULL,
int inline_depth = InlineDepthBottom) :
Type(t), _speculative(speculative), _inline_depth(inline_depth), _offset(offset),
_ptr(ptr) {}
static const PTR ptr_meet[lastPTR][lastPTR];
NOT_SUBTYPE,
LCA
};
static MeetResult
meet_instptr(PTR &ptr, ciKlass* this_klass, ciKlass* tinst_klass, bool this_xk, bool tinst_xk, PTR this_ptr,
! PTR tinst_ptr, ciKlass*&res_klass, bool &res_xk);
! static MeetResult
! meet_aryptr(PTR& ptr, const Type*& elem, ciKlass* this_klass, ciKlass* tap_klass, bool this_xk, bool tap_xk, PTR this_ptr, PTR tap_ptr, ciKlass*& res_klass, bool& res_xk);
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,
const TypePtr* speculative = NULL,
int inline_depth = InlineDepthBottom);
// 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 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
virtual const Type *xmeet( const Type *t ) const;
virtual const Type *xmeet_helper( 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()]; }
NOT_SUBTYPE,
LCA
};
static MeetResult
meet_instptr(PTR &ptr, ciKlass* this_klass, ciKlass* tinst_klass, bool this_xk, bool tinst_xk, PTR this_ptr,
! PTR tinst_ptr, bool this_flatten_array, bool tinst_flatten_array, ciKlass*&res_klass, bool &res_xk,
! bool& res_flatten_array);
!
+ static MeetResult meet_aryptr(PTR &ptr, const Type* this_elem, const Type* tap_elem, ciKlass* this_klass, ciKlass* tap_klass,
+ bool this_xk, bool tap_xk, PTR this_ptr, PTR tap_ptr, bool this_not_flat, bool tap_not_flat,
+ bool this_not_null_free, bool tap_not_null_free, const Type*& res_elem, ciKlass*&res_klass,
+ bool &res_xk, bool &res_not_flat, bool &res_not_null_free);
public:
! const Offset _offset; // Offset into oop, with TOP & BOT
const PTR _ptr; // Pointer equivalence class
! const int offset() const { return _offset.get(); }
const PTR ptr() const { return _ptr; }
! static const TypePtr* make(TYPES t, PTR ptr, Offset offset,
const TypePtr* speculative = NULL,
int inline_depth = InlineDepthBottom);
// Return a 'ptr' version of this type
virtual const Type *cast_to_ptr_type(PTR ptr) const;
virtual intptr_t get_con() const;
! Offset xadd_offset(intptr_t offset) const;
virtual const TypePtr *add_offset( intptr_t offset ) const;
+ virtual const int flattened_offset() const { return offset(); }
+
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
virtual const Type *xmeet( const Type *t ) const;
virtual const Type *xmeet_helper( const Type *t ) const;
! Offset meet_offset(int offset) const;
! Offset 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()]; }
virtual bool would_improve_ptr(ProfilePtrKind maybe_null) const;
virtual const TypePtr* with_inline_depth(int depth) const;
virtual bool maybe_null() const { return meet_ptr(Null) == ptr(); }
+ virtual bool can_be_inline_type() const { return false; }
+ virtual bool flatten_array() const { return false; }
+ virtual bool is_flat() const { return false; }
+ virtual bool is_not_flat() const { return false; }
+ virtual bool is_null_free() const { return false; }
+ virtual bool is_not_null_free() const { return false; }
+
// 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;
//------------------------------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
//------------------------------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,Offset(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
//------------------------------TypeOopPtr-------------------------------------
// Some kind of oop (Java pointer), either 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 TypePtr* speculative, int inline_depth);
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 {
//------------------------------TypeOopPtr-------------------------------------
// Some kind of oop (Java pointer), either instance or array.
class TypeOopPtr : public TypePtr {
protected:
! TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, Offset offset, Offset field_offset,
! int instance_id, const TypePtr* speculative, int inline_depth);
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 {
// If require_constant, produce a NULL if a singleton is not possible.
static const TypeOopPtr* make_from_constant(ciObject* o,
bool require_constant = false);
// Make a generic (unclassed) pointer to an oop.
! static const TypeOopPtr* make(PTR ptr, int offset, int instance_id,
const TypePtr* speculative = NULL,
int inline_depth = InlineDepthBottom);
ciObject* const_oop() const { return _const_oop; }
virtual ciKlass* klass() const { return _klass; }
// If require_constant, produce a NULL if a singleton is not possible.
static const TypeOopPtr* make_from_constant(ciObject* o,
bool require_constant = false);
// Make a generic (unclassed) pointer to an oop.
! static const TypeOopPtr* make(PTR ptr, Offset offset, int instance_id,
const TypePtr* speculative = NULL,
int inline_depth = InlineDepthBottom);
ciObject* const_oop() const { return _const_oop; }
virtual ciKlass* klass() const { return _klass; }
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; }
virtual intptr_t get_con() const;
virtual const TypeOopPtr* cast_to_ptr_type(PTR ptr) const;
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.get() >= 0; }
+
+ virtual bool can_be_inline_type() const { return EnableValhalla && (_klass == NULL || _klass->can_be_inline_klass(_klass_is_exact)); }
virtual intptr_t get_con() const;
virtual const TypeOopPtr* cast_to_ptr_type(PTR ptr) const;
//------------------------------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 TypePtr* speculative, int inline_depth);
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 TypePtr* speculative = NULL,
int inline_depth = InlineDepthBottom);
/** 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 TypeInstPtr* cast_to_ptr_type(PTR ptr) const;
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
//------------------------------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, Offset offset,
! bool flatten_array, int instance_id, const TypePtr* speculative,
+ int inline_depth);
virtual bool eq( const Type *t ) const;
virtual int hash() const; // Type specific hashing
ciSymbol* _name; // class name
+ bool _flatten_array; // Type is flat in arrays
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, Offset(0));
}
// Make a pointer to a constant oop with offset.
! static const TypeInstPtr* make(ciObject* o, Offset offset) {
! return make(TypePtr::Constant, o->klass(), true, o, offset);
}
// Make a pointer to some value of type klass.
static const TypeInstPtr *make(PTR ptr, ciKlass* klass) {
! return make(ptr, klass, false, NULL, Offset(0));
}
// 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, Offset(0));
}
// Make a pointer to some value of type klass with offset.
! static const TypeInstPtr *make(PTR ptr, ciKlass* klass, Offset offset) {
! return make(ptr, klass, false, NULL, offset);
}
// Make a pointer to an oop.
! static const TypeInstPtr* make(PTR ptr, ciKlass* k, bool xk, ciObject* o, Offset offset,
+ bool flatten_array = false,
int instance_id = InstanceBot,
const TypePtr* speculative = NULL,
int inline_depth = InlineDepthBottom);
/** 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(bool* is_val_mirror = NULL) const;
virtual const TypeInstPtr* cast_to_ptr_type(PTR ptr) const;
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
// Speculative type helper methods.
virtual const Type* remove_speculative() const;
virtual const TypePtr* with_inline_depth(int depth) const;
virtual const TypePtr* with_instance_id(int instance_id) const;
+ virtual const TypeInstPtr* cast_to_flatten_array() const;
+ virtual bool flatten_array() const { return _flatten_array; }
+
// 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.
};
//------------------------------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 TypePtr* speculative, int inline_depth)
! : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative, inline_depth),
_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);
};
//------------------------------TypeAryPtr-------------------------------------
// Class of Java array pointers
class TypeAryPtr : public TypeOopPtr {
! TypeAryPtr(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk,
! Offset offset, Offset field_offset, int instance_id, bool is_autobox_cache,
! const TypePtr* speculative, int inline_depth)
! : TypeOopPtr(AryPtr, ptr, k, xk, o, offset, field_offset, instance_id, speculative, inline_depth),
_ary(ary),
! _is_autobox_cache(is_autobox_cache),
+ _field_offset(field_offset)
{
#ifdef ASSERT
if (k != NULL) {
// Verify that specified klass and TypeAryPtr::klass() follow the same rules.
ciKlass* ck = compute_klass(true);
}
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;
+ // For flattened inline type arrays, each field of the inline type in
+ // the array has its own memory slice so we need to keep track of
+ // which field is accessed
+ const Offset _field_offset;
+ Offset meet_field_offset(const Type::Offset offset) const;
+ Offset dual_field_offset() const;
ciKlass* compute_klass(DEBUG_ONLY(bool verify = false)) const;
public:
// Accessors
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 TypePtr* speculative = NULL,
int inline_depth = InlineDepthBottom);
// 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 TypePtr* speculative = NULL,
! int inline_depth = InlineDepthBottom, bool is_autobox_cache = false);
// Return a 'ptr' version of this type
virtual const TypeAryPtr* cast_to_ptr_type(PTR ptr) const;
virtual const Type *cast_to_exactness(bool klass_is_exact) 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; }
+ // Inline type array properties
+ bool is_flat() const { return _ary->_elem->isa_inlinetype() != NULL; }
+ bool is_not_flat() const { return _ary->_not_flat; }
+ bool is_null_free() const { return is_flat() || (_ary->_elem->make_ptr() != NULL && _ary->_elem->make_ptr()->is_inlinetypeptr() && !_ary->_elem->make_ptr()->maybe_null()); }
+ bool is_not_null_free() const { return _ary->_not_null_free; }
+
bool is_autobox_cache() const { return _is_autobox_cache; }
! static const TypeAryPtr* make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, Offset offset,
+ Offset field_offset = Offset::bottom,
int instance_id = InstanceBot,
const TypePtr* speculative = NULL,
int inline_depth = InlineDepthBottom);
// Constant pointer to array
! static const TypeAryPtr* make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, Offset offset,
+ Offset field_offset = Offset::bottom,
int instance_id = InstanceBot,
const TypePtr* speculative = NULL,
! int inline_depth = InlineDepthBottom,
+ bool is_autobox_cache = false);
// Return a 'ptr' version of this type
virtual const TypeAryPtr* cast_to_ptr_type(PTR ptr) const;
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
virtual bool empty(void) const; // TRUE if type is vacuous
virtual const TypePtr *add_offset( intptr_t offset ) const;
// Speculative type helper methods.
virtual const Type* remove_speculative() const;
virtual const TypePtr* with_inline_depth(int depth) const;
virtual const TypePtr* with_instance_id(int instance_id) 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;
const TypeAryPtr* cast_to_autobox_cache() const;
! static jint max_array_length(BasicType etype) ;
virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
// Convenience common pre-built types.
static const TypeAryPtr *RANGE;
static const TypeAryPtr *OOPS;
virtual bool empty(void) const; // TRUE if type is vacuous
virtual const TypePtr *add_offset( intptr_t offset ) const;
// Speculative type helper methods.
virtual const Type* remove_speculative() const;
+ virtual const Type* cleanup_speculative() const;
virtual const TypePtr* with_inline_depth(int depth) const;
virtual const TypePtr* with_instance_id(int instance_id) 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.
+ // Inline type array properties
+ const TypeAryPtr* cast_to_not_flat(bool not_flat = true) const;
+ const TypeAryPtr* cast_to_not_null_free(bool not_null_free = true) const;
+ const TypeAryPtr* update_properties(const TypeAryPtr* new_type) const;
+
const TypeAryPtr* cast_to_stable(bool stable, int stable_dimension = 1) const;
int stable_dimension() const;
const TypeAryPtr* cast_to_autobox_cache() const;
! static jint max_array_length(BasicType etype);
+
+ const int flattened_offset() const;
+ const Offset field_offset() const { return _field_offset; }
+ const TypeAryPtr* with_field_offset(int offset) const;
+ const TypePtr* add_field_offset_and_offset(intptr_t offset) const;
+
+ virtual bool can_be_inline_type() const { return false; }
virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
// Convenience common pre-built types.
static const TypeAryPtr *RANGE;
static const TypeAryPtr *OOPS;
static const TypeAryPtr *CHARS;
static const TypeAryPtr *INTS;
static const TypeAryPtr *LONGS;
static const TypeAryPtr *FLOATS;
static const TypeAryPtr *DOUBLES;
+ static const TypeAryPtr *INLINES;
// 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];
}
//------------------------------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
//------------------------------TypeMetadataPtr-------------------------------------
// Some kind of metadata, either Method*, MethodData* or CPCacheOop
class TypeMetadataPtr : public TypePtr {
protected:
! TypeMetadataPtr(PTR ptr, ciMetadata* metadata, Offset 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
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; }
private:
ciMetadata* _metadata;
public:
! static const TypeMetadataPtr* make(PTR ptr, ciMetadata* m, Offset offset);
static const TypeMetadataPtr* make(ciMethod* m);
static const TypeMetadataPtr* make(ciMethodData* m);
ciMetadata* metadata() const { return _metadata; }
//------------------------------TypeKlassPtr-----------------------------------
// Class of Java Klass pointers
class TypeKlassPtr : public TypePtr {
protected:
! TypeKlassPtr(TYPES t, PTR ptr, ciKlass* klass, int offset);
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
public:
virtual bool eq( const Type *t ) const;
//------------------------------TypeKlassPtr-----------------------------------
// Class of Java Klass pointers
class TypeKlassPtr : public TypePtr {
protected:
! TypeKlassPtr(TYPES t, PTR ptr, ciKlass* klass, Offset offset);
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
public:
virtual bool eq( const Type *t ) const;
virtual ciKlass* klass() const { return _klass; }
bool klass_is_exact() const { return _ptr == Constant; }
bool is_loaded() const { return klass()->is_loaded(); }
static const TypeKlassPtr* make(ciKlass* klass);
! static const TypeKlassPtr *make(PTR ptr, ciKlass* klass, int offset);
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const { ShouldNotReachHere(); return NULL; }
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const { ShouldNotReachHere(); return NULL; }
virtual ciKlass* klass() const { return _klass; }
bool klass_is_exact() const { return _ptr == Constant; }
bool is_loaded() const { return klass()->is_loaded(); }
static const TypeKlassPtr* make(ciKlass* klass);
! static const TypeKlassPtr *make(PTR ptr, ciKlass* klass, Offset offset);
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const { ShouldNotReachHere(); return NULL; }
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const { ShouldNotReachHere(); return NULL; }
virtual const Type *xdual() const { ShouldNotReachHere(); return NULL; }
virtual intptr_t get_con() const;
virtual const TypeKlassPtr* with_offset(intptr_t offset) const { ShouldNotReachHere(); return NULL; }
-
- #ifndef PRODUCT
- virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
- #endif
};
// Instance klass pointer, mirrors TypeInstPtr
class TypeInstKlassPtr : public TypeKlassPtr {
! TypeInstKlassPtr(PTR ptr, ciKlass* klass, int offset)
! : TypeKlassPtr(InstKlassPtr, ptr, klass, offset) {
}
virtual bool must_be_exact() const;
public:
// Instance klass ignoring any interface
ciInstanceKlass* instance_klass() const { return klass()->as_instance_klass(); }
static const TypeInstKlassPtr *make(ciKlass* k) {
! return make(TypePtr::Constant, k, 0);
}
! static const TypeInstKlassPtr *make(PTR ptr, ciKlass* k, int offset);
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const;
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const;
virtual const Type *xdual() const { ShouldNotReachHere(); return NULL; }
virtual intptr_t get_con() const;
virtual const TypeKlassPtr* with_offset(intptr_t offset) const { ShouldNotReachHere(); return NULL; }
};
// Instance klass pointer, mirrors TypeInstPtr
class TypeInstKlassPtr : public TypeKlassPtr {
! TypeInstKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array)
! : TypeKlassPtr(InstKlassPtr, ptr, klass, offset), _flatten_array(flatten_array) {
}
virtual bool must_be_exact() const;
+ const bool _flatten_array; // Type is flat in arrays
+
public:
// Instance klass ignoring any interface
ciInstanceKlass* instance_klass() const { return klass()->as_instance_klass(); }
+ virtual bool can_be_inline_type() const { return EnableValhalla && (_klass == NULL || _klass->can_be_inline_klass(klass_is_exact())); }
+
static const TypeInstKlassPtr *make(ciKlass* k) {
! return make(TypePtr::Constant, k, Offset(0), false);
}
! static const TypeInstKlassPtr *make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array = false);
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const;
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const;
virtual const TypePtr *add_offset( intptr_t offset ) const;
virtual const Type *xmeet( const Type *t ) const;
virtual const Type *xdual() const;
virtual const TypeKlassPtr* with_offset(intptr_t offset) const;
// Convenience common pre-built types.
static const TypeInstKlassPtr* OBJECT; // Not-null object klass or below
static const TypeInstKlassPtr* OBJECT_OR_NULL; // Maybe-null version of same
};
// Array klass pointer, mirrors TypeAryPtr
class TypeAryKlassPtr : public TypeKlassPtr {
const Type *_elem;
! TypeAryKlassPtr(PTR ptr, const Type *elem, ciKlass* klass, int offset)
! : TypeKlassPtr(AryKlassPtr, ptr, klass, offset), _elem(elem) {
}
virtual bool must_be_exact() const;
public:
virtual ciKlass* klass() const;
// returns base element type, an instance klass (and not interface) for object arrays
const Type* base_element_type(int& dims) const;
! static const TypeAryKlassPtr *make(PTR ptr, ciKlass* k, int offset);
! static const TypeAryKlassPtr *make(PTR ptr, const Type *elem, ciKlass* k, int offset);
! static const TypeAryKlassPtr* make(ciKlass* klass);
const Type *elem() const { return _elem; }
virtual bool eq(const Type *t) const;
virtual int hash() const; // Type specific hashing
virtual const TypePtr *add_offset( intptr_t offset ) const;
virtual const Type *xmeet( const Type *t ) const;
virtual const Type *xdual() const;
virtual const TypeKlassPtr* with_offset(intptr_t offset) const;
+ virtual bool flatten_array() const { return _flatten_array; }
+
// Convenience common pre-built types.
static const TypeInstKlassPtr* OBJECT; // Not-null object klass or below
static const TypeInstKlassPtr* 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
};
// Array klass pointer, mirrors TypeAryPtr
class TypeAryKlassPtr : public TypeKlassPtr {
const Type *_elem;
+ const bool _not_flat; // Array is never flattened
+ const bool _not_null_free; // Array is never null-free
+ const bool _null_free;
! TypeAryKlassPtr(PTR ptr, const Type *elem, ciKlass* klass, Offset offset, bool not_flat, int not_null_free, bool null_free)
! : TypeKlassPtr(AryKlassPtr, ptr, klass, offset), _elem(elem), _not_flat(not_flat), _not_null_free(not_null_free), _null_free(null_free) {
}
virtual bool must_be_exact() const;
+ bool dual_null_free() const {
+ return _null_free;
+ }
+
+ bool meet_null_free(bool other) const {
+ return _null_free && other;
+ }
+
public:
virtual ciKlass* klass() const;
// returns base element type, an instance klass (and not interface) for object arrays
const Type* base_element_type(int& dims) const;
! static const TypeAryKlassPtr *make(PTR ptr, ciKlass* k, Offset offset, bool not_flat, bool not_null_free, bool null_free);
! static const TypeAryKlassPtr *make(PTR ptr, const Type *elem, ciKlass* k, Offset offset, bool not_flat, bool not_null_free, bool null_free);
! static const TypeAryKlassPtr* make(ciKlass* klass, PTR ptr = Constant, Offset offset= Offset(0));
const Type *elem() const { return _elem; }
virtual bool eq(const Type *t) const;
virtual int hash() const; // Type specific hashing
virtual bool empty(void) const {
return TypeKlassPtr::empty() || _elem->empty();
}
+ bool is_flat() const { return klass()->is_flat_array_klass(); }
+ bool is_not_flat() const { return _not_flat; }
+ bool is_null_free() const { return _null_free; }
+ bool is_not_null_free() const { return _not_null_free; }
+
#ifndef PRODUCT
virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
#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
! const TypeTuple* const _domain; // Domain of inputs
! const TypeTuple* const _range; // Range of results
public:
// Constants are shared among ADLC and VM
enum { Control = AdlcVMDeps::Control,
I_O = AdlcVMDeps::I_O,
};
//------------------------------TypeFunc---------------------------------------
// Class of Array Types
class TypeFunc : public Type {
! TypeFunc(const TypeTuple *domain_sig, const TypeTuple *domain_cc, const TypeTuple *range_sig, const TypeTuple *range_cc)
+ : Type(Function), _domain_sig(domain_sig), _domain_cc(domain_cc), _range_sig(range_sig), _range_cc(range_cc) {}
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
! // Domains of inputs: inline type arguments are not passed by
! // reference, instead each field of the inline type is passed as an
+ // argument. We maintain 2 views of the argument list here: one
+ // based on the signature (with an inline type argument as a single
+ // slot), one based on the actual calling convention (with a value
+ // type argument as a list of its fields).
+ const TypeTuple* const _domain_sig;
+ const TypeTuple* const _domain_cc;
+ // Range of results. Similar to domains: an inline type result can be
+ // returned in registers in which case range_cc lists all fields and
+ // is the actual calling convention.
+ const TypeTuple* const _range_sig;
+ const TypeTuple* const _range_cc;
public:
// Constants are shared among ADLC and VM
enum { Control = AdlcVMDeps::Control,
I_O = AdlcVMDeps::I_O,
Parms = AdlcVMDeps::Parms
};
// 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.
};
Parms = AdlcVMDeps::Parms
};
// Accessors:
! const TypeTuple* domain_sig() const { return _domain_sig; }
! const TypeTuple* domain_cc() const { return _domain_cc; }
! const TypeTuple* range_sig() const { return _range_sig; }
! const TypeTuple* range_cc() const { return _range_cc; }
!
+ static const TypeFunc* make(ciMethod* method, bool is_osr_compilation = false);
+ static const TypeFunc *make(const TypeTuple* domain_sig, const TypeTuple* domain_cc,
+ const TypeTuple* range_sig, const TypeTuple* range_cc);
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;
+ bool returns_inline_type_as_fields() const { return range_sig() != range_cc(); }
+
#ifndef PRODUCT
virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
#endif
// Convenience common pre-built types.
};
inline const TypeAryPtr *Type::is_aryptr() const {
assert( _base == AryPtr, "Not an array pointer" );
return (TypeAryPtr*)this;
}
+ inline const TypeInlineType* Type::isa_inlinetype() const {
+ return (_base == InlineType) ? (TypeInlineType*)this : NULL;
+ }
+
+ inline const TypeInlineType* Type::is_inlinetype() const {
+ assert(_base == InlineType, "Not an inline type");
+ return (TypeInlineType*)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;
}
(_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
(_base == DoubleCon) || (_base == DoubleBot) )
return true;
return false;
}
! inline bool Type::is_inlinetypeptr() const {
! return isa_instptr() != NULL && is_instptr()->klass()->is_inlinetype();
! }
!
!
+ inline ciInlineKlass* Type::inline_klass() const {
+ assert(is_inlinetypeptr(), "must be an inline type ptr");
+ return is_instptr()->klass()->as_inline_klass();
}
// ===============================================================
// Things that need to be 64-bits in the 64-bit build but
// For array index arithmetic
#define MulXNode MulLNode
#define AndXNode AndLNode
#define OrXNode OrLNode
#define CmpXNode CmpLNode
+ #define CmpUXNode CmpULNode
#define SubXNode SubLNode
#define LShiftXNode LShiftLNode
// For object size computation:
#define AddXNode AddLNode
#define RShiftXNode RShiftLNode
#define Op_AddX Op_AddL
#define Op_SubX Op_SubL
#define Op_XorX Op_XorL
#define Op_URShiftX Op_URShiftL
#define Op_LoadX Op_LoadL
+ #define Op_StoreX Op_StoreL
// conversions
#define ConvI2X(x) ConvI2L(x)
#define ConvL2X(x) (x)
#define ConvX2I(x) ConvL2I(x)
#define ConvX2L(x) (x)
// For array index arithmetic
#define MulXNode MulINode
#define AndXNode AndINode
#define OrXNode OrINode
#define CmpXNode CmpINode
+ #define CmpUXNode CmpUNode
#define SubXNode SubINode
#define LShiftXNode LShiftINode
// For object size computation:
#define AddXNode AddINode
#define RShiftXNode RShiftINode
#define Op_AddX Op_AddI
#define Op_SubX Op_SubI
#define Op_XorX Op_XorI
#define Op_URShiftX Op_URShiftI
#define Op_LoadX Op_LoadI
+ #define Op_StoreX Op_StoreI
// conversions
#define ConvI2X(x) (x)
#define ConvL2X(x) ConvL2I(x)
#define ConvX2I(x) (x)
#define ConvX2L(x) ConvI2L(x)
< prev index next >