hotspot/src/share/vm/oops/methodData.cpp
changeset 21095 1a04f7b3946e
parent 20709 034be898bf04
child 21581 73584c201e2d
child 22838 82c7497fbad4
--- a/hotspot/src/share/vm/oops/methodData.cpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -41,7 +41,7 @@
 
 // Some types of data layouts need a length field.
 bool DataLayout::needs_array_len(u1 tag) {
-  return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag);
+  return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag) || (tag == parameters_type_data_tag);
 }
 
 // Perform generic initialization of the data.  More specific
@@ -156,10 +156,13 @@
 }
 #endif // !PRODUCT
 
-int TypeStackSlotEntries::compute_cell_count(Symbol* signature, int max) {
+int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_receiver, int max) {
+  // Parameter profiling include the receiver
+  int args_count = include_receiver ? 1 : 0;
   ResourceMark rm;
   SignatureStream ss(signature);
-  int args_count = MIN2(ss.reference_parameter_count(), max);
+  args_count += ss.reference_parameter_count();
+  args_count = MIN2(args_count, max);
   return args_count * per_arg_cell_count;
 }
 
@@ -169,7 +172,7 @@
   Bytecode_invoke inv(stream->method(), stream->bci());
   int args_cell = 0;
   if (arguments_profiling_enabled()) {
-    args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), TypeProfileArgsLimit);
+    args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), false, TypeProfileArgsLimit);
   }
   int ret_cell = 0;
   if (return_profiling_enabled() && (inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY)) {
@@ -212,12 +215,19 @@
   int off_at(int i) const { return _offsets.at(i); }
 };
 
-void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver) {
+void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver, bool include_receiver) {
   ResourceMark rm;
-  ArgumentOffsetComputer aos(signature, _number_of_entries);
+  int start = 0;
+  // Parameter profiling include the receiver
+  if (include_receiver && has_receiver) {
+    set_stack_slot(0, 0);
+    set_type(0, type_none());
+    start += 1;
+  }
+  ArgumentOffsetComputer aos(signature, _number_of_entries-start);
   aos.total();
-  for (int i = 0; i < _number_of_entries; i++) {
-    set_stack_slot(i, aos.off_at(i) + (has_receiver ? 1 : 0));
+  for (int i = start; i < _number_of_entries; i++) {
+    set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0));
     set_type(i, type_none());
   }
 }
@@ -234,7 +244,7 @@
     assert(count > 0, "room for args type but none found?");
     check_number_of_arguments(count);
 #endif
-    _args.post_initialize(inv.signature(), inv.has_receiver());
+    _args.post_initialize(inv.signature(), inv.has_receiver(), false);
   }
 
   if (has_return()) {
@@ -255,7 +265,7 @@
     assert(count > 0, "room for args type but none found?");
     check_number_of_arguments(count);
 #endif
-    _args.post_initialize(inv.signature(), inv.has_receiver());
+    _args.post_initialize(inv.signature(), inv.has_receiver(), false);
   }
 
   if (has_return()) {
@@ -579,6 +589,34 @@
 }
 
 #endif
+
+int ParametersTypeData::compute_cell_count(Method* m) {
+  if (!MethodData::profile_parameters_for_method(m)) {
+    return 0;
+  }
+  int max = TypeProfileParmsLimit == -1 ? INT_MAX : TypeProfileParmsLimit;
+  int obj_args = TypeStackSlotEntries::compute_cell_count(m->signature(), !m->is_static(), max);
+  if (obj_args > 0) {
+    return obj_args + 1; // 1 cell for array len
+  }
+  return 0;
+}
+
+void ParametersTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
+  _parameters.post_initialize(mdo->method()->signature(), !mdo->method()->is_static(), true);
+}
+
+bool ParametersTypeData::profiling_enabled() {
+  return MethodData::profile_parameters();
+}
+
+#ifndef PRODUCT
+void ParametersTypeData::print_data_on(outputStream* st) const {
+  st->print("parameter types");
+  _parameters.print_data_on(st);
+}
+#endif
+
 // ==================================================================
 // MethodData*
 //
