< prev index next >

src/hotspot/share/opto/type.hpp

Print this page
*** 23,12 ***
--- 23,14 ---
   */
  
  #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
  

*** 134,10 ***
--- 136,34 ---
    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
    };

*** 324,10 ***
--- 350,13 ---
    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.

*** 722,12 ***
      assert(i < _cnt, "oob");
      _fields[i] = t;
    }
  
    static const TypeTuple *make( uint cnt, const Type **fields );
!   static const TypeTuple *make_range(ciSignature *sig, InterfaceHandling interface_handling = ignore_interfaces);
!   static const TypeTuple *make_domain(ciInstanceKlass* recv, ciSignature *sig, InterfaceHandling interface_handling);
  
    // 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 );
  
--- 751,12 ---
      assert(i < _cnt, "oob");
      _fields[i] = t;
    }
  
    static const TypeTuple *make( uint cnt, const Type **fields );
!   static const TypeTuple *make_range(ciSignature* sig, InterfaceHandling interface_handling = ignore_interfaces, bool ret_vt_fields = false);
!   static const TypeTuple *make_domain(ciMethod* method, InterfaceHandling interface_handling, 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 );
  

*** 752,26 ***
  };
  
  //------------------------------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 uint 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 TypeAry* remove_speculative() const;
--- 781,33 ---
  };
  
  //------------------------------TypeAry----------------------------------------
  // Class of Array Types
  class TypeAry : public Type {
!   TypeAry(const Type* elem, const TypeInt* size, bool stable, bool flat, bool not_flat, bool not_null_free) : Type(Array),
!       _elem(elem), _size(size), _stable(stable), _flat(flat), _not_flat(not_flat), _not_null_free(not_null_free) {}
  public:
    virtual bool eq( const Type *t ) const;
    virtual uint 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 _flat;             // Array is flat
+   const bool _not_flat;         // Array is never flat
+   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 flat = 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 TypeAry* remove_speculative() const;

*** 928,11 ***
    static const TypeInterfaces* interfaces(ciKlass*& k, bool klass, bool interface, bool array, InterfaceHandling interface_handling);
  
  public:
    enum PTR { TopPTR, AnyNull, Constant, Null, NotNull, BotPTR, lastPTR };
  protected:
!   TypePtr(TYPES t, PTR ptr, int offset,
            const TypePtr* speculative = nullptr,
            int inline_depth = InlineDepthBottom) :
      Type(t), _speculative(speculative), _inline_depth(inline_depth), _offset(offset),
      _ptr(ptr) {}
    static const PTR ptr_meet[lastPTR][lastPTR];
--- 964,11 ---
    static const TypeInterfaces* interfaces(ciKlass*& k, bool klass, bool interface, bool array, InterfaceHandling interface_handling);
  
  public:
    enum PTR { TopPTR, AnyNull, Constant, Null, NotNull, BotPTR, lastPTR };
  protected:
!   TypePtr(TYPES t, PTR ptr, Offset offset,
            const TypePtr* speculative = nullptr,
            int inline_depth = InlineDepthBottom) :
      Type(t), _speculative(speculative), _inline_depth(inline_depth), _offset(offset),
      _ptr(ptr) {}
    static const PTR ptr_meet[lastPTR][lastPTR];

*** 984,51 ***
      SUBTYPE,
      NOT_SUBTYPE,
      LCA
    };
    template<class T> static TypePtr::MeetResult meet_instptr(PTR& ptr, const TypeInterfaces*& interfaces, const T* this_type,
!                                                             const T* other_type, ciKlass*& res_klass, bool& res_xk);
  
    template<class T> static MeetResult meet_aryptr(PTR& ptr, const Type*& elem, const T* this_ary, const T* other_ary,
!                                                   ciKlass*& res_klass, bool& res_xk);
  
    template <class T1, class T2> static bool is_java_subtype_of_helper_for_instance(const T1* this_one, const T2* other, bool this_exact, bool other_exact);
    template <class T1, class T2> static bool is_same_java_type_as_helper_for_instance(const T1* this_one, const T2* other);
    template <class T1, class T2> static bool maybe_java_subtype_of_helper_for_instance(const T1* this_one, const T2* other, bool this_exact, bool other_exact);
    template <class T1, class T2> static bool is_java_subtype_of_helper_for_array(const T1* this_one, const T2* other, bool this_exact, bool other_exact);
    template <class T1, class T2> static bool is_same_java_type_as_helper_for_array(const T1* this_one, const T2* other);
    template <class T1, class T2> static bool maybe_java_subtype_of_helper_for_array(const T1* this_one, const T2* other, bool this_exact, bool other_exact);
    template <class T1, class T2> static bool is_meet_subtype_of_helper_for_instance(const T1* this_one, const T2* other, bool this_xk, bool other_xk);
    template <class T1, class T2> static bool is_meet_subtype_of_helper_for_array(const T1* this_one, const T2* other, bool this_xk, bool other_xk);
  public:
