changeset 505:3d3ff9a50b09

6805724: ModLNode::Ideal() generates functionally incorrect graph when divisor is any (2^k-1) constant. Summary: C2, ModLNode::Ideal() generates functionally incorrect graph when divisor is any (2^k-1) constant. Reviewed-by: rasbold
author kvn
date Tue, 17 Feb 2009 15:00:38 -0800
parents b7549fd4792e
children 1277526667b2
files src/share/vm/opto/divnode.cpp src/share/vm/utilities/globalDefinitions.hpp test/compiler/6805724/Test6805724.java
diffstat 3 files changed, 90 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/opto/divnode.cpp	Tue Feb 03 01:39:12 2009 -0800
+++ b/src/share/vm/opto/divnode.cpp	Tue Feb 17 15:00:38 2009 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  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
@@ -976,7 +976,7 @@
 
   // Expand mod
   if( con >= 0 && con < max_jlong && is_power_of_2_long(con+1) ) {
-    uint k = log2_long(con);       // Extract k
+    uint k = exact_log2_long(con+1);  // Extract k
 
     // Basic algorithm by David Detlefs.  See fastmod_long.java for gory details.
     // Used to help a popular random number generator which does a long-mod
--- a/src/share/vm/utilities/globalDefinitions.hpp	Tue Feb 03 01:39:12 2009 -0800
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Tue Feb 17 15:00:38 2009 -0800
@@ -907,6 +907,14 @@
   return log2_intptr(x);
 }
 
+//* the argument must be exactly a power of 2
+inline int exact_log2_long(jlong x) {
+  #ifdef ASSERT
+    if (!is_power_of_2_long(x)) basic_fatal("x must be a power of 2");
+  #endif
+  return log2_long(x);
+}
+
 
 // returns integer round-up to the nearest multiple of s (s must be a power of two)
 inline intptr_t round_to(intptr_t x, uintx s) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/6805724/Test6805724.java	Tue Feb 17 15:00:38 2009 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6805724
+ * @summary ModLNode::Ideal() generates functionally incorrect graph when divisor is any (2^k-1) constant.
+ *
+ * @run main/othervm -Xcomp -XX:CompileOnly=Test6805724.fcomp Test6805724
+ */
+
+import java.net.URLClassLoader;
+
+public class Test6805724 implements Runnable {
+    // Initialize DIVISOR so that it is final in this class.
+    static final long DIVISOR;  // 2^k-1 constant
+
+    static {
+        long value = 0;
+        try {
+            value = Long.decode(System.getProperty("divisor"));
+        } catch (Throwable t) {
+            // This one is required for the Class.forName() in main.
+        }
+        DIVISOR = value;
+    }
+
+    static long fint(long x) {
+        return x % DIVISOR;
+    }
+
+    static long fcomp(long x) {
+        return x % DIVISOR;
+    }
+
+    public void run() {
+        long a = 0x617981E1L;
+
+        long expected = fint(a);
+        long result = fcomp(a);
+
+        if (result != expected)
+            throw new InternalError(result + " != " + expected);
+    }
+
+    public static void main(String args[]) throws Exception {
+        Class cl = Class.forName("Test6805724");
+        URLClassLoader apploader = (URLClassLoader) cl.getClassLoader();
+
+        // Iterate over all 2^k-1 divisors.
+        for (int k = 1; k < Long.SIZE; k++) {
+            long divisor = (1L << k) - 1;
+            System.setProperty("divisor", "" + divisor);
+            ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent());
+            Class c = loader.loadClass("Test6805724");
+            Runnable r = (Runnable) c.newInstance();
+            r.run();
+        }
+    }
+}