changeset 19944:f73a6e260e0c

Merge
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Wed, 18 Mar 2015 10:07:47 -0700
parents 6a0692faf9fd (diff) ed3e144ced29 (current diff)
children efa840053649 b3a2e8e564ad
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARCScratchRegister.java
diffstat 10 files changed, 260 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Wed Mar 18 16:39:06 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Wed Mar 18 10:07:47 2015 -0700
@@ -53,13 +53,9 @@
 
     @OptionalInput(InputType.Memory) MemoryNode lastLocationAccess;
 
-    public ArrayEqualsNode(ValueNode array1, ValueNode array2, ValueNode length) {
+    public ArrayEqualsNode(ValueNode array1, ValueNode array2, ValueNode length, @ConstantNodeParameter Kind kind) {
         super(TYPE, StampFactory.forKind(Kind.Boolean));
-        // Ignore nullness in stamp equality test
-        assert array1.stamp().join(StampFactory.objectNonNull()).equals(array2.stamp().join(StampFactory.objectNonNull()));
-        ObjectStamp array1Stamp = (ObjectStamp) array1.stamp();
-        ResolvedJavaType componentType = array1Stamp.type().getComponentType();
-        this.kind = componentType.getKind();
+        this.kind = kind;
         this.array1 = array1;
         this.array2 = array2;
         this.length = length;
@@ -109,28 +105,39 @@
     }
 
     @NodeIntrinsic
-    public static native boolean equals(boolean[] array1, boolean[] array2, int length);
+    public static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter Kind kind);
 
-    @NodeIntrinsic
-    public static native boolean equals(byte[] array1, byte[] array2, int length);
+    public static boolean equals(boolean[] array1, boolean[] array2, int length) {
+        return equals(array1, array2, length, Kind.Boolean);
+    }
 
-    @NodeIntrinsic
-    public static native boolean equals(char[] array1, char[] array2, int length);
+    public static boolean equals(byte[] array1, byte[] array2, int length) {
+        return equals(array1, array2, length, Kind.Byte);
+    }
 
-    @NodeIntrinsic
-    public static native boolean equals(short[] array1, short[] array2, int length);
+    public static boolean equals(char[] array1, char[] array2, int length) {
+        return equals(array1, array2, length, Kind.Char);
+    }
 
-    @NodeIntrinsic
-    public static native boolean equals(int[] array1, int[] array2, int length);
+    public static boolean equals(short[] array1, short[] array2, int length) {
+        return equals(array1, array2, length, Kind.Short);
+    }
 
-    @NodeIntrinsic
-    public static native boolean equals(long[] array1, long[] array2, int length);
+    public static boolean equals(int[] array1, int[] array2, int length) {
+        return equals(array1, array2, length, Kind.Int);
+    }
 
-    @NodeIntrinsic
-    public static native boolean equals(float[] array1, float[] array2, int length);
+    public static boolean equals(long[] array1, long[] array2, int length) {
+        return equals(array1, array2, length, Kind.Long);
+    }
 
-    @NodeIntrinsic
-    public static native boolean equals(double[] array1, double[] array2, int length);
+    public static boolean equals(float[] array1, float[] array2, int length) {
+        return equals(array1, array2, length, Kind.Float);
+    }
+
+    public static boolean equals(double[] array1, double[] array2, int length) {
+        return equals(array1, array2, length, Kind.Double);
+    }
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java	Wed Mar 18 16:39:06 2015 +0100
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java	Wed Mar 18 10:07:47 2015 -0700
@@ -45,6 +45,7 @@
         System.out.println("  -e:   sort events by elapsed time");
         System.out.println("  -n:   sort events by name and start");
         System.out.println("  -L:   print eliminated locks");
+        System.out.println("  -Q:   print compile queue activity");
         System.exit(exitcode);
     }
 
@@ -54,6 +55,7 @@
         boolean printInlining = false;
         boolean cleanup = false;
         boolean printEliminatedLocks = false;
+        boolean printCompileQueue = false;
         int index = 0;
 
         while (args.length > index) {
@@ -80,6 +82,9 @@
             } else if (args[index].equals("-L")) {
                 printEliminatedLocks = true;
                 index++;
+            } else if (args[index].equals("-Q")) {
+                printCompileQueue = true;
+                index++;
             } else {
                 break;
             }