!   const int _offset;            // Offset into oop, with TOP & BOT
    const PTR _ptr;               // Pointer equivalence class
  
!   int offset() const { return _offset; }
    PTR ptr()    const { return _ptr; }
  
!   static const TypePtr *make(TYPES t, PTR ptr, int offset,
                               const TypePtr* speculative = nullptr,
                               int inline_depth = InlineDepthBottom);
  
    // Return a 'ptr' version of this type
    virtual const TypePtr* 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 const TypePtr* with_offset(intptr_t offset) const;
    virtual bool eq(const Type *t) const;
    virtual uint 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()];      }
--- 1020,52 ---
      SUBTYPE,
      NOT_SUBTYPE,
      LCA
    };
    template<class T> static TypePtr::MeetResult meet_instptr(PTR& ptr, const TypeInterfaces*& interfaces, const T* this_type,
!                                                             const T* other_type, ciKlass*& res_klass, bool& res_xk, bool& res_flat_array);
  
    template<class T> static MeetResult meet_aryptr(PTR& ptr, const Type*& elem, const T* this_ary, const T* other_ary,
!                                                   ciKlass*& res_klass, bool& res_xk, bool &res_flat, bool &res_not_flat, bool &res_not_null_free);
  
    template <class T1, class T2> static bool is_java_subtype_of_helper_for_instance(const T1* this_one, const T2* other, bool this_exact, bool other_exact);
    template <class T1, class T2> static bool is_same_java_type_as_helper_for_instance(const T1* this_one, const T2* other);
    template <class T1, class T2> static bool maybe_java_subtype_of_helper_for_instance(const T1* this_one, const T2* other, bool this_exact, bool other_exact);
    template <class T1, class T2> static bool is_java_subtype_of_helper_for_array(const T1* this_one, const T2* other, bool this_exact, bool other_exact);
    template <class T1, class T2> static bool is_same_java_type_as_helper_for_array(const T1* this_one, const T2* other);
    template <class T1, class T2> static bool maybe_java_subtype_of_helper_for_array(const T1* this_one, const T2* other, bool this_exact, bool other_exact);
    template <class T1, class T2> static bool is_meet_subtype_of_helper_for_instance(const T1* this_one, const T2* other, bool this_xk, bool other_xk);
    template <class T1, class T2> static bool is_meet_subtype_of_helper_for_array(const T1* this_one, const T2* other, bool this_xk, bool other_xk);
  public:
!   const Offset _offset;         // Offset into oop, with TOP & BOT
    const PTR _ptr;               // Pointer equivalence class
  
!   int offset() const { return _offset.get(); }
    PTR ptr()    const { return _ptr; }
  
!   static const TypePtr* make(TYPES t, PTR ptr, Offset offset,
                               const TypePtr* speculative = nullptr,
                               int inline_depth = InlineDepthBottom);
  
    // Return a 'ptr' version of this type
    virtual const TypePtr* cast_to_ptr_type(PTR ptr) const;
  
    virtual intptr_t get_con() const;
  
!   Type::Offset xadd_offset(intptr_t offset) const;
    virtual const TypePtr* add_offset(intptr_t offset) const;
    virtual const TypePtr* with_offset(intptr_t offset) const;
+   virtual int flat_offset() const { return offset(); }
    virtual bool eq(const Type *t) const;
    virtual uint 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()];      }

*** 1052,10 ***
--- 1089,18 ---
    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 flat_in_array()      const { return false; }
+   virtual bool not_flat_in_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;

*** 1069,11 ***
  //------------------------------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 uint hash() const;    // Type specific hashing
  
    const address _bits;          // Constant value, if applicable
