hotspot/src/share/vm/oops/methodData.hpp
changeset 21095 1a04f7b3946e
parent 20709 034be898bf04
child 21581 73584c201e2d
child 22838 82c7497fbad4
--- a/hotspot/src/share/vm/oops/methodData.hpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -119,7 +119,8 @@
     multi_branch_data_tag,
     arg_info_data_tag,
     call_type_data_tag,
-    virtual_call_type_data_tag
+    virtual_call_type_data_tag,
+    parameters_type_data_tag
   };
 
   enum {
@@ -264,6 +265,7 @@
 class   ArrayData;
 class     MultiBranchData;
 class     ArgInfoData;
+class     ParametersTypeData;
 
 // ProfileData
 //
@@ -397,6 +399,7 @@
   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; }
 
 
   BitData* as_BitData() const {
@@ -447,6 +450,10 @@
     assert(is_VirtualCallTypeData(), "wrong type");
     return is_VirtualCallTypeData() ? (VirtualCallTypeData*)this : NULL;
   }
+  ParametersTypeData* as_ParametersTypeData() const {
+    assert(is_ParametersTypeData(), "wrong type");
+    return is_ParametersTypeData() ? (ParametersTypeData*)this : NULL;
+  }
 
 
   // Subclass specific initialization
@@ -767,9 +774,9 @@
   TypeStackSlotEntries(int base_off, int nb_entries)
     : TypeEntries(base_off), _number_of_entries(nb_entries) {}
 
-  static int compute_cell_count(Symbol* signature, int max);
+  static int compute_cell_count(Symbol* signature, bool include_receiver, int max);
 
-  void post_initialize(Symbol* signature, bool has_receiver);
+  void post_initialize(Symbol* signature, bool has_receiver, bool include_receiver);
 
   // offset of cell for stack slot for entry i within this block of cells for a TypeStackSlotEntries
   static int stack_slot_local_offset(int i) {
@@ -946,17 +953,6 @@
     assert(number_of_arguments() == total, "should be set in DataLayout::initialize");
   }
 
-protected:
-  // An entry for a return value takes less space than an entry for an
-  // argument so if the number of cells exceeds the number of cells
-  // needed for an argument, this object contains type information for
-  // at least one argument.
-  bool has_arguments() const {
-    bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
-    assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
-    return res;
-  }
-
 public:
   CallTypeData(DataLayout* layout) :
     CounterData(layout),
@@ -1018,6 +1014,16 @@
   }
 
   // An entry for a return value takes less space than an entry for an
+  // argument so if the number of cells exceeds the number of cells
+  // needed for an argument, this object contains type information for
+  // at least one argument.
+  bool has_arguments() const {
+    bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
+    assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
+    return res;
+  }
+
+  // An entry for a return value takes less space than an entry for an
   // argument, so if the remainder of the number of cells divided by
   // the number of cells for an argument is not null, a return value
   // is profiled in this object.
@@ -1213,17 +1219,6 @@
     assert(number_of_arguments() == total, "should be set in DataLayout::initialize");
   }
 
-protected:
-  // An entry for a return value takes less space than an entry for an
-  // argument so if the number of cells exceeds the number of cells
-  // needed for an argument, this object contains type information for
-  // at least one argument.
-  bool has_arguments() const {
-    bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
-    assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
-    return res;
-  }
-
 public:
   VirtualCallTypeData(DataLayout* layout) :
     VirtualCallData(layout),
@@ -1294,6 +1289,16 @@
     return res;
   }
 
+  // An entry for a return value takes less space than an entry for an
+  // argument so if the number of cells exceeds the number of cells
+  // needed for an argument, this object contains type information for
+  // at least one argument.
+  bool has_arguments() const {
+    bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
+    assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
+    return res;
+  }
+
   // Code generation support
   static ByteSize args_data_offset() {
     return cell_offset(VirtualCallData::static_cell_count()) + TypeEntriesAtCall::args_data_offset();
@@ -1662,6 +1667,75 @@
 #endif
 };
 