@@ -92,32 +97,17 @@
         while (index < args.length) {
             ArrayList<LogEvent> events = LogParser.parse(args[index], cleanup);
 
-            if (printEliminatedLocks) {
-                Collections.sort(events, defaultSort);
-                for (LogEvent e : events) {
-                    if (e instanceof Compilation) {
-                        Compilation c = (Compilation) e;
-                        List<JVMState> eliminated = c.getEliminatedLocks();
-                        if (!eliminated.isEmpty()) {
-                            c.print(System.out);
-                            System.out.println("  Eliminated locks");
-                            for (JVMState jvms : eliminated) {
-                                System.err.print("   ");
-                                while (jvms != null) {
-                                    System.out.printf(" %s.%s@%d", jvms.method.getHolder().replace('/', '.'), jvms.method.getName(), jvms.bci);
-                                    jvms = jvms.outer;
-                                }
-                                System.out.println();
-                            }
-                        }
-                    }
-                }
+            if (printCompileQueue) {
+                printCompileQueue(events, System.out);
+            } else if (printEliminatedLocks) {
+                printEliminatedLocks(events, System.out, defaultSort);
             } else if (statistics) {
                 printStatistics(events, System.out);
             } else {
                 Collections.sort(events, defaultSort);
                 for (LogEvent c : events) {
                     if (c instanceof NMethod) continue;
+                    if (c instanceof TaskEvent) continue;
 
                     System.out.printf("%f ", c.getStart());
                     if (printInlining && c instanceof Compilation) {
@@ -131,7 +121,81 @@
             index++;
         }
     }
+    
+    public static void printCompileQueue(ArrayList<LogEvent> events, PrintStream out) {
+        int[] levels = new int[5];
+        HashMap<String, TaskEvent> tasks = new HashMap<String, TaskEvent>();
+        
+        out.printf("%7s ", "Stamp");
+        for (int i = 1; i <= 4; i++) {
+            out.printf(" Level%d", i);
+        }
+        out.printf("   %10s", "Kind");
+        out.println();
+        for (LogEvent e : events) {
+            if (e instanceof TaskEvent) {
+                boolean demoted = false;
+                TaskEvent t = (TaskEvent) e;
+                TaskEvent start = tasks.get(t.getId());
+                switch (t.getKind()) {
+                case Enqueue:
+                    assert start == null;
+                    levels[t.getLevel()] = levels[t.getLevel()] + 1;
+                    tasks.put(t.getId(), t);
+                    break;
+                    
+                case Finish:
+                case Dequeue:
+                    if (start != null && start.getLevel() != t.getLevel()) {
+                        // Sometimes tasks are moved to a lower
+                        // compilation level when the queue fills.
+                        demoted = true;
+                        levels[start.getLevel()] = levels[start.getLevel()] - 1;
+                    } else {
+                        levels[t.getLevel()] = levels[t.getLevel()] - 1;
+                    }
+                    break;
+                default:
+                    throw new InternalError();
+                }
+                out.printf("%7.3f ", t.getStart());
+                for (int i = 1; i <= 4; i++) {
+                    out.printf(" %6d", levels[i]);
+                }
+                out.printf("   %10s", t.getKind());
+                if (t.getComment() != null) {
+                    out.printf(" %s", t.getComment());
+                }
+                if (demoted) {
+                    out.printf("  %d->%d", start.getLevel(), t.getLevel());
+                }
+                out.println();
+            }
+        }
+    }
 
+    public static void printEliminatedLocks(ArrayList<LogEvent> events, PrintStream out, Comparator<LogEvent> defaultSort) {
+        Collections.sort(events, defaultSort);
+        for (LogEvent e : events) {
+            if (e instanceof Compilation) {
+                Compilation c = (Compilation) e;
+                List<JVMState> eliminated = c.getEliminatedLocks();
+                if (!eliminated.isEmpty()) {
+                    c.print(out);
+                    out.println("  Eliminated locks");
+                    for (JVMState jvms : eliminated) {
+                        System.err.print("   ");
+                        while (jvms != null) {
+                            out.printf(" %s.%s@%d", jvms.method.getHolder().replace('/', '.'), jvms.method.getName(), jvms.bci);
+                            jvms = jvms.outer;
+                        }
+                        out.println();
+                    }
+                }
+            }
+        }
+    }
+    
     public static void printStatistics(ArrayList<LogEvent> events, PrintStream out) {
         long cacheSize = 0;
         long maxCacheSize = 0;
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Wed Mar 18 16:39:06 2015 +0100
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Wed Mar 18 10:07:47 2015 -0700
@@ -204,7 +204,7 @@
                     }
                 } else {
                     if (c == null) {
-                        throw new InternalError("can't find compilation " + ble.getId() + " for " + ble);
+                        // throw new InternalError("can't find compilation " + ble.getId() + " for " + ble);
                     }
                 }
             }
@@ -363,6 +363,17 @@
             scopes.peek().last().setReason(search(atts, "reason"));
         } else if (qname.equals("failure")) {
             failureReason = search(atts, "reason");
+        } else if (qname.equals("task_queued")) {
+            String id = makeId(atts);
+            int level = Integer.parseInt(search(atts, "level"));
+            TaskEvent t = new TaskEvent(Double.parseDouble(search(atts, "stamp")), id, level, TaskEvent.Kind.Enqueue);
+            events.add(t);
+        } else if (qname.equals("task_dequeued")) {
+            String id = makeId(atts);
+            int level = Integer.parseInt(search(atts, "level"));
+            TaskEvent t = new TaskEvent(Double.parseDouble(search(atts, "stamp")), id, level, TaskEvent.Kind.Dequeue);
+            t.setComment(search(atts, "comment"));
+            events.add(t);
         } else if (qname.equals("task_done")) {
             compile.setEnd(Double.parseDouble(search(atts, "stamp")));
             if (Integer.parseInt(search(atts, "success")) == 0) {
@@ -425,6 +436,12 @@
                                      parseLong(atts.getValue("size")));
             nmethods.put(id, nm);
             events.add(nm);
+
+            int level = Integer.parseInt(search(atts, "level"));
+            if (level > 0) {
+                TaskEvent t = new TaskEvent(Double.parseDouble(search(atts, "stamp")), id, level, TaskEvent.Kind.Finish);
+                events.add(t);
+            }
         } else if (qname.equals("parse")) {
             Method m = method(search(atts, "method"));
             if (scopes.size() == 0) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/TaskEvent.java	Wed Mar 18 10:07:47 2015 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009, 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.
+ *
+ */
+
+package com.sun.hotspot.tools.compiler;
+
+import java.io.PrintStream;
+
+public class TaskEvent extends BasicLogEvent {
+    private int level;
+    private String comment;
+    private Kind kind;
+
+    enum Kind {
+        Enqueue,
+        Dequeue,
+        Finish
+    }
+    
+    public TaskEvent(double start, String id, int level, Kind kind) {
+        super(start, id);
+        this.level = level;
+        this.kind = kind;
+    }
+
+    void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    String getComment() {
+        return comment;
+    }
+
+    int getLevel() {
+        return level;
+    }
+
+    Kind getKind() {
+        return kind;
+    }
+
+    public void print(PrintStream stream) {
+        stream.printf("%s id='%s' level='%s' %s%n", start, id, level, kind);
+    }
+}
--- a/src/share/vm/compiler/compileBroker.cpp	Wed Mar 18 16:39:06 2015 +0100
+++ b/src/share/vm/compiler/compileBroker.cpp	Wed Mar 18 10:07:47 2015 -0700
@@ -558,6 +558,24 @@
 
 
 // ------------------------------------------------------------------
+// CompileTask::log_task_dequeued
+void CompileTask::log_task_dequeued(const char* comment) {
+  if (LogCompilation && xtty != NULL) {
+    Thread* thread = Thread::current();
+    ttyLocker ttyl;
+    ResourceMark rm(thread);
+
+    xtty->begin_elem("task_dequeued");
+    log_task(xtty);
+    if (comment != NULL) {
+      xtty->print(" comment='%s'", comment);
+    }
+    xtty->end_elem();
+  }
+}
+
+
+// ------------------------------------------------------------------
 // CompileTask::log_task_start
 void CompileTask::log_task_start(CompileLog* log)   {
   log->begin_head("task");
@@ -1202,10 +1220,12 @@
         blocking = false;
       }
 
-      // Don't allow blocking compiles if inside a class initializer
+      // Don't allow blocking compiles if inside a class initializer or while performing class loading
       vframeStream vfst((JavaThread*) thread);
       for (; !vfst.at_end(); vfst.next()) {
-        if (vfst.method()->is_static_initializer()) {
+        if (vfst.method()->is_static_initializer() ||
+            (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
+             vfst.method()->name() == vmSymbols::loadClass_name())) {
           blocking = false;
           break;
         }
--- a/src/share/vm/compiler/compileBroker.hpp	Wed Mar 18 16:39:06 2015 +0100
+++ b/src/share/vm/compiler/compileBroker.hpp	Wed Mar 18 10:07:47 2015 -0700
@@ -129,6 +129,7 @@
 
   void         log_task(xmlStream* log);
   void         log_task_queued();
+  void         log_task_dequeued(const char* comment);
   void         log_task_start(CompileLog* log);
   void         log_task_done(CompileLog* log);
 };
--- a/src/share/vm/graal/graalCompiler.cpp	Wed Mar 18 16:39:06 2015 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Wed Mar 18 10:07:47 2015 -0700
@@ -65,6 +65,9 @@
 void GraalCompiler::bootstrap() {
   JavaThread* THREAD = JavaThread::current();
   _bootstrapping = true;
+  // Allow bootstrap to perform Graal compilations of itself
+  bool c1only = GraalCompileWithC1Only;
+  GraalCompileWithC1Only = false;
   ResourceMark rm;
   HandleMark hm;
   if (PrintBootstrap) {
@@ -105,6 +108,7 @@
   if (PrintBootstrap) {
     tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)", os::javaTimeMillis() - start, _methodsCompiled);
   }
+  GraalCompileWithC1Only = c1only;
   _bootstrapping = false;
 }
 
--- a/src/share/vm/graal/graalGlobals.hpp	Wed Mar 18 16:39:06 2015 +0100
+++ b/src/share/vm/graal/graalGlobals.hpp	Wed Mar 18 10:07:47 2015 -0700
@@ -82,6 +82,12 @@
   product(bool, GraalHProfEnabled, false,                                   \
           "Is Heap  Profiler enabled")                                      \
                                                                             \
+  product(bool, GraalCompileWithC1Only, true,                               \
+          "Only compile Graal classes with C1")                             \
+                                                                            \
+  product(bool, GraalCompileAppFirst, false,                                \
+          "Prioritize application compilations over Graal compilations")    \
+                                                                            \
   develop(bool, GraalUseFastLocking, true,                                  \
           "Use fast inlined locking code")                                  \
                                                                             \
--- a/src/share/vm/runtime/advancedThresholdPolicy.cpp	Wed Mar 18 16:39:06 2015 +0100
+++ b/src/share/vm/runtime/advancedThresholdPolicy.cpp	Wed Mar 18 10:07:47 2015 -0700
@@ -157,6 +157,9 @@
 
 // Called with the queue locked and with at least one element
 CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) {
+#ifdef COMPILERGRAAL
+  CompileTask *max_non_graal_task = NULL;
+#endif
   CompileTask *max_task = NULL;
   Method* max_method = NULL;
   jlong t = os::javaTimeMillis();
@@ -175,6 +178,7 @@
         if (PrintTieredEvents) {
           print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level());
         }
+        task->log_task_dequeued("stale");
         CompileTaskWrapper ctw(task); // Frees the task
         compile_queue->remove(task);
         method->clear_queued_for_compilation();
@@ -188,9 +192,30 @@
         max_method = method;
       }
     }