@@ -741,6 +779,12 @@
   int arg_size = method->size_of_parameters();
   object_size += DataLayout::compute_size_in_bytes(arg_size+1);
 
+  // Reserve room for an area of the MDO dedicated to profiling of
+  // parameters
+  int args_cell = ParametersTypeData::compute_cell_count(method());
+  if (args_cell > 0) {
+    object_size += DataLayout::compute_size_in_bytes(args_cell);
+  }
   return object_size;
 }
 
@@ -915,6 +959,8 @@
     return new CallTypeData(this);
   case DataLayout::virtual_call_type_data_tag:
     return new VirtualCallTypeData(this);
+  case DataLayout::parameters_type_data_tag:
+    return new ParametersTypeData(this);
   };
 }
 
@@ -936,6 +982,9 @@
     stream->next();
     data->post_initialize(stream, this);
   }
+  if (_parameters_type_data_di != -1) {
+    parameters_type_data()->post_initialize(NULL, this);
+  }
 }
 
 // Initialize the MethodData* corresponding to a given method.
@@ -975,7 +1024,23 @@
   int arg_size = method->size_of_parameters();
   dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1);
 
-  object_size += extra_size + DataLayout::compute_size_in_bytes(arg_size+1);
+  int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1);
+  object_size += extra_size + arg_data_size;
+
+  int args_cell = ParametersTypeData::compute_cell_count(method());
+  // If we are profiling parameters, we reserver an area near the end
+  // of the MDO after the slots for bytecodes (because there's no bci
+  // for method entry so they don't fit with the framework for the
+  // profiling of bytecodes). We store the offset within the MDO of
+  // this area (or -1 if no parameter is profiled)
+  if (args_cell > 0) {
+    object_size += DataLayout::compute_size_in_bytes(args_cell);
+    _parameters_type_data_di = data_size + extra_size + arg_data_size;
+    DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size);
+    dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell);
+  } else {
+    _parameters_type_data_di = -1;
+  }
 
   // Set an initial hint. Don't use set_hint_di() because
   // first_di() may be out of bounds if data_size is 0.
@@ -1134,6 +1199,9 @@
 void MethodData::print_data_on(outputStream* st) const {
   ResourceMark rm;
   ProfileData* data = first_data();
+  if (_parameters_type_data_di != -1) {
+    parameters_type_data()->print_data_on(st);
+  }
   for ( ; is_valid(data); data = next_data(data)) {
     st->print("%d", dp_to_di(data->dp()));
     st->fill_to(6);
@@ -1222,7 +1290,7 @@
 }
 
 int MethodData::profile_return_flag() {
-  return TypeProfileLevel / 10;
+  return (TypeProfileLevel % 100) / 10;
 }
 
 bool MethodData::profile_return() {
@@ -1249,3 +1317,32 @@
   assert(profile_return_jsr292_only(), "inconsistent");
   return profile_jsr292(m, bci);
 }
+
+int MethodData::profile_parameters_flag() {
+  return TypeProfileLevel / 100;
+}
+
+bool MethodData::profile_parameters() {
+  return profile_parameters_flag() > no_type_profile && profile_parameters_flag() <= type_profile_all;
+}
+
+bool MethodData::profile_parameters_jsr292_only() {
+  return profile_parameters_flag() == type_profile_jsr292;
+}
+
+bool MethodData::profile_all_parameters() {
+  return profile_parameters_flag() == type_profile_all;
+}
+
+bool MethodData::profile_parameters_for_method(methodHandle m) {
+  if (!profile_parameters()) {
+    return false;
+  }
+
+  if (profile_all_parameters()) {
+    return true;
+  }
+
+  assert(profile_parameters_jsr292_only(), "inconsistent");
+  return m->is_compiled_lambda_form();
+}