changeset 5826:7d1eb0dcab5a

8064524: Compiler code generation improvements Summary: Contains refactoring from 8009130, 8033150, 7200776 & 8028438 without default method work Reviewed-by: jrose, acorn, vlivanov
author drchase
date Tue, 17 Apr 2018 22:51:28 +0100
parents 8b0587cd6277
children 0dc659da232e
files src/share/vm/code/dependencies.cpp src/share/vm/code/dependencies.hpp src/share/vm/interpreter/linkResolver.cpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/instanceKlass.hpp
diffstat 5 files changed, 119 insertions(+), 113 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/code/dependencies.cpp	Sat Apr 14 07:26:03 2018 +0100
+++ b/src/share/vm/code/dependencies.cpp	Tue Apr 17 22:51:28 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -810,8 +810,11 @@
     if (doing_subtype_search()) {
       return Dependencies::is_concrete_klass(k);
     } else {
-      methodOop m = instanceKlass::cast(k)->find_method(_name, _signature);
-      if (m == NULL || !Dependencies::is_concrete_method(m))  return false;
+      // Search class hierarchy first.
+      methodOop m = instanceKlass::cast(k)->find_instance_method(_name, _signature);
+      if (!Dependencies::is_concrete_method(m)) {
+            return false;
+      }
       _found_methods[_num_participants] = m;
       // Note:  If add_participant(k) is called,
       // the method m will already be memoized for it.
@@ -1104,15 +1107,12 @@
 }
 
 bool Dependencies::is_concrete_method(methodOop m) {
-  // Statics are irrelevant to virtual call sites.
-  if (m->is_static())  return false;
-
-  // We could also return false if m does not yet appear to be
-  // executed, if the VM version supports this distinction also.
-  return !m->is_abstract();
+  // NULL is not a concrete method,
+  // statics are irrelevant to virtual call sites,
+  // abstract methods are not concrete,
+  return ! ( m == NULL || m -> is_static() || m -> is_abstract());
 }
 
-
 Klass* Dependencies::find_finalizable_subclass(Klass* k) {
   if (k->is_interface())  return NULL;
   if (k->has_finalizer()) return k;
@@ -1134,16 +1134,6 @@
   return true;
 }
 
-bool Dependencies::is_concrete_method(ciMethod* m) {
-  // Statics are irrelevant to virtual call sites.
-  if (m->is_static())  return false;
-
-  // We could also return false if m does not yet appear to be
-  // executed, if the VM version supports this distinction also.
-  return !m->is_abstract();
-}
-
-
 bool Dependencies::has_finalizable_subclass(ciInstanceKlass* k) {
   return k->has_finalizable_subclass();
 }
@@ -1387,61 +1377,6 @@
   return wf.find_witness_definer(ctxk, changes);
 }
 
