< prev index next >

src/hotspot/share/oops/methodData.hpp

Print this page
*** 127,11 ***
      multi_branch_data_tag,
      arg_info_data_tag,
      call_type_data_tag,
      virtual_call_type_data_tag,
      parameters_type_data_tag,
!     speculative_trap_data_tag
    };
  
    enum {
      // The trap state breaks down as [recompile:1 | reason:31].
      // This further breakdown is defined in deoptimization.cpp.
--- 127,14 ---
      multi_branch_data_tag,
      arg_info_data_tag,
      call_type_data_tag,
      virtual_call_type_data_tag,
      parameters_type_data_tag,
!     speculative_trap_data_tag,
+     array_store_data_tag,
+     array_load_data_tag,
+     acmp_data_tag
    };
  
    enum {
      // The trap state breaks down as [recompile:1 | reason:31].
      // This further breakdown is defined in deoptimization.cpp.

*** 259,27 ***
  class   BitData;
  class     CounterData;
  class       ReceiverTypeData;
  class         VirtualCallData;
  class           VirtualCallTypeData;
  class       RetData;
  class       CallTypeData;
  class   JumpData;
  class     BranchData;
  class   ArrayData;
  class     MultiBranchData;
  class     ArgInfoData;
  class     ParametersTypeData;
  class   SpeculativeTrapData;
  
  // ProfileData
  //
  // A ProfileData object is created to refer to a section of profiling
  // data in a structured way.
  class ProfileData : public ResourceObj {
    friend class TypeEntries;
!   friend class ReturnTypeEntry;
    friend class TypeStackSlotEntries;
  private:
    enum {
      tab_width_one = 16,
      tab_width_two = 36
--- 262,30 ---
  class   BitData;
  class     CounterData;
  class       ReceiverTypeData;
  class         VirtualCallData;
  class           VirtualCallTypeData;
+ class         ArrayStoreData;
  class       RetData;
  class       CallTypeData;
  class   JumpData;
  class     BranchData;
+ class       ACmpData;
  class   ArrayData;
  class     MultiBranchData;
  class     ArgInfoData;
  class     ParametersTypeData;
  class   SpeculativeTrapData;
+ class   ArrayLoadData;
  
  // ProfileData
  //
  // A ProfileData object is created to refer to a section of profiling
  // data in a structured way.
  class ProfileData : public ResourceObj {
    friend class TypeEntries;
!   friend class SingleTypeEntry;
    friend class TypeStackSlotEntries;
  private:
    enum {
      tab_width_one = 16,
      tab_width_two = 36

*** 396,10 ***
--- 402,13 ---
    virtual bool is_ArgInfoData()     const { return false; }
    virtual bool is_CallTypeData()    const { return false; }
    virtual bool is_VirtualCallTypeData()const { return false; }
    virtual bool is_ParametersTypeData() const { return false; }
    virtual bool is_SpeculativeTrapData()const { return false; }
+   virtual bool is_ArrayStoreData() const { return false; }
+   virtual bool is_ArrayLoadData() const { return false; }
+   virtual bool is_ACmpData()           const { return false; }
  
  
    BitData* as_BitData() const {
      assert(is_BitData(), "wrong type");
      return is_BitData()         ? (BitData*)        this : nullptr;

*** 454,10 ***
--- 463,22 ---
    }
    SpeculativeTrapData* as_SpeculativeTrapData() const {
      assert(is_SpeculativeTrapData(), "wrong type");
      return is_SpeculativeTrapData() ? (SpeculativeTrapData*)this : nullptr;
    }
+   ArrayStoreData* as_ArrayStoreData() const {
+     assert(is_ArrayStoreData(), "wrong type");
+     return is_ArrayStoreData() ? (ArrayStoreData*)this : nullptr;
+   }
+   ArrayLoadData* as_ArrayLoadData() const {
+     assert(is_ArrayLoadData(), "wrong type");
+     return is_ArrayLoadData() ? (ArrayLoadData*)this : nullptr;
+   }
+   ACmpData* as_ACmpData() const {
+     assert(is_ACmpData(), "wrong type");
+     return is_ACmpData() ? (ACmpData*)this : nullptr;
+   }
  
  
    // Subclass specific initialization
    virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {}
  

*** 489,15 ***
    friend class JVMCIVMStructs;
  protected:
    enum : u1 {
      // null_seen:
      //  saw a null operand (cast/aastore/instanceof)
!       null_seen_flag              = DataLayout::first_flag + 0
  #if INCLUDE_JVMCI
      // bytecode threw any exception
!     , exception_seen_flag         = null_seen_flag + 1
  #endif
    };
    enum { bit_cell_count = 0 };  // no additional data fields needed.
  public:
    BitData(DataLayout* layout) : ProfileData(layout) {
    }
--- 510,16 ---
    friend class JVMCIVMStructs;
  protected:
    enum : u1 {
      // null_seen:
      //  saw a null operand (cast/aastore/instanceof)
!       null_seen_flag              = DataLayout::first_flag + 0,
  #if INCLUDE_JVMCI
      // bytecode threw any exception
!       exception_seen_flag         = null_seen_flag + 1,
  #endif
+       last_bit_data_flag
    };
    enum { bit_cell_count = 0 };  // no additional data fields needed.
  public:
    BitData(DataLayout* layout) : ProfileData(layout) {
    }

*** 514,11 ***
  
    // Accessor
  
    // The null_seen flag bit is specially known to the interpreter.
    // Consulting it allows the compiler to avoid setting up null_check traps.
!   bool null_seen()     { return flag_at(null_seen_flag); }
    void set_null_seen()    { set_flag_at(null_seen_flag); }
  
  #if INCLUDE_JVMCI
    // true if an exception was thrown at the specific BCI
    bool exception_seen() { return flag_at(exception_seen_flag); }
--- 536,11 ---
  
    // Accessor
  
    // The null_seen flag bit is specially known to the interpreter.
    // Consulting it allows the compiler to avoid setting up null_check traps.
!   bool null_seen() const  { return flag_at(null_seen_flag); }
    void set_null_seen()    { set_flag_at(null_seen_flag); }
  
  #if INCLUDE_JVMCI
    // true if an exception was thrown at the specific BCI
    bool exception_seen() { return flag_at(exception_seen_flag); }

*** 608,11 ***
    }
  
  public:
    JumpData(DataLayout* layout) : ProfileData(layout) {
      assert(layout->tag() == DataLayout::jump_data_tag ||
!       layout->tag() == DataLayout::branch_data_tag, "wrong type");
    }
  
    virtual bool is_JumpData() const { return true; }
  
    static int static_cell_count() {
--- 630,12 ---
    }
  
  public:
    JumpData(DataLayout* layout) : ProfileData(layout) {
      assert(layout->tag() == DataLayout::jump_data_tag ||
!       layout->tag() == DataLayout::branch_data_tag ||
+       layout->tag() == DataLayout::acmp_data_tag, "wrong type");
    }
  
    virtual bool is_JumpData() const { return true; }
  
    static int static_cell_count() {

*** 844,19 ***
    void print_data_on(outputStream* st) const;
  };
  
  // Type entry used for return from a call. A single cell to record the
  // type.
! class ReturnTypeEntry : public TypeEntries {
  
  private:
    enum {
      cell_count = 1
    };
  
  public:
!   ReturnTypeEntry(int base_off)
      : TypeEntries(base_off) {}
  
    void post_initialize() {
      set_type(type_none());
    }
--- 867,19 ---
    void print_data_on(outputStream* st) const;
  };
  
  // Type entry used for return from a call. A single cell to record the
  // type.
! class SingleTypeEntry : public TypeEntries {
  
  private:
    enum {
      cell_count = 1
    };
  
  public:
!   SingleTypeEntry(int base_off)
      : TypeEntries(base_off) {}
  
    void post_initialize() {
      set_type(type_none());
    }

*** 886,11 ***
  
    void print_data_on(outputStream* st) const;
  };
  
  // Entries to collect type information at a call: contains arguments
! // (TypeStackSlotEntries), a return type (ReturnTypeEntry) and a
  // number of cells. Because the number of cells for the return type is
  // smaller than the number of cells for the type of an arguments, the
  // number of cells is used to tell how many arguments are profiled and
  // whether a return value is profiled. See has_arguments() and
  // has_return().
--- 909,11 ---
  
    void print_data_on(outputStream* st) const;
  };
  
  // Entries to collect type information at a call: contains arguments
! // (TypeStackSlotEntries), a return type (SingleTypeEntry) and a
  // number of cells. Because the number of cells for the return type is
  // smaller than the number of cells for the type of an arguments, the
  // number of cells is used to tell how many arguments are profiled and
  // whether a return value is profiled. See has_arguments() and
  // has_return().

*** 940,11 ***
    static ByteSize argument_type_offset(int i) {
      return in_ByteSize(argument_type_local_offset(i) * DataLayout::cell_size);
    }
  
    static ByteSize return_only_size() {
!     return ReturnTypeEntry::size() + in_ByteSize(header_cell_count() * DataLayout::cell_size);
    }
  
  };
  
  // CallTypeData
--- 963,11 ---
    static ByteSize argument_type_offset(int i) {
      return in_ByteSize(argument_type_local_offset(i) * DataLayout::cell_size);
    }
  
    static ByteSize return_only_size() {
!     return SingleTypeEntry::size() + in_ByteSize(header_cell_count() * DataLayout::cell_size);
    }
  
  };
  
  // CallTypeData

*** 955,11 ***
  class CallTypeData : public CounterData {
  private:
    // entries for arguments if any
    TypeStackSlotEntries _args;
    // entry for return type if any
!   ReturnTypeEntry _ret;
  
    int cell_count_global_offset() const {
      return CounterData::static_cell_count() + TypeEntriesAtCall::cell_count_local_offset();
    }
  
--- 978,11 ---
  class CallTypeData : public CounterData {
  private:
    // entries for arguments if any
    TypeStackSlotEntries _args;
    // entry for return type if any
!   SingleTypeEntry _ret;
  
    int cell_count_global_offset() const {
      return CounterData::static_cell_count() + TypeEntriesAtCall::cell_count_local_offset();
    }
  

*** 974,11 ***
  
  public:
    CallTypeData(DataLayout* layout) :
      CounterData(layout),
      _args(CounterData::static_cell_count()+TypeEntriesAtCall::header_cell_count(), number_of_arguments()),
!     _ret(cell_count() - ReturnTypeEntry::static_cell_count())
    {
      assert(layout->tag() == DataLayout::call_type_data_tag, "wrong type");
      // Some compilers (VC++) don't want this passed in member initialization list
      _args.set_profile_data(this);
      _ret.set_profile_data(this);
--- 997,11 ---
  
  public:
    CallTypeData(DataLayout* layout) :
      CounterData(layout),
      _args(CounterData::static_cell_count()+TypeEntriesAtCall::header_cell_count(), number_of_arguments()),
!     _ret(cell_count() - SingleTypeEntry::static_cell_count())
    {
      assert(layout->tag() == DataLayout::call_type_data_tag, "wrong type");
      // Some compilers (VC++) don't want this passed in member initialization list
      _args.set_profile_data(this);
      _ret.set_profile_data(this);

*** 987,11 ***
    const TypeStackSlotEntries* args() const {
      assert(has_arguments(), "no profiling of arguments");
      return &_args;
    }
  
!   const ReturnTypeEntry* ret() const {
      assert(has_return(), "no profiling of return value");
      return &_ret;
    }
  
    virtual bool is_CallTypeData() const { return true; }
--- 1010,11 ---
    const TypeStackSlotEntries* args() const {
      assert(has_arguments(), "no profiling of arguments");
      return &_args;
    }
  
!   const SingleTypeEntry* ret() const {
      assert(has_return(), "no profiling of return value");
      return &_ret;
    }
  
    virtual bool is_CallTypeData() const { return true; }

*** 1099,11 ***
  
  public:
    ReceiverTypeData(DataLayout* layout) : CounterData(layout) {
      assert(layout->tag() == DataLayout::receiver_type_data_tag ||
             layout->tag() == DataLayout::virtual_call_data_tag ||
!            layout->tag() == DataLayout::virtual_call_type_data_tag, "wrong type");
    }
  
    virtual bool is_ReceiverTypeData() const { return true; }
  
    static int static_cell_count() {
--- 1122,12 ---
  
  public:
    ReceiverTypeData(DataLayout* layout) : CounterData(layout) {
      assert(layout->tag() == DataLayout::receiver_type_data_tag ||
             layout->tag() == DataLayout::virtual_call_data_tag ||
!            layout->tag() == DataLayout::virtual_call_type_data_tag ||
+            layout->tag() == DataLayout::array_store_data_tag, "wrong type");
    }
  
    virtual bool is_ReceiverTypeData() const { return true; }
  
    static int static_cell_count() {

*** 1229,11 ***
  class VirtualCallTypeData : public VirtualCallData {
  private:
    // entries for arguments if any
    TypeStackSlotEntries _args;
    // entry for return type if any
!   ReturnTypeEntry _ret;
  
    int cell_count_global_offset() const {
      return VirtualCallData::static_cell_count() + TypeEntriesAtCall::cell_count_local_offset();
    }
  
--- 1253,11 ---
  class VirtualCallTypeData : public VirtualCallData {
  private:
    // entries for arguments if any
    TypeStackSlotEntries _args;
    // entry for return type if any
!   SingleTypeEntry _ret;
  
    int cell_count_global_offset() const {
      return VirtualCallData::static_cell_count() + TypeEntriesAtCall::cell_count_local_offset();
    }
  

*** 1248,11 ***
  
  public:
    VirtualCallTypeData(DataLayout* layout) :
      VirtualCallData(layout),
      _args(VirtualCallData::static_cell_count()+TypeEntriesAtCall::header_cell_count(), number_of_arguments()),
!     _ret(cell_count() - ReturnTypeEntry::static_cell_count())
    {
      assert(layout->tag() == DataLayout::virtual_call_type_data_tag, "wrong type");
      // Some compilers (VC++) don't want this passed in member initialization list
      _args.set_profile_data(this);
      _ret.set_profile_data(this);
--- 1272,11 ---
  
  public:
    VirtualCallTypeData(DataLayout* layout) :
      VirtualCallData(layout),
      _args(VirtualCallData::static_cell_count()+TypeEntriesAtCall::header_cell_count(), number_of_arguments()),
!     _ret(cell_count() - SingleTypeEntry::static_cell_count())
    {
      assert(layout->tag() == DataLayout::virtual_call_type_data_tag, "wrong type");
      // Some compilers (VC++) don't want this passed in member initialization list
      _args.set_profile_data(this);
      _ret.set_profile_data(this);

*** 1261,11 ***
    const TypeStackSlotEntries* args() const {
      assert(has_arguments(), "no profiling of arguments");
      return &_args;
    }
  
!   const ReturnTypeEntry* ret() const {
      assert(has_return(), "no profiling of return value");
      return &_ret;
    }
  
    virtual bool is_VirtualCallTypeData() const { return true; }
--- 1285,11 ---
    const TypeStackSlotEntries* args() const {
      assert(has_arguments(), "no profiling of arguments");
      return &_args;
    }
  
!   const SingleTypeEntry* ret() const {
      assert(has_return(), "no profiling of return value");
      return &_ret;
    }
  
    virtual bool is_VirtualCallTypeData() const { return true; }

*** 1463,11 ***
      set_int_at(displacement_off_set, displacement);
    }
  
  public:
    BranchData(DataLayout* layout) : JumpData(layout) {
!     assert(layout->tag() == DataLayout::branch_data_tag, "wrong type");
    }
  
    virtual bool is_BranchData() const { return true; }
  
    static int static_cell_count() {
--- 1487,11 ---
      set_int_at(displacement_off_set, displacement);
    }
  
  public:
    BranchData(DataLayout* layout) : JumpData(layout) {
!     assert(layout->tag() == DataLayout::branch_data_tag || layout->tag() == DataLayout::acmp_data_tag, "wrong type");
    }
  
    virtual bool is_BranchData() const { return true; }
  
    static int static_cell_count() {

*** 1817,10 ***
--- 1841,218 ---
  
    static ByteSize method_offset() {
      return cell_offset(speculative_trap_method);
    }
  
+   virtual void print_data_on(outputStream* st, const char* extra = nullptr) const;
+ };
+ 
+ class ArrayStoreData : public ReceiverTypeData {
+ private:
+   enum {
+     flat_array_flag = BitData::last_bit_data_flag,
+     null_free_array_flag = flat_array_flag + 1,
+   };
+ 
+   SingleTypeEntry _array;
+ 
+ public:
+   ArrayStoreData(DataLayout* layout) :
+     ReceiverTypeData(layout),
+     _array(ReceiverTypeData::static_cell_count()) {
+     assert(layout->tag() == DataLayout::array_store_data_tag, "wrong type");
+     _array.set_profile_data(this);
+   }
+ 
+   const SingleTypeEntry* array() const {
+     return &_array;
+   }
+ 
+   virtual bool is_ArrayStoreData() const { return true; }
+ 
+   static int static_cell_count() {
+     return ReceiverTypeData::static_cell_count() + SingleTypeEntry::static_cell_count();
+   }
+ 
+   virtual int cell_count() const {
+     return static_cell_count();
+   }
+ 
+   void set_flat_array() { set_flag_at(flat_array_flag); }
+   bool flat_array() const { return flag_at(flat_array_flag); }
+ 
+   void set_null_free_array() { set_flag_at(null_free_array_flag); }
+   bool null_free_array() const { return flag_at(null_free_array_flag); }
+ 
+   // Code generation support
+   static int flat_array_byte_constant() {
+     return flag_number_to_constant(flat_array_flag);
+   }
+ 
+   static int null_free_array_byte_constant() {
+     return flag_number_to_constant(null_free_array_flag);
+   }
+ 
+   static ByteSize array_offset() {
+     return cell_offset(ReceiverTypeData::static_cell_count());
+   }
+ 
+   virtual void clean_weak_klass_links(bool always_clean) {
+     ReceiverTypeData::clean_weak_klass_links(always_clean);
+     _array.clean_weak_klass_links(always_clean);
+   }
+ 
+   static ByteSize array_store_data_size() {
+     return cell_offset(static_cell_count());
+   }
+ 
+   virtual void print_data_on(outputStream* st, const char* extra = nullptr) const;
+ };
+ 
+ class ArrayLoadData : public ProfileData {
+ private:
+   enum {
+     flat_array_flag = DataLayout::first_flag,
+     null_free_array_flag = flat_array_flag + 1,
+   };
+ 
+   SingleTypeEntry _array;
+   SingleTypeEntry _element;
+ 
+ public:
+   ArrayLoadData(DataLayout* layout) :
+     ProfileData(layout),
+     _array(0),
+     _element(SingleTypeEntry::static_cell_count()) {
+     assert(layout->tag() == DataLayout::array_load_data_tag, "wrong type");
+     _array.set_profile_data(this);
+     _element.set_profile_data(this);
+   }
+ 
+   const SingleTypeEntry* array() const {
+     return &_array;
+   }
+ 
+   const SingleTypeEntry* element() const {
+     return &_element;
+   }
+ 
+   virtual bool is_ArrayLoadData() const { return true; }
+ 
+   static int static_cell_count() {
+     return SingleTypeEntry::static_cell_count() * 2;
+   }
+ 
+   virtual int cell_count() const {
+     return static_cell_count();
+   }
+ 
+   void set_flat_array() { set_flag_at(flat_array_flag); }
+   bool flat_array() const { return flag_at(flat_array_flag); }
+ 
+   void set_null_free_array() { set_flag_at(null_free_array_flag); }
+   bool null_free_array() const { return flag_at(null_free_array_flag); }
+ 
+   // Code generation support
+   static int flat_array_byte_constant() {
+     return flag_number_to_constant(flat_array_flag);
+   }
+ 
+   static int null_free_array_byte_constant() {
+     return flag_number_to_constant(null_free_array_flag);
+   }
+ 
+   static ByteSize array_offset() {
+     return cell_offset(0);
+   }
+ 
+   static ByteSize element_offset() {
+     return cell_offset(SingleTypeEntry::static_cell_count());
+   }
+ 
+   virtual void clean_weak_klass_links(bool always_clean) {
+     _array.clean_weak_klass_links(always_clean);
+     _element.clean_weak_klass_links(always_clean);
+   }
+ 
+   static ByteSize array_load_data_size() {
+     return cell_offset(static_cell_count());
+   }
+ 
+   virtual void print_data_on(outputStream* st, const char* extra = nullptr) const;
+ };
+ 
+ class ACmpData : public BranchData {
+ private:
+   enum {
+     left_inline_type_flag = DataLayout::first_flag,
+     right_inline_type_flag
+   };
+ 
+   SingleTypeEntry _left;
+   SingleTypeEntry _right;
+ 
+ public:
+   ACmpData(DataLayout* layout) :
+     BranchData(layout),
+     _left(BranchData::static_cell_count()),
+     _right(BranchData::static_cell_count() + SingleTypeEntry::static_cell_count()) {
+     assert(layout->tag() == DataLayout::acmp_data_tag, "wrong type");
+     _left.set_profile_data(this);
+     _right.set_profile_data(this);
+   }
+ 
+   const SingleTypeEntry* left() const {
+     return &_left;
+   }
+ 
+   const SingleTypeEntry* right() const {
+     return &_right;
+   }
+ 
+   virtual bool is_ACmpData() const { return true; }
+ 
+   static int static_cell_count() {
+     return BranchData::static_cell_count() + SingleTypeEntry::static_cell_count() * 2;
+   }
+ 
+   virtual int cell_count() const {
+     return static_cell_count();
+   }
+ 
+   void set_left_inline_type() { set_flag_at(left_inline_type_flag); }
+   bool left_inline_type() const { return flag_at(left_inline_type_flag); }
+ 
+   void set_right_inline_type() { set_flag_at(right_inline_type_flag); }
+   bool right_inline_type() const { return flag_at(right_inline_type_flag); }
+ 
+   // Code generation support
+   static int left_inline_type_byte_constant() {
+     return flag_number_to_constant(left_inline_type_flag);
+   }
+ 
+   static int right_inline_type_byte_constant() {
+     return flag_number_to_constant(right_inline_type_flag);
+   }
+ 
+   static ByteSize left_offset() {
+     return cell_offset(BranchData::static_cell_count());
+   }
+ 
+   static ByteSize right_offset() {
+     return cell_offset(BranchData::static_cell_count() + SingleTypeEntry::static_cell_count());
+   }
+ 
+   virtual void clean_weak_klass_links(bool always_clean) {
+     _left.clean_weak_klass_links(always_clean);
+     _right.clean_weak_klass_links(always_clean);
+   }
+ 
+   static ByteSize acmp_data_size() {
+     return cell_offset(static_cell_count());
+   }
+ 
    virtual void print_data_on(outputStream* st, const char* extra = nullptr) const;
  };
  
  // MethodData*
  //
< prev index next >