--- 1114,11 ---
  //------------------------------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 uint hash() const;    // Type specific hashing
  
    const address _bits;          // Constant value, if applicable

*** 1105,11 ***
    friend class TypeAry;
    friend class TypePtr;
    friend class TypeInstPtr;
    friend class TypeAryPtr;
  protected:
!  TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, const TypeInterfaces* interfaces, bool xk, ciObject* o, int offset, int instance_id,
              const TypePtr* speculative, int inline_depth);
  public:
    virtual bool eq( const Type *t ) const;
    virtual uint hash() const;             // Type specific hashing
    virtual bool singleton(void) const;    // TRUE if type is a singleton
--- 1150,11 ---
    friend class TypeAry;
    friend class TypePtr;
    friend class TypeInstPtr;
    friend class TypeAryPtr;
  protected:
!  TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, const TypeInterfaces* interfaces, 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 uint hash() const;             // Type specific hashing
    virtual bool singleton(void) const;    // TRUE if type is a singleton

*** 1146,11 ***
  
    // Do not allow interface-vs.-noninterface joins to collapse to top.
    virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
  
    virtual ciKlass* exact_klass_helper() const { return nullptr; }
!   virtual ciKlass* klass() const { return _klass;     }
  
  public:
  
    bool is_java_subtype_of(const TypeOopPtr* other) const {
      return is_java_subtype_of_helper(other, klass_is_exact(), other->klass_is_exact());
--- 1191,11 ---
  
    // Do not allow interface-vs.-noninterface joins to collapse to top.
    virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
  
    virtual ciKlass* exact_klass_helper() const { return nullptr; }
!   virtual ciKlass* klass() const { return _klass; }
  
  public:
  
    bool is_java_subtype_of(const TypeOopPtr* other) const {
      return is_java_subtype_of_helper(other, klass_is_exact(), other->klass_is_exact());

*** 1193,11 ***
    // 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 = nullptr,
                                  int inline_depth = InlineDepthBottom);
  
    ciObject* const_oop()    const { return _const_oop; }
    // Exact klass, possibly an interface or an array of interface
--- 1238,11 ---
    // 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 = nullptr,
                                  int inline_depth = InlineDepthBottom);
  
    ciObject* const_oop()    const { return _const_oop; }
    // Exact klass, possibly an interface or an array of interface

*** 1212,11 ***
    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;
  
--- 1257,14 ---
    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 (_klass == nullptr || _klass->can_be_inline_klass(_klass_is_exact)); }
+   virtual bool can_be_inline_array() const { ShouldNotReachHere(); return false; }
  
    virtual intptr_t get_con() const;
  
    virtual const TypeOopPtr* cast_to_ptr_type(PTR ptr) const;
  

*** 1275,15 ***
  
  //------------------------------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, const TypeInterfaces* interfaces, bool xk, ciObject* o, int off, int instance_id,
!               const TypePtr* speculative, int inline_depth);
    virtual bool eq( const Type *t ) const;
    virtual uint hash() const;             // Type specific hashing
! 
    ciKlass* exact_klass_helper() const;
  
  public:
  
    // Instance klass, ignoring any interface
--- 1323,16 ---
  
  //------------------------------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, const TypeInterfaces* interfaces, bool xk, ciObject* o, Offset offset,
!               bool flat_in_array, int instance_id, const TypePtr* speculative,
+               int inline_depth);
    virtual bool eq( const Type *t ) const;
    virtual uint hash() const;             // Type specific hashing
!   bool _flat_in_array; // Type is flat in arrays
    ciKlass* exact_klass_helper() const;
  
  public:
  
    // Instance klass, ignoring any interface

*** 1298,45 ***
  
    // Make a pointer to a constant oop.
    static const TypeInstPtr *make(ciObject* o) {
      ciKlass* k = o->klass();
      const TypeInterfaces* interfaces = TypePtr::interfaces(k, true, false, false, ignore_interfaces);
!     return make(TypePtr::Constant, k, interfaces, true, o, 0, InstanceBot);
    }
    // Make a pointer to a constant oop with offset.
