changeset 19748:cb4d01e1c084

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 09 Mar 2015 23:07:28 +0100
parents 0493ae8a552d (current diff) 415975c5550b (diff)
children 095ddb9421d0
files
diffstat 15 files changed, 215 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Mon Mar 09 23:06:11 2015 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Mon Mar 09 23:07:28 2015 +0100
@@ -161,9 +161,9 @@
      * slot following a double word item. This should really be checked in FrameState itself but
      * because of Word type rewriting and alternative backends that can't be done.
      */
-    public boolean validateFormat() {
+    public boolean validateFormat(boolean derivedOk) {
         if (caller() != null) {
-            caller().validateFormat();
+            caller().validateFormat(derivedOk);
         }
         for (int i = 0; i < numLocals + numStack; i++) {
             if (values[i] != null) {
@@ -172,6 +172,7 @@
                     assert values.length > i + 1 : String.format("missing second word %s", this);
                     assert values[i + 1] == null || values[i + 1].getKind() == Kind.Illegal : this;
                 }
+                assert derivedOk || ValueUtil.isIllegal(values[i]) || !values[i].getLIRKind().isDerivedReference() : "Unexpected derived value: " + values[i];
             }
         }
         return true;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConcreteSubtypeTest.java	Mon Mar 09 23:07:28 2015 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, 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.oracle.graal.compiler.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.Assumptions.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Ensure that abstract classes with a single implementor are properly optimized and that loading a
+ * subclass below the leaf type triggers invalidation.
+ */
+public class ConcreteSubtypeTest extends GraalCompilerAssumptionsTest {
+    abstract static class AbstractBase {
+        abstract void check();
+    }
+
+    static class Subclass extends AbstractBase {
+        @Override
+        public void check() {
+            throw new InternalError();
+        }
+    }
+
+    static class SubSubclass extends Subclass {
+        @Override
+        public void check() {
+        }
+    }
+
+    public void callAbstractType(AbstractBase object) {
+        object.check();
+    }
+
+    @Override
+    protected void checkGraph(Assumption expectedAssumption, StructuredGraph graph) {
+        super.checkGraph(expectedAssumption, graph);
+        assertTrue(graph.isTrivial());
+    }
+
+    /**
+     * Test that {@link #callAbstractType} gets compiled into an empty method with a
+     * {@link ConcreteSubtype} assumption on {@link AbstractBase} and {@link Subclass}. Then ensures
+     * that loading and initialization of {@link SubSubclass} causes the compiled method to be
+     * invalidated.
+     */
+    @Test
+    public void testLeafAbstractType() {
+        testAssumptionInvalidate("callAbstractType", new ConcreteSubtype(resolveAndInitialize(AbstractBase.class), resolveAndInitialize(Subclass.class)), "SubSubclass");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerAssumptionsTest.java	Mon Mar 09 23:07:28 2015 +0100
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, 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.oracle.graal.compiler.test;
+
+import static org.junit.Assert.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.Assumptions.Assumption;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+
+public abstract class GraalCompilerAssumptionsTest extends GraalCompilerTest {
+
+    public GraalCompilerAssumptionsTest() {
+        super();
+    }
+
+    public GraalCompilerAssumptionsTest(Class<? extends Architecture> arch) {
+        super(arch);
+    }
+
+    protected void testAssumptionInvalidate(String methodName, Assumption expected, String classToLoad) {
+        testAssumption(methodName, expected, classToLoad, true);
+    }
+
+    /**
+     * Checks the behavior of class loading on {@link Assumption invalidation}. {@code methodName}
+     * is compiled and the resulting graph is checked for {@code expectedAssumption}. The code is
+     * installed and optionally {@code classToLoad} is loaded. The class is assumed to be an inner
+     * class of the test class and the name of the class to load is constructed relative to that.
+     *
+     * @param methodName the method to compile
+     * @param expectedAssumption expected {@link Assumption} instance to find in graph
+     * @param classToLoad an optional class to load to trigger an invalidation check
+     * @param willInvalidate true if loading {@code classToLoad} should invalidate the method
+     */
+    protected void testAssumption(String methodName, Assumption expectedAssumption, String classToLoad, boolean willInvalidate) {
+        ResolvedJavaMethod javaMethod = getResolvedJavaMethod(methodName);
+
+        StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.YES);
+        assertTrue(!graph.getAssumptions().isEmpty());
+        checkGraph(expectedAssumption, graph);
+
+        CompilationResult compilationResult = compile(javaMethod, graph);
+        final InstalledCode installedCode = getProviders().getCodeCache().setDefaultMethod(javaMethod, compilationResult);
+        assertTrue(installedCode.isValid());
+        if (classToLoad != null) {
+            String fullName = getClass().getName() + "$" + classToLoad;
+            try {
+                Class.forName(fullName);
+            } catch (ClassNotFoundException e) {
+                assertFalse(String.format("Can't find class %s", fullName), true);
+            }
+            assertTrue(!willInvalidate == installedCode.isValid());
+        }
+    }
+
+    protected void checkGraph(Assumption expectedAssumption, StructuredGraph graph) {
+        boolean found = false;
+        for (Assumption a : graph.getAssumptions()) {
+            if (expectedAssumption.equals(a)) {
+                found = true;
+            }
+        }
+        assertTrue(String.format("Can't find assumption %s", expectedAssumption), found);
+    }
+
+    /**
+     * Converts a {@link Class} to an initialized {@link ResolvedJavaType}.
+     */
+    protected ResolvedJavaType resolveAndInitialize(Class<?> clazz) {
+        ResolvedJavaType type = getMetaAccess().lookupJavaType(clazz);
+        type.initialize();
+        return type;
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Mar 09 23:06:11 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Mar 09 23:07:28 2015 +0100
@@ -113,7 +113,7 @@
         }
         objectStates.clear();
 
-        assert frame.validateFormat();
+        assert frame.validateFormat(false);
         return newLIRFrameState(exceptionEdge, frame, virtualObjectsArray);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java	Mon Mar 09 23:06:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java	Mon Mar 09 23:07:28 2015 +0100
@@ -115,7 +115,7 @@
                 Infopoint info = (Infopoint) site;
                 if (info.debugInfo != null) {
                     BytecodeFrame frame = info.debugInfo.frame();
-                    assert frame == null || frame.validateFormat();
+                    assert frame == null || frame.validateFormat(false);
                 }
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Mar 09 23:06:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Mar 09 23:07:28 2015 +0100
@@ -739,7 +739,6 @@
     @HotSpotVMFlag(name = "VerifyOops") @Stable public boolean verifyOops;
     @HotSpotVMFlag(name = "CITime") @Stable public boolean ciTime;
     @HotSpotVMFlag(name = "CITimeEach") @Stable public boolean ciTimeEach;
-    @HotSpotVMFlag(name = "CompileThreshold") @Stable public long compileThreshold;
     @HotSpotVMFlag(name = "CompileTheWorldStartAt", optional = true) @Stable public int compileTheWorldStartAt;
     @HotSpotVMFlag(name = "CompileTheWorldStopAt", optional = true) @Stable public int compileTheWorldStopAt;
     @HotSpotVMFlag(name = "DontCompileHugeMethods") @Stable public boolean dontCompileHugeMethods;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Mar 09 23:06:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Mar 09 23:07:28 2015 +0100
@@ -83,7 +83,7 @@
 
         assert target == providers.getCodeCache().getTarget();
         checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(providers, target);
-        instanceofSnippets = new InstanceOfSnippets.Templates(providers, target, config.compileThreshold);
+        instanceofSnippets = new InstanceOfSnippets.Templates(providers, target);
         newObjectSnippets = new NewObjectSnippets.Templates(providers, target);
         monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking);
         writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CRC32Substitutions.java	Mon Mar 09 23:06:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CRC32Substitutions.java	Mon Mar 09 23:07:28 2015 +0100
@@ -44,14 +44,17 @@
 
     public static class Guard implements SubstitutionGuard {
 
-        private HotSpotVMConfig config;
+        @SuppressWarnings("unused") private HotSpotVMConfig config;
 
         public Guard(HotSpotVMConfig config) {
             this.config = config;
         }
 
         public boolean execute() {
-            return config.useCRC32Intrinsics;
+            /*
+             * Disabled until MethodSubstitutions are compiled like snipppets.
+             */
+            return false; // return config.useCRC32Intrinsics;
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Mar 09 23:06:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Mar 09 23:07:28 2015 +0100
@@ -60,33 +60,9 @@
  */
 public class InstanceOfSnippets implements Snippets {
 
-    private static final double COMPILED_VS_INTERPRETER_SPEEDUP = 50;
-    private static final double INSTANCEOF_DEOPT_SPEEDUP = 1.01; // generous 1% speedup
-
-    private static final int DEOPT_THRESHOLD_FACTOR = (int) (COMPILED_VS_INTERPRETER_SPEEDUP / (INSTANCEOF_DEOPT_SPEEDUP - 1.0));
-
     /**
-     * Gets the minimum required probability of a profiled instanceof hitting one the profiled types
-     * for use of the {@linkplain #instanceofWithProfile deoptimizing} snippet. The value is
-     * computed to be an order of greater than the configured compilation threshold by a
-     * {@linkplain #DEOPT_THRESHOLD_FACTOR factor}.
-     *
-     * <p>
-     * This factor is such that the additional executions we get from using the deoptimizing snippet
-     * (({@linkplain #INSTANCEOF_DEOPT_SPEEDUP speedup} - 1) / probability threshold) is greater
-     * than the time lost during re-interpretation ({@linkplain #COMPILED_VS_INTERPRETER_SPEEDUP
-     * compiled code speedup} &times compilation threshold).
-     * </p>
-     */
-    public static double hintHitProbabilityThresholdForDeoptimizingSnippet(long compilationThreshold) {
-        return 1.0D - (1.0D / (compilationThreshold * DEOPT_THRESHOLD_FACTOR));
-    }
-
-    /**
-     * A test against a set of hints derived from a profile with very close to 100% precise coverage
-     * of seen types. This snippet deoptimizes on hint miss paths.
-     *
-     * @see #hintHitProbabilityThresholdForDeoptimizingSnippet(long)
+     * A test against a set of hints derived from a profile with 100% precise coverage of seen
+     * types. This snippet deoptimizes on hint miss paths.
      */
     @Snippet
     public static Object instanceofWithProfile(Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue,
@@ -243,11 +219,9 @@
         private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary");
         private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic");
         private final SnippetInfo isAssignableFrom = snippet(InstanceOfSnippets.class, "isAssignableFrom");
-        private final long compilationThreshold;
 
-        public Templates(HotSpotProviders providers, TargetDescription target, long compilationThreshold) {
+        public Templates(HotSpotProviders providers, TargetDescription target) {
             super(providers, providers.getSnippetReflection(), target);
-            this.compilationThreshold = compilationThreshold;
         }
 
         @Override
@@ -263,7 +237,7 @@
                 Arguments args;
 
                 StructuredGraph graph = instanceOf.graph();
-                if (hintInfo.hintHitProbability >= hintHitProbabilityThresholdForDeoptimizingSnippet(compilationThreshold) && hintInfo.exact == null) {
+                if (hintInfo.hintHitProbability >= 1.0 && hintInfo.exact == null) {
                     Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph);
                     args = new Arguments(instanceofWithProfile, graph.getGuardsStage(), tool.getLoweringStage());
                     args.add("object", object);
@@ -288,7 +262,7 @@
                 }
                 args.add("trueValue", replacer.trueValue);
                 args.add("falseValue", replacer.falseValue);
-                if (hintInfo.hintHitProbability >= hintHitProbabilityThresholdForDeoptimizingSnippet(compilationThreshold) && hintInfo.exact == null) {
+                if (hintInfo.hintHitProbability >= 1.0 && hintInfo.exact == null) {
                     args.addConst("nullSeen", hintInfo.profile.getNullSeen() != TriState.FALSE);
                 }
                 return args;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Mar 09 23:06:11 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Mar 09 23:07:28 2015 +0100
@@ -534,4 +534,12 @@
     public Set<ResolvedJavaMethod> getInlinedMethods() {
         return inlinedMethods;
     }
+
+    /**
+     *
+     * @return true if the graph contains only a {@link StartNode} and {@link ReturnNode}
+     */
+    public boolean isTrivial() {
+        return !(start.next() instanceof ReturnNode);
+    }
 }
--- a/mx/mx_graal.py	Mon Mar 09 23:06:11 2015 +0100
+++ b/mx/mx_graal.py	Mon Mar 09 23:07:28 2015 +0100
@@ -940,8 +940,7 @@
             # This removes the need to unzip the *.diz files before debugging in gdb
             setMakeVar('ZIP_DEBUGINFO_FILES', '0', env=env)
 
-            # Clear these 2 variables as having them set can cause very confusing build problems
-            env.pop('LD_LIBRARY_PATH', None)
+            # Clear this variable as having it set can cause very confusing build problems
             env.pop('CLASSPATH', None)
 
             # Issue an env prefix that can be used to run the make on the command line
--- a/src/cpu/x86/vm/compiledIC_x86.cpp	Mon Mar 09 23:06:11 2015 +0100
+++ b/src/cpu/x86/vm/compiledIC_x86.cpp	Mon Mar 09 23:07:28 2015 +0100
@@ -135,10 +135,15 @@
   NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
   NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
 
-  assert(method_holder->data() == 0 || method_holder->data() == (intptr_t)callee(),
+#ifdef ASSERT
+  // read the value once
+  intptr_t data = method_holder->data();
+  address destination = jump->jump_destination();
+  assert(data == 0 || data == (intptr_t)callee(),
          "a) MT-unsafe modification of inline cache");
-  assert(jump->jump_destination() == (address)-1 || jump->jump_destination() == entry,
+  assert(destination == (address)-1 || destination == entry,
          "b) MT-unsafe modification of inline cache");
+#endif
 
   // Update stub.
   method_holder->set_data((intptr_t)callee());
--- a/src/share/vm/code/nmethod.cpp	Mon Mar 09 23:06:11 2015 +0100
+++ b/src/share/vm/code/nmethod.cpp	Mon Mar 09 23:07:28 2015 +0100
@@ -856,7 +856,8 @@
     CodeCache::commit(this);
   }
 
-  if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
+  bool printnmethods = PrintNMethods || PrintNMethodsAtLevel == _comp_level;
+  if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
     ttyLocker ttyl;  // keep the following output all in one block
     // This output goes directly to the tty, not the compiler log.
     // To enable tools to match it up with the compilation activity,
@@ -870,7 +871,7 @@
     // print the header part first
     print();
     // then print the requested information
-    if (PrintNMethods) {
+    if (printnmethods) {
       print_code();
     }
     if (PrintRelocations) {
@@ -1014,7 +1015,7 @@
            " entry points must be same for static methods and vice versa");
   }
 
-  bool printnmethods = PrintNMethods
+  bool printnmethods = PrintNMethods || PrintNMethodsAtLevel == _comp_level
     || CompilerOracle::should_print(_method)
     || CompilerOracle::has_option_string(_method, "PrintNMethods");
   if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
@@ -1105,13 +1106,13 @@
       oop_maps()->print();
     }
   }
-  if (PrintDebugInfo) {
+  if (PrintDebugInfo || CompilerOracle::has_option_string(_method, "PrintDebugInfo")) {
     print_scopes();
   }
-  if (PrintRelocations) {
+  if (PrintRelocations || CompilerOracle::has_option_string(_method, "PrintRelocations")) {
     print_relocations();
   }
-  if (PrintDependencies) {
+  if (PrintDependencies || CompilerOracle::has_option_string(_method, "PrintDependencies")) {
     print_dependencies();
   }
   if (PrintExceptionHandlers) {
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Mon Mar 09 23:06:11 2015 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Mon Mar 09 23:07:28 2015 +0100
@@ -212,6 +212,7 @@
   oop lirKind = AbstractValue::lirKind(value);
   oop platformKind = LIRKind::platformKind(lirKind);
   jint referenceMask = LIRKind::referenceMask(lirKind);
+  assert(referenceMask != -1, "derived pointers are not allowed");
   assert(referenceMask == 0 || referenceMask == 1, "unexpected referenceMask");
   bool reference = referenceMask == 1;
 
@@ -660,9 +661,8 @@
   if (context != subtype) {
     assert(context->is_abstract(), "");
     _dependencies->assert_abstract_with_unique_concrete_subtype(context, subtype);
-  } else {
-    _dependencies->assert_leaf_type(subtype);
   }
+  _dependencies->assert_leaf_type(subtype);
 }
 
 void CodeInstaller::assumption_ConcreteMethod(Handle assumption) {
--- a/src/share/vm/runtime/globals.hpp	Mon Mar 09 23:06:11 2015 +0100
+++ b/src/share/vm/runtime/globals.hpp	Mon Mar 09 23:07:28 2015 +0100
@@ -993,6 +993,9 @@
   diagnostic(bool, PrintNMethods, false,                                    \
           "Print assembly code for nmethods when generated")                \
                                                                             \
+  diagnostic(intx, PrintNMethodsAtLevel, -1,                                \
+          "Only print code for nmethods at the given compilation level")    \
+                                                                            \
   diagnostic(bool, PrintNativeNMethods, false,                              \
           "Print assembly code for native nmethods when generated")         \
                                                                             \