6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
authorkvn
Thu, 07 Jan 2010 16:26:31 -0800
changeset 4580 db05951a970c
parent 4579 62478db2dc78
child 4581 e89fbd1bcb3d
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE. Summary: Add missing check that value is used in memory expression in instructions with embedded load. Reviewed-by: never, jrose
hotspot/src/share/vm/opto/lcm.cpp
hotspot/test/compiler/6912517/Test.java
--- a/hotspot/src/share/vm/opto/lcm.cpp	Thu Jan 07 16:24:17 2010 -0800
+++ b/hotspot/src/share/vm/opto/lcm.cpp	Thu Jan 07 16:26:31 2010 -0800
@@ -120,6 +120,7 @@
     case Op_LoadRange:
     case Op_LoadD_unaligned:
     case Op_LoadL_unaligned:
+      assert(mach->in(2) == val, "should be address");
       break;
     case Op_StoreB:
     case Op_StoreC:
@@ -146,6 +147,21 @@
     default:                    // Also check for embedded loads
       if( !mach->needs_anti_dependence_check() )
         continue;               // Not an memory op; skip it
+      {
+        // Check that value is used in memory address.
+        Node* base;
+        Node* index;
+        const MachOper* oper = mach->memory_inputs(base, index);
+        if (oper == NULL || oper == (MachOper*)-1) {
+          continue;             // Not an memory op; skip it
+        }
+        if (val == base ||
+            val == index && val->bottom_type()->isa_narrowoop()) {
+          break;                // Found it
+        } else {
+          continue;             // Skip it
+        }
+      }
       break;
     }
     // check if the offset is not too high for implicit exception
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6912517/Test.java	Thu Jan 07 16:26:31 2010 -0800
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2009 D.E. Shaw.  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 6912517
+ * @summary JIT bug compiles out (and stops running) code that needs to be run.  Causes NPE.
+ *
+ * @run main/othervm -Xbatch -XX:CompileThreshold=100 -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops Test
+ */
+
+/**
+ * Highlights a bug with the JIT compiler.
+ * @author Matt Bruce m b r u c e __\at/__ g m a i l DOT c o m
+ */
+public class Test implements Runnable
+{
+    private final Thread myThread;
+    private Thread       myInitialThread;
+    private boolean      myShouldCheckThreads;
+
+    /**
+     * Sets up the running thread, and starts it.
+     */
+    public Test(int id)
+    {
+        myThread = new Thread(this);
+        myThread.setName("Runner: " + id);
+        myThread.start();
+        myShouldCheckThreads = false;
+    }
+
+    /**
+     * @param shouldCheckThreads the shouldCheckThreads to set
+     */
+    public void setShouldCheckThreads(boolean shouldCheckThreads)
+    {
+        myShouldCheckThreads = shouldCheckThreads;
+    }
+
+    /**
+     * Starts up the two threads with enough delay between them for JIT to
+     * kick in.
+     * @param args
+     * @throws InterruptedException
+     */
+    public static void main(String[] args) throws InterruptedException
+    {
+        // let this run for a bit, so the "run" below is JITTed.
+        for (int id = 0; id < 20; id++) {
+            System.out.println("Starting thread: " + id);
+            Test bug = new Test(id);
+            bug.setShouldCheckThreads(true);
+            Thread.sleep(2500);
+        }
+    }
+
+    /**
+     * @see java.lang.Runnable#run()
+     */
+    public void run()
+    {
+        long runNumber = 0;
+        while (true) {
+            // run hot for a little while, give JIT time to kick in to this loop.
+            // then run less hot.
+            if (runNumber > 15000) {
+                try {
+                    Thread.sleep(5);
+                }
+                catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+            runNumber++;
+            ensureProperCallingThread();
+        }
+    }
+
+    private void ensureProperCallingThread()
+    {
+        // this should never be null.  but with the JIT bug, it will be.
+        // JIT BUG IS HERE ==>>>>>
+        if (myShouldCheckThreads) {
+            if (myInitialThread == null) {
+                myInitialThread = Thread.currentThread();
+            }
+            else if (myInitialThread != Thread.currentThread()) {
+                System.out.println("Not working: " + myInitialThread.getName());
+            }
+        }
+    }
+}