+#ifdef COMPILERGRAAL
+    if (GraalCompileAppFirst && (task->comp_level() == CompLevel_full_optimization || !method->has_compiled_code()) &&
+        SystemDictionary::graal_loader() != NULL &&
+        method->method_holder()->class_loader() != SystemDictionary::graal_loader()) {
+      if (max_non_graal_task == NULL) {
+        max_non_graal_task = task;
+      } else {
+        // Select a method with a higher rate
+        if (compare_methods(method, max_non_graal_task->method())) {
+          max_non_graal_task = task;
+        }
+      }
+    }
+#endif
     task = next_task;
   }
 
+#ifdef COMPILERGRAAL
+  if (max_non_graal_task != NULL) {
+    max_task = max_non_graal_task;
+    max_method = max_task->method();
+  }
+#endif
+
   if (max_task->comp_level() == CompLevel_full_profile && TieredStopAtLevel > CompLevel_full_profile
       && is_method_profiled(max_method)) {
     max_task->set_comp_level(CompLevel_limited_profile);
--- a/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Wed Mar 18 16:39:06 2015 +0100
+++ b/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Wed Mar 18 10:07:47 2015 -0700
@@ -55,6 +55,13 @@
 // Determine if a given method is such a case.
 bool SimpleThresholdPolicy::is_trivial(Method* method) {
   if (method->is_accessor()) return true;
+#ifdef COMPILERGRAAL
+  if (TieredCompilation && GraalCompileWithC1Only &&
+      SystemDictionary::graal_loader() != NULL &&
+      method->method_holder()->class_loader() == SystemDictionary::graal_loader()) {
+    return true;
+  }
+#endif
   if (method->code() != NULL) {
     MethodData* mdo = method->method_data();
     if (mdo != NULL && mdo->num_loops() == 0 &&