-// Find the set of all non-abstract methods under ctxk that match m[0].
-// (The method m[0] must be defined or inherited in ctxk.)
-// Include m itself in the set, unless it is abstract.
-// Fill the given array m[0..(mlen-1)] with this set, and return the length.
-// (The length may be zero if no concrete methods are found anywhere.)
-// If there are too many concrete methods to fit in marray, return -1.
-int Dependencies::find_exclusive_concrete_methods(klassOop ctxk,
-                                                  int mlen,
-                                                  methodOop marray[]) {
-  methodOop m0 = marray[0];
-  ClassHierarchyWalker wf(m0);
-  assert(wf.check_method_context(ctxk, m0), "proper context");
-  wf.record_witnesses(mlen);
-  bool participants_hide_witnesses = true;
-  klassOop wit = wf.find_witness_definer(ctxk);
-  if (wit != NULL)  return -1;  // Too many witnesses.
-  int num = wf.num_participants();
-  assert(num <= mlen, "oob");
-  // Keep track of whether m is also part of the result set.
-  int mfill = 0;
-  assert(marray[mfill] == m0, "sanity");
-  if (Dependencies::is_concrete_method(m0))
-    mfill++;  // keep m0 as marray[0], the first result
-  for (int i = 0; i < num; i++) {
-    methodOop fm = wf.found_method(i);
-    if (fm == m0)  continue;  // Already put this guy in the list.
-    if (mfill == mlen) {
-      return -1;              // Oops.  Too many methods after all!
-    }
-    marray[mfill++] = fm;
-  }
-#ifndef PRODUCT
-  // Make sure the dependency mechanism will pass this discovery:
-  if (VerifyDependencies) {
-    // Turn off dependency tracing while actually testing deps.
-    FlagSetting fs(TraceDependencies, false);
-    switch (mfill) {
-    case 1:
-      guarantee(NULL == (void *)check_unique_concrete_method(ctxk, marray[0]),
-                "verify dep.");
-      break;
-    case 2:
-      guarantee(NULL == (void *)
-                check_exclusive_concrete_methods(ctxk, marray[0], marray[1]),
-                "verify dep.");
-      break;
-    default:
-      ShouldNotReachHere();  // mlen > 2 yet supported
-    }
-  }
-#endif //PRODUCT
-  return mfill;
-}
-
-
 klassOop Dependencies::check_has_no_finalizable_subclasses(klassOop ctxk, KlassDepChange* changes) {
   Klass* search_at = ctxk->klass_part();
   if (changes != NULL)
@@ -1453,7 +1388,6 @@
   return result->as_klassOop();
 }
 
-
 klassOop Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) {
   assert(call_site    ->is_a(SystemDictionary::CallSite_klass()),     "sanity");
   assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity");
--- a/src/share/vm/code/dependencies.hpp	Sat Apr 14 07:26:03 2018 +0100
+++ b/src/share/vm/code/dependencies.hpp	Tue Apr 17 22:51:28 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -301,7 +301,6 @@
   // not go back into the VM to get their value; they must cache the
   // bit in the CI, either eagerly or lazily.)
   static bool is_concrete_klass(ciInstanceKlass* k); // k appears instantiable
-  static bool is_concrete_method(ciMethod* m);       // m appears invocable
   static bool has_finalizable_subclass(ciInstanceKlass* k);
 
   // As a general rule, it is OK to compile under the assumption that
@@ -348,7 +347,6 @@
   static klassOop  find_unique_concrete_subtype(klassOop ctxk);
   static methodOop find_unique_concrete_method(klassOop ctxk, methodOop m);
   static int       find_exclusive_concrete_subtypes(klassOop ctxk, int klen, klassOop k[]);
-  static int       find_exclusive_concrete_methods(klassOop ctxk, int mlen, methodOop m[]);
 
   // Create the encoding which will be stored in an nmethod.
   void encode_content_bytes();
--- a/src/share/vm/interpreter/linkResolver.cpp	Sat Apr 14 07:26:03 2018 +0100
+++ b/src/share/vm/interpreter/linkResolver.cpp	Tue Apr 17 22:51:28 2018 +0100
@@ -188,6 +188,7 @@
 //
 // According to JVM spec. $5.4.3c & $5.4.3d
 
+// Look up method in klasses, including static methods
 void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
   methodOop result_oop = klass->uncached_lookup_method(name, signature);
 
@@ -213,8 +214,8 @@
   methodOop result_oop = klass->uncached_lookup_method(name, signature);
   result = methodHandle(THREAD, result_oop);
   while (!result.is_null() && result->is_static()) {
-    klass = KlassHandle(THREAD, Klass::cast(result->method_holder())->super());
-    result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature));
+    KlassHandle super_klass = KlassHandle(THREAD, Klass::cast(result->method_holder())->super());
+    result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature));
   }
 }
 
--- a/src/share/vm/oops/instanceKlass.cpp	Sat Apr 14 07:26:03 2018 +0100
+++ b/src/share/vm/oops/instanceKlass.cpp	Tue Apr 17 22:51:28 2018 +0100
@@ -1046,11 +1046,7 @@
 }
 #endif
 