!   static const TypeInstPtr *make(ciObject* o, int offset) {
      ciKlass* k = o->klass();
      const TypeInterfaces* interfaces = TypePtr::interfaces(k, true, false, false, ignore_interfaces);
!     return make(TypePtr::Constant, k, interfaces, true, o, offset, InstanceBot);
    }
  
    // Make a pointer to some value of type klass.
    static const TypeInstPtr *make(PTR ptr, ciKlass* klass, InterfaceHandling interface_handling = ignore_interfaces) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(klass, true, true, false, interface_handling);
!     return make(ptr, klass, interfaces, false, nullptr, 0, InstanceBot);
    }
  
    // Make a pointer to some non-polymorphic value of exactly type klass.
    static const TypeInstPtr *make_exact(PTR ptr, ciKlass* klass) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(klass, true, false, false, ignore_interfaces);
!     return make(ptr, klass, interfaces, true, nullptr, 0, InstanceBot);
    }
  
    // Make a pointer to some value of type klass with offset.
!   static const TypeInstPtr *make(PTR ptr, ciKlass* klass, int offset) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(klass, true, false, false, ignore_interfaces);
!     return make(ptr, klass, interfaces, false, nullptr, offset, InstanceBot);
    }
  
!   static const TypeInstPtr *make(PTR ptr, ciKlass* k, const TypeInterfaces* interfaces, bool xk, ciObject* o, int offset,
                                   int instance_id = InstanceBot,
                                   const TypePtr* speculative = nullptr,
                                   int inline_depth = InlineDepthBottom);
  
!   static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(k, true, false, false, ignore_interfaces);
!     return make(ptr, k, interfaces, xk, o, offset, instance_id);
    }
  
    /** Create constant type for a constant boxed value */
    const Type* get_const_boxed_value() const;
  
--- 1347,47 ---
  
    // Make a pointer to a constant oop.
    static const TypeInstPtr *make(ciObject* o) {
      ciKlass* k = o->klass();
      const TypeInterfaces* interfaces = TypePtr::interfaces(k, true, false, false, ignore_interfaces);
!     return make(TypePtr::Constant, k, interfaces, true, o, Offset(0));
    }
    // Make a pointer to a constant oop with offset.
!   static const TypeInstPtr *make(ciObject* o, Offset offset) {
      ciKlass* k = o->klass();
      const TypeInterfaces* interfaces = TypePtr::interfaces(k, true, false, false, ignore_interfaces);
!     return make(TypePtr::Constant, k, interfaces, true, o, offset);
    }
  
    // Make a pointer to some value of type klass.
    static const TypeInstPtr *make(PTR ptr, ciKlass* klass, InterfaceHandling interface_handling = ignore_interfaces) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(klass, true, true, false, interface_handling);
!     return make(ptr, klass, interfaces, false, nullptr, Offset(0));
    }
  
    // Make a pointer to some non-polymorphic value of exactly type klass.
    static const TypeInstPtr *make_exact(PTR ptr, ciKlass* klass) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(klass, true, false, false, ignore_interfaces);
!     return make(ptr, klass, interfaces, true, nullptr, Offset(0));
    }
  
    // Make a pointer to some value of type klass with offset.
!   static const TypeInstPtr *make(PTR ptr, ciKlass* klass, Offset offset) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(klass, true, false, false, ignore_interfaces);
!     return make(ptr, klass, interfaces, false, nullptr, offset);
    }
  
!   // Make a pointer to an oop.
+   static const TypeInstPtr* make(PTR ptr, ciKlass* k, const TypeInterfaces* interfaces, bool xk, ciObject* o, Offset offset,
+                                  bool flat_in_array = false,
                                   int instance_id = InstanceBot,
                                   const TypePtr* speculative = nullptr,
                                   int inline_depth = InlineDepthBottom);
  
!   static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, Offset offset, int instance_id = InstanceBot) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(k, true, false, false, ignore_interfaces);
!     return make(ptr, k, interfaces, xk, o, offset, false, instance_id);
    }
  
    /** Create constant type for a constant boxed value */
    const Type* get_const_boxed_value() const;
  

*** 1357,17 ***
--- 1408,23 ---
    // Speculative type helper methods.
    virtual const TypeInstPtr* 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_flat_in_array() const;
