changeset 10936:dd646a857cc3 default tip

Merge jdk8u292-ga
author Andrew John Hughes <gnu_andrew@member.fsf.org>
date Mon, 26 Apr 2021 14:01:43 +0100
parents f79e943d15a7 (current diff) b6054610c065 (diff)
children
files .hgtags make/linux/makefiles/defs.make src/cpu/aarch64/vm/c1_FrameMap_aarch64.cpp src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp src/share/vm/code/dependencies.cpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/instanceKlass.hpp src/share/vm/opto/mathexactnode.cpp src/share/vm/opto/mathexactnode.hpp
diffstat 10 files changed, 160 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Sun Apr 25 18:18:49 2021 +0100
+++ b/.hgtags	Mon Apr 26 14:01:43 2021 +0100
@@ -1439,3 +1439,9 @@
 306a4643e4d22f7558b4a725708cb39c82ac1cc1 jdk8u292-b03
 16bc2fd11c4c62b01473221b1b6b892a63723e18 jdk8u292-b04
 a435c913c8ce30f0487d05cfec1d9be3fcc57f10 jdk8u292-b05
+a5795acea81480d6377dbc5256d82e2f25cd7394 jdk8u292-b06
+f206e4bfcef993ce5a75ed54612f045ca047abd3 jdk8u292-b07
+85c5bc8157df45d7351c388f18ab65297b5bdd01 jdk8u292-b08
+65907019826ad9fe7d13df531e0c108cc1f179b0 jdk8u292-b09
+2a6952bb390975722d73580d1dc3cb6ac69b76b0 jdk8u292-b10
+2a6952bb390975722d73580d1dc3cb6ac69b76b0 jdk8u292-ga
--- a/make/linux/makefiles/defs.make	Sun Apr 25 18:18:49 2021 +0100
+++ b/make/linux/makefiles/defs.make	Mon Apr 26 14:01:43 2021 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2021, 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
@@ -314,11 +314,13 @@
 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   ifneq ($(STRIP_POLICY),no_strip)
     ifeq ($(ZIP_DEBUGINFO_FILES),1)
-      ADD_SA_BINARIES/x86   += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.diz
-      ADD_SA_BINARIES/sparc += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.diz
+      ADD_SA_BINARIES/x86     += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.diz
+      ADD_SA_BINARIES/sparc   += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.diz
+      ADD_SA_BINARIES/aarch64 += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.diz
     else
-      ADD_SA_BINARIES/x86   += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
-      ADD_SA_BINARIES/sparc += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
+      ADD_SA_BINARIES/x86     += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
+      ADD_SA_BINARIES/sparc   += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
+      ADD_SA_BINARIES/aarch64 += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
     endif
   endif
 endif
--- a/src/cpu/aarch64/vm/c1_FrameMap_aarch64.cpp	Sun Apr 25 18:18:49 2021 +0100
+++ b/src/cpu/aarch64/vm/c1_FrameMap_aarch64.cpp	Mon Apr 26 14:01:43 2021 +0100
@@ -54,6 +54,8 @@
       opr = as_oop_opr(reg);
     } else if (type == T_METADATA) {
       opr = as_metadata_opr(reg);
+    } else if (type == T_ADDRESS) {
+      opr = as_address_opr(reg);
     } else {
       opr = as_opr(reg);
     }
--- a/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Sun Apr 25 18:18:49 2021 +0100
+++ b/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Mon Apr 26 14:01:43 2021 +0100
@@ -792,7 +792,7 @@
     if (type == T_ARRAY || type == T_OBJECT) {
       __ str(src->as_register(), frame_map()->address_for_slot(dest->single_stack_ix()));
       __ verify_oop(src->as_register());
-    } else if (type == T_METADATA || type == T_DOUBLE) {
+    } else if (type == T_METADATA || type == T_DOUBLE || type == T_ADDRESS) {
       __ str(src->as_register(), frame_map()->address_for_slot(dest->single_stack_ix()));
     } else {
       __ strw(src->as_register(), frame_map()->address_for_slot(dest->single_stack_ix()));
@@ -905,7 +905,7 @@
     if (type == T_ARRAY || type == T_OBJECT) {
       __ ldr(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix()));
       __ verify_oop(dest->as_register());
-    } else if (type == T_METADATA) {
+    } else if (type == T_METADATA || type == T_ADDRESS) {
       __ ldr(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix()));
     } else {
       __ ldrw(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix()));
--- a/src/share/vm/code/dependencies.cpp	Sun Apr 25 18:18:49 2021 +0100
+++ b/src/share/vm/code/dependencies.cpp	Mon Apr 26 14:01:43 2021 +0100
@@ -29,6 +29,7 @@
 #include "ci/ciMethod.hpp"
 #include "code/dependencies.hpp"
 #include "compiler/compileLog.hpp"