-methodOop instanceKlass::find_method(Symbol* name, Symbol* signature) const {
-  return instanceKlass::find_method(methods(), name, signature);
-}
-
-methodOop instanceKlass::find_method(objArrayOop methods, Symbol* name, Symbol* signature) {
+static int binary_search(objArrayOop methods, Symbol* name) {
   int len = methods->length();
   // methods are sorted, so do binary search
   int l = 0;
@@ -1061,43 +1057,100 @@
     assert(m->is_method(), "must be method");
     int res = m->name()->fast_compare(name);
     if (res == 0) {
-      // found matching name; do linear search to find matching signature
-      // first, quick check for common case
-      if (m->signature() == signature) return m;
-      // search downwards through overloaded methods
-      int i;
-      for (i = mid - 1; i >= l; i--) {
-        methodOop m = (methodOop)methods->obj_at(i);
-        assert(m->is_method(), "must be method");
-        if (m->name() != name) break;
-        if (m->signature() == signature) return m;
-      }
-      // search upwards
-      for (i = mid + 1; i <= h; i++) {
-        methodOop m = (methodOop)methods->obj_at(i);
-        assert(m->is_method(), "must be method");
-        if (m->name() != name) break;
-        if (m->signature() == signature) return m;
-      }
-      // not found
-#ifdef ASSERT
-      int index = linear_search(methods, name, signature);
-      assert(index == -1, err_msg("binary search should have found entry %d", index));
-#endif
-      return NULL;
+      return mid;
     } else if (res < 0) {
       l = mid + 1;
     } else {
       h = mid - 1;
     }
   }
+  return -1;
+}
+
+// find_method looks up the name/signature in the local methods array
+methodOop instanceKlass::find_method(Symbol* name, Symbol* signature) const {
+  return instanceKlass::find_method(methods(), name, signature);
+}
+
+// find_instance_method looks up the name/signature in the local methods array
+// and skips over static methods
+methodOop instanceKlass::find_instance_method(Symbol* name, Symbol* signature) {
+  return instanceKlass::find_instance_method(methods(), name, signature);
+}
+
+// find_instance_method looks up the name/signature in the local methods array
+// and skips over static methods
+methodOop instanceKlass::find_instance_method(objArrayOop methods, Symbol* name, Symbol* signature) {
+  methodOop meth = instanceKlass::find_method_impl(methods, name, signature, true);
+  return meth;
+}
+
+// find_method looks up the name/signature in the local methods array
+methodOop instanceKlass::find_method(objArrayOop methods, Symbol* name, Symbol* signature) {
+  return instanceKlass::find_method_impl(methods, name, signature, false);
+}
+
+methodOop instanceKlass::find_method_impl(objArrayOop methods, Symbol* name, Symbol* signature, bool skipping_static) {
+  int hit = find_method_index(methods, name, signature, skipping_static);
+  return hit >= 0 ? (methodOop) methods->obj_at(hit): NULL;
+}
+
+bool instanceKlass::method_matches(methodOop m, Symbol* signature, bool skipping_static) {
+    return (m->signature() == signature) && (!skipping_static || !m->is_static());
+}
+
+// Used indirectly by find_method
+// find_method_index looks in the local methods array to return the index
+// of the matching name/signature
+int instanceKlass::find_method_index(objArrayOop methods, Symbol* name, Symbol* signature, bool skipping_static) {
+  int hit = binary_search(methods, name);
+  if (hit != -1) {
+    methodOop m = (methodOop) methods->obj_at(hit);
+
+    // Do linear search to find matching signature.  First, quick check
+    // for common case
+    if (method_matches(m, signature, skipping_static)) return hit;
+    // search downwards through overloaded methods
+    int i;
+    for (i = hit - 1; i >= 0; --i) {
+        methodOop m = (methodOop) methods->obj_at(i);
+        assert(m->is_method(), "must be method");
+        if (m->name() != name) break;
+        if (method_matches(m, signature, skipping_static)) return i;
+    }
+    // search upwards
+    for (i = hit + 1; i < methods->length(); ++i) {
+        methodOop m = (methodOop) methods->obj_at(i);
+        assert(m->is_method(), "must be method");
+        if (m->name() != name) break;
+        if (method_matches(m, signature, skipping_static)) return i;
+    }
+    // not found
 #ifdef ASSERT
-  int index = linear_search(methods, name, signature);
-  assert(index == -1, err_msg("binary search should have found entry %d", index));
+    int index = skipping_static ? -1 : linear_search(methods, name, signature);
+    assert(index == -1, err_msg("binary search should have found entry %d", index));
 #endif
-  return NULL;
+  }
+  return -1;
+}
+int instanceKlass::find_method_by_name(Symbol* name, int* end) {
+  return find_method_by_name(methods(), name, end);
 }
 