+   virtual bool flat_in_array() const { return _flat_in_array; }
+   virtual bool not_flat_in_array() const { return !can_be_inline_type() || (_klass->is_inlinetype() && !flat_in_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 *tinst, const TypeInterfaces* interfaces) const;
    virtual const Type *xdual() const;    // Compute dual right now.
  
    const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
  
+   virtual bool can_be_inline_array() const;
+ 
    // Convenience common pre-built types.
    static const TypeInstPtr *NOTNULL;
    static const TypeInstPtr *BOTTOM;
    static const TypeInstPtr *MIRROR;
    static const TypeInstPtr *MARK;

*** 1388,32 ***
  //------------------------------TypeAryPtr-------------------------------------
  // Class of Java array pointers
  class TypeAryPtr : public TypeOopPtr {
    friend class Type;
    friend class TypePtr;
  
!   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,_array_interfaces,xk,o,offset, instance_id, speculative, inline_depth),
      _ary(ary),
!     _is_autobox_cache(is_autobox_cache)
   {
      int dummy;
      bool top_or_bottom = (base_element_type(dummy) == Type::TOP || base_element_type(dummy) == Type::BOTTOM);
  
      if (UseCompressedOops && (elem()->make_oopptr() != nullptr && !top_or_bottom) &&
!         _offset != 0 && _offset != arrayOopDesc::length_offset_in_bytes() &&
!         _offset != arrayOopDesc::klass_offset_in_bytes()) {
        _is_ptr_to_narrowoop = true;
      }
  
    }
    virtual bool eq( const Type *t ) const;
    virtual uint 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;
  
    // A pointer to delay allocation to Type::Initialize_shared()
  
--- 1445,40 ---
  //------------------------------TypeAryPtr-------------------------------------
  // Class of Java array pointers
  class TypeAryPtr : public TypeOopPtr {
    friend class Type;
    friend class TypePtr;
+   friend class TypeInstPtr;
  
!   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, _array_interfaces, xk, o, offset, field_offset, instance_id, speculative, inline_depth),
      _ary(ary),
!     _is_autobox_cache(is_autobox_cache),
+     _field_offset(field_offset)
   {
      int dummy;
      bool top_or_bottom = (base_element_type(dummy) == Type::TOP || base_element_type(dummy) == Type::BOTTOM);
  
      if (UseCompressedOops && (elem()->make_oopptr() != nullptr && !top_or_bottom) &&
!         _offset.get() != 0 && _offset.get() != arrayOopDesc::length_offset_in_bytes() &&
!         _offset.get() != arrayOopDesc::klass_offset_in_bytes()) {
        _is_ptr_to_narrowoop = true;
      }
  
    }
    virtual bool eq( const Type *t ) const;
    virtual uint hash() const;    // Type specific hashing
    const TypeAry *_ary;          // Array we point into
    const bool     _is_autobox_cache;
+   // For flat 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;
  
    // A pointer to delay allocation to Type::Initialize_shared()
  

*** 1437,21 ***
    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 = nullptr,
                                  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 = nullptr,
!                                 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 TypeAryPtr* cast_to_exactness(bool klass_is_exact) const;
--- 1502,30 ---
    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->_flat; }
+   bool is_not_flat()      const { return _ary->_not_flat; }
+   bool is_null_free()     const { return is_flat() || (_ary->_elem->make_ptr() != nullptr && _ary->_elem->make_ptr()->is_inlinetypeptr() && (_ary->_elem->make_ptr()->ptr() == NotNull || _ary->_elem->make_ptr()->ptr() == AnyNull)); }
+   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 = nullptr,
                                  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 = nullptr,
!                                 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 TypeAryPtr* cast_to_exactness(bool klass_is_exact) const;

*** 1466,25 ***
    virtual const TypeAryPtr *with_offset( intptr_t offset ) const;
    const TypeAryPtr* with_ary(const TypeAry* ary) const;
  
    // Speculative type helper methods.
    virtual const TypeAryPtr* 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;
    static const TypeAryPtr *NARROWOOPS;
    static const TypeAryPtr *BYTES;
--- 1540,43 ---
    virtual const TypeAryPtr *with_offset( intptr_t offset ) const;
    const TypeAryPtr* with_ary(const TypeAry* ary) const;
  
    // Speculative type helper methods.
    virtual const TypeAryPtr* 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;
+   jint flat_layout_helper() const;
+   int flat_elem_size() const;
+   int flat_log_elem_size() 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);
+ 
+   int flat_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;
  
