diff src/share/vm/ci/ciMethod.cpp @ 12966:b2ee5dc63353

8024070: C2 needs some form of type speculation Summary: record unused type profile information with type system, propagate and use it. Reviewed-by: kvn, twisti
author roland
date Wed, 23 Oct 2013 12:40:23 +0200
parents c775af091fe9
children 096c224171c4 183bd5c00828 e46f2ee62e78
line wrap: on
line diff
--- a/src/share/vm/ci/ciMethod.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/src/share/vm/ci/ciMethod.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -565,6 +565,116 @@
   if (_limit < MorphismLimit) _limit++;
 }
 
+
+void ciMethod::assert_virtual_call_type_ok(int bci) {
+  assert(java_code_at_bci(bci) == Bytecodes::_invokevirtual ||
+         java_code_at_bci(bci) == Bytecodes::_invokeinterface, err_msg("unexpected bytecode %s", Bytecodes::name(java_code_at_bci(bci))));
+}
+
+void ciMethod::assert_call_type_ok(int bci) {
+  assert(java_code_at_bci(bci) == Bytecodes::_invokestatic ||
+         java_code_at_bci(bci) == Bytecodes::_invokespecial ||
+         java_code_at_bci(bci) == Bytecodes::_invokedynamic, err_msg("unexpected bytecode %s", Bytecodes::name(java_code_at_bci(bci))));
+}
+
+/**
+ * Check whether profiling provides a type for the argument i to the
+ * call at bci bci
+ *
+ * @param bci  bci of the call
+ * @param i    argument number
+ * @return     profiled type
+ *
+ * If the profile reports that the argument may be null, return false
+ * at least for now.
+ */
+ciKlass* ciMethod::argument_profiled_type(int bci, int i) {
+  if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
+    ciProfileData* data = method_data()->bci_to_data(bci);
+    if (data != NULL) {
+      if (data->is_VirtualCallTypeData()) {
+        assert_virtual_call_type_ok(bci);
+        ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
+        if (i >= call->number_of_arguments()) {
+          return NULL;
+        }
+        ciKlass* type = call->valid_argument_type(i);
+        if (type != NULL && !call->argument_maybe_null(i)) {
+          return type;
+        }
+      } else if (data->is_CallTypeData()) {
+        assert_call_type_ok(bci);
+        ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
+        if (i >= call->number_of_arguments()) {
+          return NULL;
+        }
+        ciKlass* type = call->valid_argument_type(i);
+        if (type != NULL && !call->argument_maybe_null(i)) {
+          return type;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+/**
+ * Check whether profiling provides a type for the return value from
+ * the call at bci bci
+ *
+ * @param bci  bci of the call
+ * @return     profiled type
+ *
+ * If the profile reports that the argument may be null, return false
+ * at least for now.
+ */
+ciKlass* ciMethod::return_profiled_type(int bci) {
+  if (MethodData::profile_return() && method_data() != NULL && method_data()->is_mature()) {
+    ciProfileData* data = method_data()->bci_to_data(bci);
+    if (data != NULL) {
+      if (data->is_VirtualCallTypeData()) {
+        assert_virtual_call_type_ok(bci);
+        ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
+        ciKlass* type = call->valid_return_type();
+        if (type != NULL && !call->return_maybe_null()) {
+          return type;
+        }
+      } else if (data->is_CallTypeData()) {
+        assert_call_type_ok(bci);
+        ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
+        ciKlass* type = call->valid_return_type();
+        if (type != NULL && !call->return_maybe_null()) {
+          return type;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+/**
+ * Check whether profiling provides a type for the parameter i
+ *
+ * @param i    parameter number
+ * @return     profiled type
+ *
+ * If the profile reports that the argument may be null, return false
+ * at least for now.
+ */
+ciKlass* ciMethod::parameter_profiled_type(int i) {
+  if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
+    ciParametersTypeData* parameters = method_data()->parameters_type_data();
+    if (parameters != NULL && i < parameters->number_of_parameters()) {
+      ciKlass* type = parameters->valid_parameter_type(i);
+      if (type != NULL && !parameters->parameter_maybe_null(i)) {
+        return type;
+      }
+    }
+  }
+  return NULL;
+}
+
+
 // ------------------------------------------------------------------
 // ciMethod::find_monomorphic_target
 //