+// ParametersTypeData
+//
+// A ParametersTypeData is used to access profiling information about
+// types of parameters to a method
+class ParametersTypeData : public ArrayData {
+
+private:
+  TypeStackSlotEntries _parameters;
+
+  static int stack_slot_local_offset(int i) {
+    assert_profiling_enabled();
+    return array_start_off_set + TypeStackSlotEntries::stack_slot_local_offset(i);
+  }
+
+  static int type_local_offset(int i) {
+    assert_profiling_enabled();
+    return array_start_off_set + TypeStackSlotEntries::type_local_offset(i);
+  }
+
+  static bool profiling_enabled();
+  static void assert_profiling_enabled() {
+    assert(profiling_enabled(), "method parameters profiling should be on");
+  }
+
+public:
+  ParametersTypeData(DataLayout* layout) : ArrayData(layout), _parameters(1, number_of_parameters()) {
+    assert(layout->tag() == DataLayout::parameters_type_data_tag, "wrong type");
+    // Some compilers (VC++) don't want this passed in member initialization list
+    _parameters.set_profile_data(this);
+  }
+
+  static int compute_cell_count(Method* m);
+
+  virtual bool is_ParametersTypeData() const { return true; }
+
+  virtual void post_initialize(BytecodeStream* stream, MethodData* mdo);
+
+  int number_of_parameters() const {
+    return array_len() / TypeStackSlotEntries::per_arg_count();
+  }
+
+  const TypeStackSlotEntries* parameters() const { return &_parameters; }
+
+  uint stack_slot(int i) const {
+    return _parameters.stack_slot(i);
+  }
+
+  void set_type(int i, Klass* k) {
+    intptr_t current = _parameters.type(i);
+    _parameters.set_type(i, TypeEntries::with_status((intptr_t)k, current));
+  }
+
+  virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
+    _parameters.clean_weak_klass_links(is_alive_closure);
+  }
+
+#ifndef PRODUCT
+  virtual void print_data_on(outputStream* st) const;
+#endif
+
+  static ByteSize stack_slot_offset(int i) {
+    return cell_offset(stack_slot_local_offset(i));
+  }
+
+  static ByteSize type_offset(int i) {
+    return cell_offset(type_local_offset(i));
+  }
+};
+
 // MethodData*
 //
 // A MethodData* holds information which has been collected about
@@ -1773,6 +1847,10 @@
   // Size of _data array in bytes.  (Excludes header and extra_data fields.)
   int _data_size;
 
+  // data index for the area dedicated to parameters. -1 if no
+  // parameter profiling.
+  int _parameters_type_data_di;
+
   // Beginning of the data entries
   intptr_t _data[1];
 
@@ -1842,6 +1920,9 @@
   static int profile_return_flag();
   static bool profile_all_return();
   static bool profile_return_for_invoke(methodHandle m, int bci);
+  static int profile_parameters_flag();
+  static bool profile_parameters_jsr292_only();
+  static bool profile_all_parameters();
 
 public:
   static int header_size() {
@@ -2048,6 +2129,16 @@
     }
   }
 
+  // Return pointer to area dedicated to parameters in MDO
+  ParametersTypeData* parameters_type_data() const {
+    return _parameters_type_data_di != -1 ? data_layout_at(_parameters_type_data_di)->data_in()->as_ParametersTypeData() : NULL;
+  }
+
+  int parameters_type_data_di() const {
+    assert(_parameters_type_data_di != -1, "no args type data");
+    return _parameters_type_data_di;
+  }
+
   // Support for code generation
   static ByteSize data_offset() {
     return byte_offset_of(MethodData, _data[0]);
@@ -2060,6 +2151,10 @@
     return byte_offset_of(MethodData, _backedge_counter);
   }
 
+  static ByteSize parameters_type_data_di_offset() {
+    return byte_offset_of(MethodData, _parameters_type_data_di);
+  }
+
   // Deallocation support - no pointer fields to deallocate
   void deallocate_contents(ClassLoaderData* loader_data) {}
 
@@ -2083,8 +2178,10 @@
   void verify_on(outputStream* st);
   void verify_data_on(outputStream* st);
 
+  static bool profile_parameters_for_method(methodHandle m);
   static bool profile_arguments();
   static bool profile_return();
+  static bool profile_parameters();
   static bool profile_return_jsr292_only();
 };