+#include "oops/klass.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/handles.inline.hpp"
@@ -896,8 +897,9 @@
     } else if (!k->oop_is_instance()) {
       return false; // no methods to find in an array type
     } else {
-      // Search class hierarchy first.
-      Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature);
+      // Search class hierarchy first, skipping private implementations
+      // as they never override any inherited methods
+      Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature, Klass::skip_private);
       if (!Dependencies::is_concrete_method(m, k)) {
         // Check for re-abstraction of method
         if (!k->is_interface() && m != NULL && m->is_abstract()) {
@@ -907,7 +909,7 @@
           ClassHierarchyWalker wf(_participants, _num_participants);
           Klass* w = wf.find_witness_subtype(k);
           if (w != NULL) {
-            Method* wm = InstanceKlass::cast(w)->find_instance_method(_name, _signature);
+            Method* wm = InstanceKlass::cast(w)->find_instance_method(_name, _signature, Klass::skip_private);
             if (!Dependencies::is_concrete_method(wm, w)) {
               // Found a concrete subtype 'w' which does not override abstract method 'm'.
               // Bail out because 'm' could be called with 'w' as receiver (leading to an
@@ -968,6 +970,7 @@
   Klass* find_witness_in(KlassDepChange& changes,
                          Klass* context_type,
                            bool participants_hide_witnesses);
+  bool witnessed_reabstraction_in_supers(Klass* k);
  public:
   Klass* find_witness_subtype(Klass* context_type, KlassDepChange* changes = NULL) {
     assert(doing_subtype_search(), "must set up a subtype search");
@@ -1042,7 +1045,6 @@
 #define count_find_witness_calls() (0)
 #endif //PRODUCT
 
-
 Klass* ClassHierarchyWalker::find_witness_in(KlassDepChange& changes,
                                                Klass* context_type,
                                                bool participants_hide_witnesses) {
@@ -1080,15 +1082,20 @@
     }
   }
 
-  if (is_witness(new_type) &&
-      !ignore_witness(new_type)) {
-    return new_type;
+  if (is_witness(new_type)) {
+    if (!ignore_witness(new_type)) {
+      return new_type;
+    }
+  } else if (!doing_subtype_search()) {
+    // No witness found, but is_witness() doesn't detect method re-abstraction in case of spot-checking.
+    if (witnessed_reabstraction_in_supers(new_type)) {
+      return new_type;
+    }
   }
 
   return NULL;
 }
 
-
 // Walk hierarchy under a context type, looking for unexpected types.
 // Do not report participant types, and recursively walk beneath
 // them only if participants_hide_witnesses is false.
@@ -1207,6 +1214,32 @@
 #undef ADD_SUBCLASS_CHAIN
 }
 
+bool ClassHierarchyWalker::witnessed_reabstraction_in_supers(Klass* k) {
+  if (!k->oop_is_instance()) {
+    return false; // no methods to find in an array type
+  } else {
+    // Looking for a case when an abstract method is inherited into a concrete class.
+    if (Dependencies::is_concrete_klass(k) && !k->is_interface()) {
+      Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature, Klass::skip_private);
+      if (m != NULL) {
+        return false; // no reabstraction possible: local method found
+      }
+      for (InstanceKlass* super = InstanceKlass::cast(k)->java_super(); super != NULL; super = super->java_super()) {
+        m = super->find_instance_method(_name, _signature, Klass::skip_private);
+        if (m != NULL) { // inherited method found
+          if (m->is_abstract() || m->is_overpass()) {
+            _found_methods[_num_participants] = m;
+            return true; // abstract method found
+          }
+          return false;
+        }
+      }
+      assert(false, "root method not found");
+      return true;
+    }
+    return false;
+  }
+}
 
 bool Dependencies::is_concrete_klass(Klass* k) {
   if (k->is_abstract())  return false;
--- a/src/share/vm/oops/instanceKlass.cpp	Sun Apr 25 18:18:49 2021 +0100
+++ b/src/share/vm/oops/instanceKlass.cpp	Mon Apr 26 14:01:43 2021 +0100
@@ -1494,18 +1494,22 @@
 
 // find_instance_method looks up the name/signature in the local methods array
 // and skips over static methods
-Method* InstanceKlass::find_instance_method(
-    Array<Method*>* methods, Symbol* name, Symbol* signature) {
+Method* InstanceKlass::find_instance_method(Array<Method*>* methods,
+                                            Symbol* name,
+                                            Symbol* signature,
+                                            PrivateLookupMode private_mode) {
   Method* meth = InstanceKlass::find_method_impl(methods, name, signature,
-                                                 find_overpass, skip_static, find_private);
+                                                 find_overpass, skip_static, private_mode);
   assert(((meth == NULL) || !meth->is_static()), "find_instance_method should have skipped statics");
   return meth;
 }
 
 // find_instance_method looks up the name/signature in the local methods array
 // and skips over static methods
-Method* InstanceKlass::find_instance_method(Symbol* name, Symbol* signature) {
-    return InstanceKlass::find_instance_method(methods(), name, signature);
+Method* InstanceKlass::find_instance_method(Symbol* name,
+                                            Symbol* signature,
+                                            PrivateLookupMode private_mode) {
+  return InstanceKlass::find_instance_method(methods(), name, signature, private_mode);
 }
 
 // Find looks up the name/signature in the local methods array
--- a/src/share/vm/oops/instanceKlass.hpp	Sun Apr 25 18:18:49 2021 +0100
+++ b/src/share/vm/oops/instanceKlass.hpp	Mon Apr 26 14:01:43 2021 +0100
@@ -526,8 +526,11 @@
   static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
 
   // find a local method, but skip static methods
-  Method* find_instance_method(Symbol* name, Symbol* signature);
-  static Method* find_instance_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
+  Method* find_instance_method(Symbol* name, Symbol* signature,
+                               PrivateLookupMode private_mode);
+  static Method* find_instance_method(Array<Method*>* methods,
+                                      Symbol* name, Symbol* signature,
+                                      PrivateLookupMode private_mode);
 
   // find a local method (returns NULL if not found)
   Method* find_local_method(Symbol* name, Symbol* signature,
--- a/src/share/vm/opto/mathexactnode.cpp	Sun Apr 25 18:18:49 2021 +0100
+++ b/src/share/vm/opto/mathexactnode.cpp	Mon Apr 26 14:01:43 2021 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -117,23 +117,33 @@
   return SubHelper<OverflowSubLNode>::will_overflow(v1, v2);
 }
 
-bool OverflowMulLNode::will_overflow(jlong val1, jlong val2) const {
-    jlong result = val1 * val2;
-    jlong ax = (val1 < 0 ? -val1 : val1);
-    jlong ay = (val2 < 0 ? -val2 : val2);
+bool OverflowMulLNode::is_overflow(jlong val1, jlong val2) {
+    // x * { 0, 1 } will never overflow. Even for x = min_jlong
+    if (val1 == 0 || val2 == 0 || val1 == 1 || val2 == 1) {
+      return false;
+    }
 
-    bool overflow = false;
-    if ((ax | ay) & CONST64(0xFFFFFFFF00000000)) {
-      // potential overflow if any bit in upper 32 bits are set
-      if ((val1 == min_jlong && val2 == -1) || (val2 == min_jlong && val1 == -1)) {
-        // -1 * Long.MIN_VALUE will overflow
-        overflow = true;
-      } else if (val2 != 0 && (result / val2 != val1)) {
-        overflow = true;
-      }
+    // x * min_jlong for x not in { 0, 1 } overflows
+    // even -1 as -1 * min_jlong is an overflow
+    if (val1 == min_jlong || val2 == min_jlong) {
+      return true;
     }
 
-    return overflow;
+    // if (x * y) / y == x there is no overflow
+    //
+    // the multiplication here is done as unsigned to avoid undefined behaviour which
+    // can be used by the compiler to assume that the check further down (result / val2 != val1)
+    // is always false and breaks the overflow check
+    julong v1 = (julong) val1;
+    julong v2 = (julong) val2;
+    julong tmp = v1 * v2;
+    jlong result = (jlong) tmp;
+
+    if (result / val2 != val1) {
+      return true;
+    }
+
+    return false;
 }
 
 bool OverflowAddINode::can_overflow(const Type* t1, const Type* t2) const {
--- a/src/share/vm/opto/mathexactnode.hpp	Sun Apr 25 18:18:49 2021 +0100
+++ b/src/share/vm/opto/mathexactnode.hpp	Mon Apr 26 14:01:43 2021 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -129,8 +129,10 @@
   OverflowMulLNode(Node* in1, Node* in2) : OverflowLNode(in1, in2) {}
   virtual int Opcode() const;
 
-  virtual bool will_overflow(jlong v1, jlong v2) const;
+  virtual bool will_overflow(jlong v1, jlong v2) const { return is_overflow(v1, v2); }
   virtual bool can_overflow(const Type* t1, const Type* t2) const;
+
+  static bool is_overflow(jlong v1, jlong v2);
 };
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/intrinsics/mathexact/LongMulOverflowTest.java	Mon Apr 26 14:01:43 2021 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8191915
+ * @summary Regression test for multiplyExact intrinsic
+ * @compile LongMulOverflowTest.java
+ * @run main/othervm -Xcomp -XX:-TieredCompilation LongMulOverflowTest
+ */
+
+public class LongMulOverflowTest {
+    public static void main(String[] args) {
+        LongMulOverflowTest test = new LongMulOverflowTest();
+        for (int i = 0; i < 10; ++i) {
+            try {
+                test.runTest();
+                throw new RuntimeException("Error, runTest() did not overflow!");
+            } catch (ArithmeticException e) {
+                // success
+            }
+
+            try {
+                test.runTestOverflow();
+                throw new RuntimeException("Error, runTestOverflow() did not overflow!");
+            } catch (ArithmeticException e) {
+                // success
+            }
+        }
+    }
+
+    public void runTest() {
+        java.lang.Math.multiplyExact(Long.MIN_VALUE, 7);
+    }
+
+    public void runTestOverflow() {
+      java.lang.Math.multiplyExact((Long.MAX_VALUE / 2) + 1, 2);
+    }
+}