< prev index next >

src/hotspot/share/oops/methodData.hpp

Print this page
@@ -127,11 +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
+     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.

@@ -284,27 +287,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 ReturnTypeEntry;
+   friend class SingleTypeEntry;
    friend class TypeStackSlotEntries;
  private:
    enum {
      tab_width_one = 16,
      tab_width_two = 36

@@ -421,10 +427,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;

@@ -479,10 +488,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) {}
  

@@ -521,10 +542,11 @@
        deprecated_method_callsite_flag = exception_handler_entered_flag + 1
  #if INCLUDE_JVMCI
      // bytecode threw any exception
      , exception_seen_flag             = deprecated_method_callsite_flag + 1
  #endif
+     , last_bit_data_flag
    };
    enum { bit_cell_count = 0 };  // no additional data fields needed.
  public:
    BitData(DataLayout* layout) : ProfileData(layout) {
    }

@@ -541,11 +563,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); }
+   bool null_seen() const  { return flag_at(null_seen_flag); }
    void set_null_seen()    { set_flag_at(null_seen_flag); }
    bool deprecated_method_call_site() const { return flag_at(deprecated_method_callsite_flag); }
    bool set_deprecated_method_call_site() { return data()->set_flag_at(deprecated_method_callsite_flag); }
    bool clear_deprecated_method_call_site() { return data()->clear_flag_at(deprecated_method_callsite_flag); }
  

@@ -642,11 +664,12 @@
    }
  
  public:
    JumpData(DataLayout* layout) : ProfileData(layout) {
      assert(layout->tag() == DataLayout::jump_data_tag ||
-       layout->tag() == DataLayout::branch_data_tag, "wrong type");
+       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() {

@@ -878,19 +901,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 {
+ class SingleTypeEntry : public TypeEntries {
  
  private:
    enum {
      cell_count = 1
    };
  
  public:
-   ReturnTypeEntry(int base_off)
+   SingleTypeEntry(int base_off)
      : TypeEntries(base_off) {}
  
    void post_initialize() {
      set_type(type_none());
    }

@@ -920,11 +943,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
+ // (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().

@@ -974,11 +997,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);
+     return SingleTypeEntry::size() + in_ByteSize(header_cell_count() * DataLayout::cell_size);
    }
  
  };
  
  // CallTypeData

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

@@ -1008,11 +1031,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())
+     _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);

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

@@ -1133,11 +1156,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, "wrong type");
+            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() {

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

@@ -1282,11 +1306,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())
+     _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);

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

@@ -1497,11 +1521,11 @@
      set_int_at(displacement_off_set, displacement);
    }
  
  public:
    BranchData(DataLayout* layout) : JumpData(layout) {
-     assert(layout->tag() == DataLayout::branch_data_tag, "wrong type");
+     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() {

@@ -1854,10 +1878,218 @@
    }
  
    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*
  //
  // A MethodData* holds information which has been collected about
  // a method.  Its layout looks like this:
  //
< prev index next >