+   virtual bool can_be_inline_array() const;
+ 
    // Convenience common pre-built types.
    static const TypeAryPtr *RANGE;
    static const TypeAryPtr *OOPS;
    static const TypeAryPtr *NARROWOOPS;
    static const TypeAryPtr *BYTES;

*** 1492,10 ***
--- 1584,11 ---
    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] != nullptr, "bad elem type");
      return _array_body_type[elem];
    }

*** 1510,11 ***
  
  //------------------------------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 uint hash() const;             // Type specific hashing
--- 1603,11 ---
  
  //------------------------------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 uint hash() const;             // Type specific hashing

*** 1522,11 ***
  
  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; }
--- 1615,11 ---
  
  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; }

*** 1553,11 ***
  class TypeKlassPtr : public TypePtr {
    friend class TypeInstKlassPtr;
    friend class TypeAryKlassPtr;
    friend class TypePtr;
  protected:
!   TypeKlassPtr(TYPES t, PTR ptr, ciKlass* klass, const TypeInterfaces* interfaces, int offset);
  
    virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
  
  public:
    virtual bool eq( const Type *t ) const;
--- 1646,11 ---
  class TypeKlassPtr : public TypePtr {
    friend class TypeInstKlassPtr;
    friend class TypeAryKlassPtr;
    friend class TypePtr;
  protected:
!   TypeKlassPtr(TYPES t, PTR ptr, ciKlass* klass, const TypeInterfaces* interfaces, Offset offset);
  
    virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
  
  public:
    virtual bool eq( const Type *t ) const;

*** 1592,11 ***
    // Exact klass, possibly an interface or an array of interface
    ciKlass* exact_klass(bool maybe_null = false) const { assert(klass_is_exact(), ""); ciKlass* k = exact_klass_helper(); assert(k != nullptr || maybe_null, ""); return k;  }
    virtual bool klass_is_exact()    const { return _ptr == Constant; }
  
    static const TypeKlassPtr* make(ciKlass* klass, InterfaceHandling interface_handling = ignore_interfaces);
!   static const TypeKlassPtr *make(PTR ptr, ciKlass* klass, int offset, InterfaceHandling interface_handling = ignore_interfaces);
  
    virtual bool  is_loaded() const { return _klass->is_loaded(); }
  
    virtual const TypeKlassPtr* cast_to_ptr_type(PTR ptr) const { ShouldNotReachHere(); return nullptr; }
  
--- 1685,11 ---
    // Exact klass, possibly an interface or an array of interface
    ciKlass* exact_klass(bool maybe_null = false) const { assert(klass_is_exact(), ""); ciKlass* k = exact_klass_helper(); assert(k != nullptr || maybe_null, ""); return k;  }
    virtual bool klass_is_exact()    const { return _ptr == Constant; }
  
    static const TypeKlassPtr* make(ciKlass* klass, InterfaceHandling interface_handling = ignore_interfaces);
!   static const TypeKlassPtr *make(PTR ptr, ciKlass* klass, Offset offset, InterfaceHandling interface_handling = ignore_interfaces);
  
    virtual bool  is_loaded() const { return _klass->is_loaded(); }
  
    virtual const TypeKlassPtr* cast_to_ptr_type(PTR ptr) const { ShouldNotReachHere(); return nullptr; }
  

*** 1611,10 ***
--- 1704,11 ---
  
    virtual intptr_t get_con() const;
  
    virtual const TypeKlassPtr* with_offset(intptr_t offset) const { ShouldNotReachHere(); return nullptr; }
  
+   virtual bool can_be_inline_array() const { ShouldNotReachHere(); return false; }
    virtual const TypeKlassPtr* try_improve() const { return this; }
  
  #ifndef PRODUCT
    virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
  #endif

*** 1645,17 ***
  };
  
  // Instance klass pointer, mirrors TypeInstPtr
  class TypeInstKlassPtr : public TypeKlassPtr {
  
!   TypeInstKlassPtr(PTR ptr, ciKlass* klass, const TypeInterfaces* interfaces, int offset)
!     : TypeKlassPtr(InstKlassPtr, ptr, klass, interfaces, offset) {
      assert(klass->is_instance_klass() && (!klass->is_loaded() || !klass->is_interface()), "");
    }
  
    virtual bool must_be_exact() const;
  
  public:
    // Instance klass ignoring any interface
    ciInstanceKlass* instance_klass() const {
      assert(!klass()->is_interface(), "");
      return klass()->as_instance_klass();
--- 1739,19 ---
  };
  
  // Instance klass pointer, mirrors TypeInstPtr
  class TypeInstKlassPtr : public TypeKlassPtr {
  
!   TypeInstKlassPtr(PTR ptr, ciKlass* klass, const TypeInterfaces* interfaces, Offset offset, bool flat_in_array)
!     : TypeKlassPtr(InstKlassPtr, ptr, klass, interfaces, offset), _flat_in_array(flat_in_array) {
      assert(klass->is_instance_klass() && (!klass->is_loaded() || !klass->is_interface()), "");
    }
  
    virtual bool must_be_exact() const;
  
+   const bool _flat_in_array; // Type is flat in arrays
+ 
  public:
    // Instance klass ignoring any interface
    ciInstanceKlass* instance_klass() const {
      assert(!klass()->is_interface(), "");
      return klass()->as_instance_klass();

*** 1663,17 ***
  
    bool is_same_java_type_as_helper(const TypeKlassPtr* other) const;
    bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
    bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
  
    static const TypeInstKlassPtr *make(ciKlass* k, InterfaceHandling interface_handling) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(k, true, true, false, interface_handling);
!     return make(TypePtr::Constant, k, interfaces, 0);
    }
!   static const TypeInstKlassPtr* make(PTR ptr, ciKlass* k, const TypeInterfaces* interfaces, int offset);
  
!   static const TypeInstKlassPtr* make(PTR ptr, ciKlass* k, int offset) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(k, true, false, false, ignore_interfaces);
      return make(ptr, k, interfaces, offset);
    }
  
    virtual const TypeInstKlassPtr* cast_to_ptr_type(PTR ptr) const;
--- 1759,19 ---
  
    bool is_same_java_type_as_helper(const TypeKlassPtr* other) const;
    bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
    bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
  
+   virtual bool can_be_inline_type() const { return (_klass == nullptr || _klass->can_be_inline_klass(klass_is_exact())); }
+ 
    static const TypeInstKlassPtr *make(ciKlass* k, InterfaceHandling interface_handling) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(k, true, true, false, interface_handling);
!     return make(TypePtr::Constant, k, interfaces, Offset(0));
    }
!   static const TypeInstKlassPtr* make(PTR ptr, ciKlass* k, const TypeInterfaces* interfaces, Offset offset, bool flat_in_array = false);
  
!   static const TypeInstKlassPtr* make(PTR ptr, ciKlass* k, Offset offset) {
      const TypeInterfaces* interfaces = TypePtr::interfaces(k, true, false, false, ignore_interfaces);
      return make(ptr, k, interfaces, offset);
    }
  
    virtual const TypeInstKlassPtr* cast_to_ptr_type(PTR ptr) const;

*** 1690,10 ***
--- 1788,15 ---
    virtual const Type    *xdual() const;
    virtual const TypeInstKlassPtr* with_offset(intptr_t offset) const;
  
    virtual const TypeKlassPtr* try_improve() const;
  
+   virtual bool flat_in_array() const { return _flat_in_array; }
+   virtual bool not_flat_in_array() const { return !_klass->can_be_inline_klass() || (_klass->is_inlinetype() && !flat_in_array()); }
+ 
+   virtual bool can_be_inline_array() 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
  private:
    virtual bool is_meet_subtype_of_helper(const TypeKlassPtr* other, bool this_xk, bool other_xk) const;

*** 1704,37 ***
    friend class TypeInstKlassPtr;
    friend class Type;
    friend class TypePtr;
  
    const Type *_elem;
  
    static const TypeInterfaces* _array_interfaces;
!   TypeAryKlassPtr(PTR ptr, const Type *elem, ciKlass* klass, int offset)
!     : TypeKlassPtr(AryKlassPtr, ptr, klass, _array_interfaces, offset), _elem(elem) {
!     assert(klass == nullptr || klass->is_type_array_klass() || !klass->as_obj_array_klass()->base_element_klass()->is_interface(), "");
    }
  
    virtual ciKlass* exact_klass_helper() const;
    // Only guaranteed non null for array of basic types
    virtual ciKlass* klass() const;
  
    virtual bool must_be_exact() const;
  
  public:
  
    // 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, InterfaceHandling interface_handling);
  
    bool is_same_java_type_as_helper(const TypeKlassPtr* other) const;
    bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
    bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
  
    bool  is_loaded() const { return (_elem->isa_klassptr() ? _elem->is_klassptr()->is_loaded() : true); }
  
!   static const TypeAryKlassPtr *make(PTR ptr, const Type *elem, ciKlass* k, int offset);
    static const TypeAryKlassPtr* make(ciKlass* klass, InterfaceHandling interface_handling);
  
    const Type *elem() const { return _elem; }
  
    virtual bool eq(const Type *t) const;
--- 1807,49 ---
    friend class TypeInstKlassPtr;
    friend class Type;
    friend class TypePtr;
  
    const Type *_elem;
+   const bool _not_flat;      // Array is never flat
+   const bool _not_null_free; // Array is never null-free
+   const bool _null_free;
  
    static const TypeInterfaces* _array_interfaces;
!   TypeAryKlassPtr(PTR ptr, const Type *elem, ciKlass* klass, Offset offset, bool not_flat, int not_null_free, bool null_free)
!     : TypeKlassPtr(AryKlassPtr, ptr, klass, _array_interfaces, offset), _elem(elem), _not_flat(not_flat), _not_null_free(not_null_free), _null_free(null_free) {
!     assert(klass == nullptr || klass->is_type_array_klass() || klass->is_flat_array_klass() || !klass->as_obj_array_klass()->base_element_klass()->is_interface(), "");
    }
  
    virtual ciKlass* exact_klass_helper() const;
    // Only guaranteed non null for array of basic types
    virtual ciKlass* klass() const;
  
    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:
  
    // 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, InterfaceHandling interface_handling, bool not_flat, bool not_null_free, bool null_free);
  
    bool is_same_java_type_as_helper(const TypeKlassPtr* other) const;
    bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
    bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
  
    bool  is_loaded() const { return (_elem->isa_klassptr() ? _elem->is_klassptr()->is_loaded() : true); }
  
!   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(PTR ptr, ciKlass* k, Offset offset, InterfaceHandling interface_handling);
    static const TypeAryKlassPtr* make(ciKlass* klass, InterfaceHandling interface_handling);
  
    const Type *elem() const { return _elem; }
  
    virtual bool eq(const Type *t) const;

*** 1742,10 ***
--- 1857,12 ---
  
    virtual const TypeAryKlassPtr* cast_to_ptr_type(PTR ptr) const;
  
    virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const;
  
+   const TypeAryKlassPtr* cast_to_null_free() const;
+ 
    // corresponding pointer to instance, for a given class
    virtual const TypeOopPtr* as_instance_type(bool klass_change = true) const;
  
    virtual const TypePtr *add_offset( intptr_t offset ) const;
    virtual const Type    *xmeet( const Type *t ) const;

*** 1755,10 ***
--- 1872,16 ---
  
    virtual bool empty(void) const {
      return TypeKlassPtr::empty() || _elem->empty();
    }
  
+   bool is_flat()          const { return klass() != nullptr && 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; }
+   virtual bool can_be_inline_array() const;
+ 
  #ifndef PRODUCT
    virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
  #endif
  private:
    virtual bool is_meet_subtype_of_helper(const TypeKlassPtr* other, bool this_xk, bool other_xk) const;

*** 1890,18 ***
  };
  
  //------------------------------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 uint 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,
--- 2013,30 ---
  };
  
  //------------------------------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 uint 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,

*** 1911,22 ***
           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.
  };
--- 2046,27 ---
           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.
  };

*** 2178,10 ***
--- 2318,18 ---
        (_base == DoubleCon) || (_base == DoubleBot) )
      return true;
    return false;
  }
  
+ inline bool Type::is_inlinetypeptr() const {
+   return isa_instptr() != nullptr && is_instptr()->instance_klass()->is_inlinetype();
+ }
+ 
+ inline ciInlineKlass* Type::inline_klass() const {
+   return make_ptr()->is_instptr()->instance_klass()->as_inline_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.

*** 2204,10 ***
--- 2352,11 ---
  // 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

*** 2222,10 ***
--- 2371,11 ---
  #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)

*** 2250,10 ***
--- 2400,11 ---
  // 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

*** 2268,10 ***
--- 2419,11 ---
  #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 >