+int instanceKlass::find_method_by_name(objArrayOop methods, Symbol* name, int* end_ptr) {
+  assert(end_ptr != NULL, "just checking");
+  int start = binary_search(methods, name);
+  int end = start + 1;
+  if (start != -1) {
+    while (start - 1 >= 0 && ((methodOop)(methods->obj_at(start - 1)))->name() == name) --start;
+    while (end < methods->length() && ((methodOop)(methods->obj_at(end)))->name() == name) ++end;
+    *end_ptr = end;
+    return start;
+  }
+  return -1;
+}
+
+// lookup_method searches both the local methods array and all superclasses methods arrays
 methodOop instanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
   klassOop klass = as_klassOop();
   while (klass != NULL) {
--- a/src/share/vm/oops/instanceKlass.hpp	Sat Apr 14 07:26:03 2018 +0100
+++ b/src/share/vm/oops/instanceKlass.hpp	Tue Apr 17 22:51:28 2018 +0100
@@ -494,6 +494,16 @@
   methodOop find_method(Symbol* name, Symbol* signature) const;
   static methodOop find_method(objArrayOop methods, Symbol* name, Symbol* signature);
 
+  // find a local method, but skip static methods
+  methodOop find_instance_method(Symbol* name, Symbol* signature);
+  static methodOop find_instance_method(objArrayOop methods, Symbol* name, Symbol* signature);
+
+  // true if method matches signature and conforms to skipping_X conditions.
+  static bool method_matches(methodOop m, Symbol* signature, bool skipping_static);
+
+  // find a local method index in default_methods (returns -1 if not found)
+  static int find_method_index(objArrayOop methods, Symbol* name, Symbol* signature, bool skipping_static);
+
   // lookup operation (returns NULL if not found)
   methodOop uncached_lookup_method(Symbol* name, Symbol* signature) const;
 
@@ -501,6 +511,13 @@
   // (returns NULL if not found)
   methodOop lookup_method_in_all_interfaces(Symbol* name, Symbol* signature) const;
 
+  // Find method indices by name.  If a method with the specified name is
+  // found the index to the first method is returned, and 'end' is filled in
+  // with the index of first non-name-matching method.  If no method is found
+  // -1 is returned.
+  int find_method_by_name(Symbol* name, int* end);
+  static int find_method_by_name(objArrayOop methods, Symbol* name, int* end);
+
   // constant pool
   constantPoolOop constants() const        { return _constants; }
   void set_constants(constantPoolOop c)    { oop_store_without_check((oop*) &_constants, (oop) c); }
@@ -968,6 +985,9 @@
   // Returns the array class with this class as element type
   klassOop array_klass_impl(bool or_null, TRAPS);
 
+  // find a local method (returns NULL if not found)
+  static methodOop find_method_impl(objArrayOop methods, Symbol* name, Symbol* signature, bool skipping_static);
+
 public:
   // sharing support
   virtual void remove_unshareable_info();