# HG changeset patch # User Lukas Stadler # Date 1370699079 -7200 # Node ID b4325bc087c4c80b111e649839d6ec85949c90f2 # Parent f8a4c5011a10495dd51aded5c1cd96203859cc78# Parent 2194b25ff11169a057d85543b22bc2ad3d6bac62 Merge diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java Sat Jun 08 15:44:39 2013 +0200 @@ -32,28 +32,39 @@ * it's highly likely nothing will change the likelihood of the deoptimization happening again. * For example, a compiled array allocation where the size is negative. */ - None, + None(false), /** * Do not invalidate the machine code, but schedule a recompilation if this deoptimization is * triggered too often. */ - RecompileIfTooManyDeopts, + RecompileIfTooManyDeopts(true), /** * Invalidate the machine code and reset the profiling information. */ - InvalidateReprofile, + InvalidateReprofile(true), /** * Invalidate the machine code and immediately schedule a recompilation. This is typically used * when deoptimizing to resolve an unresolved symbol in which case extra profiling is not * required to determine that the deoptimization will not re-occur. */ - InvalidateRecompile, + InvalidateRecompile(true), /** * Invalidate the machine code and stop compiling the outermost method of this compilation. */ - InvalidateStopCompiling; + InvalidateStopCompiling(true); + + private final boolean invalidatesCompilation; + + private DeoptimizationAction(boolean invalidatesCompilation) { + this.invalidatesCompilation = invalidatesCompilation; + } + + public boolean doesInvalidateCompilation() { + return invalidatesCompilation; + } + } diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java Sat Jun 08 15:44:39 2013 +0200 @@ -25,10 +25,14 @@ import java.io.*; /** - * This profile object represents a certain set of profiling information at a specific BCI. The - * precision of the supplied values may vary, but a runtime that provides this information should be - * aware that it will be used to guide performance-critical decisions like speculative inlining, - * etc. + * This object holds probability information for a set of items that were profiled at a specific + * BCI. The precision of the supplied values may vary, but a runtime that provides this information + * should be aware that it will be used to guide performance-critical decisions like speculative + * inlining, etc. + * + * @param a subclass of AbstractProfiledItem + * @param the class of the items that are profiled at the specific BCI and for which + * probabilities are stored. E.g., a ResolvedJavaType or a ResolvedJavaMethod. */ public abstract class AbstractJavaProfile, U> implements Serializable { diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java Sat Jun 08 15:44:39 2013 +0200 @@ -87,6 +87,11 @@ } @Override + public boolean isMature() { + return false; + } + + @Override public String toString() { return "BaseProfilingInfo<" + MetaUtil.profileToString(this, null, "; ") + ">"; } diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java Sat Jun 08 15:44:39 2013 +0200 @@ -112,4 +112,12 @@ */ int getDeoptimizationCount(DeoptimizationReason reason); + /** + * Returns true if the profiling information can be assumed as sufficiently accurate. + * + * @return true if the profiling information was recorded often enough mature enough, false + * otherwise. + */ + boolean isMature(); + } diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java Sat Jun 08 15:44:39 2013 +0200 @@ -128,7 +128,11 @@ } public static Serializable checkCastSnippet(Object obj) { - return (Serializable) obj; + try { + return (Serializable) obj; + } catch (ClassCastException e) { + return null; + } } @Test @@ -250,19 +254,30 @@ @Test public void testNullSeen() { - ProfilingInfo info = profile("instanceOfSnippet", 1); + testNullSeen("instanceOfSnippet"); + testNullSeen("checkCastSnippet"); + } + + private void testNullSeen(String snippet) { + ProfilingInfo info = profile(snippet, 1); Assert.assertEquals(TriState.FALSE, info.getNullSeen(1)); - continueProfiling("instanceOfSnippet", "ABC"); + continueProfiling(snippet, "ABC"); Assert.assertEquals(TriState.FALSE, info.getNullSeen(1)); - continueProfiling("instanceOfSnippet", (Object) null); + continueProfiling(snippet, new Object()); + Assert.assertEquals(TriState.FALSE, info.getNullSeen(1)); + + continueProfiling(snippet, (Object) null); Assert.assertEquals(TriState.TRUE, info.getNullSeen(1)); - continueProfiling("instanceOfSnippet", 0.0); + continueProfiling(snippet, 0.0); Assert.assertEquals(TriState.TRUE, info.getNullSeen(1)); - resetProfile("instanceOfSnippet"); + continueProfiling(snippet, new Object()); + Assert.assertEquals(TriState.TRUE, info.getNullSeen(1)); + + resetProfile(snippet); Assert.assertEquals(TriState.FALSE, info.getNullSeen(1)); } diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java Sat Jun 08 15:44:39 2013 +0200 @@ -25,6 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.sparc.*; /** * SPARC specific implementation of {@link HotSpotGraalRuntime}. @@ -44,10 +45,15 @@ return graalRuntime(); } + protected static Architecture createArchitecture() { + return new SPARC(); + } + @Override protected TargetDescription createTarget() { - // SPARC: Create target description. - throw new InternalError("NYI"); + final int stackFrameAlignment = 16; + final int implicitNullCheckLimit = 4096; + return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, true); } @Override diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Sat Jun 08 15:44:39 2013 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.hotspot.meta.*; @@ -87,9 +88,11 @@ runtime.compilerToVm = toVM; } + private static final String DEFAULT_GRAAL_RUNTIME = "basic"; + // @formatter:off @Option(help = "The runtime configuration to use") - private static final OptionValue GraalRuntime = new OptionValue<>("basic"); + private static final OptionValue GraalRuntime = new OptionValue<>(DEFAULT_GRAAL_RUNTIME); // @formatter:on protected static HotSpotGraalRuntimeFactory findFactory(String architecture) { @@ -98,6 +101,11 @@ return factory; } } + if (!DEFAULT_GRAAL_RUNTIME.equals(GraalRuntime.getValue())) { + // Fail fast if a non-default value for GraalRuntime was specified + // and the corresponding factory is not available + throw new GraalInternalError("Specified runtime \"%s\" not available for the %s architecture", GraalRuntime.getValue(), architecture); + } return null; } diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Sat Jun 08 15:44:39 2013 +0200 @@ -23,16 +23,28 @@ package com.oracle.graal.hotspot; +import static java.nio.file.Files.*; + +import java.io.*; +import java.nio.charset.*; +import java.nio.file.*; import java.util.*; import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.options.*; +/** + * Called from {@code graalCompiler.cpp} to parse any Graal specific options. Such options are + * (currently) distinguished by a {@code "-G:"} prefix. + */ public class HotSpotOptions { private static final Map options = new HashMap<>(); - static { + /** + * Initializes {@link #options} from {@link Options} services. + */ + private static void initializeOptions() { ServiceLoader sl = ServiceLoader.loadInstalled(Options.class); for (Options opts : sl) { for (OptionDescriptor desc : opts) { @@ -45,6 +57,38 @@ } } + /** + * Loads default option value overrides from a {@code graal.options} file if it exists. Each + * line in this file starts with {@code "#"} and is ignored or must have the format of a Graal + * command line option without the leading {@code "-G:"} prefix. These option value are set + * prior to processing of any Graal options present on the command line. + */ + private static void loadOptionOverrides() throws InternalError { + String javaHome = System.getProperty("java.home"); + Path graalDotOptions = Paths.get(javaHome, "lib", "graal.options"); + if (!exists(graalDotOptions)) { + graalDotOptions = Paths.get(javaHome, "jre", "lib", "graal.options"); + } + if (exists(graalDotOptions)) { + try { + for (String line : Files.readAllLines(graalDotOptions, Charset.defaultCharset())) { + if (!line.startsWith("#")) { + if (!setOption(line)) { + throw new InternalError("Invalid option \"" + line + "\" specified in " + graalDotOptions); + } + } + } + } catch (IOException e) { + throw (InternalError) new InternalError().initCause(e); + } + } + } + + static { + initializeOptions(); + loadOptionOverrides(); + } + // Called from VM code public static boolean setOption(String option) { if (option.length() == 0) { diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Sat Jun 08 15:44:39 2013 +0200 @@ -384,6 +384,8 @@ public int typeProfileWidth; public int methodProfileWidth; + public int interpreterProfilingThreshold; + public long inlineCacheMissStub; public long handleDeoptStub; public long uncommonTrapStub; diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java Sat Jun 08 15:44:39 2013 +0200 @@ -127,13 +127,15 @@ } @Override - public void put(StructuredGraph graph) { + public void put(StructuredGraph graph, boolean hasMatureProfilingInfo) { assert graph.method() != null; - cachedGraphIds.put(graph.graphId(), new WeakReference<>(graph.method())); - graph.method().getCompilerStorage().put(this, graph); + if (hasMatureProfilingInfo) { + cachedGraphIds.put(graph.graphId(), new WeakReference<>(graph.method())); + graph.method().getCompilerStorage().put(this, graph); - if (PrintGraphCache.getValue()) { - putCounter++; + if (PrintGraphCache.getValue()) { + putCounter++; + } } } diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Sat Jun 08 15:44:39 2013 +0200 @@ -24,7 +24,6 @@ import static com.oracle.graal.graph.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; @@ -376,7 +375,7 @@ protected abstract long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position); private static JavaTypeProfile createTypeProfile(TriState nullSeen, ResolvedJavaType[] types, long[] counts, long totalCount, int entries) { - if (entries <= 0 || totalCount < MatureExecutionsTypeProfile.getValue()) { + if (entries <= 0 || totalCount <= 0) { return null; } @@ -484,7 +483,7 @@ } private static JavaMethodProfile createMethodProfile(ResolvedJavaMethod[] methods, long[] counts, long totalCount, int entries) { - if (entries <= 0 || totalCount < MatureExecutionsTypeProfile.getValue()) { + if (entries <= 0 || totalCount <= 0) { return null; } @@ -540,11 +539,7 @@ long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET); long total = takenCount + notTakenCount; - if (total < MatureExecutionsBranch.getValue()) { - return -1; - } else { - return takenCount / (double) total; - } + return total <= 0 ? -1 : takenCount / (double) total; } @Override @@ -607,7 +602,7 @@ result[i - 1] = count; } - if (totalCount < MatureExecutionsPerSwitchCase.getValue() * length) { + if (totalCount <= 0) { return null; } else { for (int i = 0; i < length; i++) { diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java Sat Jun 08 15:44:39 2013 +0200 @@ -22,32 +22,36 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.phases.*; public final class HotSpotProfilingInfo extends CompilerObject implements ProfilingInfo { private static final long serialVersionUID = -8307682725047864875L; private static final DebugMetric metricInsufficentSpace = Debug.metric("InsufficientSpaceForProfilingData"); + private final HotSpotMethodData methodData; + private final HotSpotResolvedJavaMethod method; + private int position; private int hintPosition; private int hintBCI; private HotSpotMethodDataAccessor dataAccessor; - private HotSpotMethodData methodData; - private final int codeSize; - public HotSpotProfilingInfo(HotSpotMethodData methodData, int codeSize) { + public HotSpotProfilingInfo(HotSpotMethodData methodData, HotSpotResolvedJavaMethod method) { this.methodData = methodData; - this.codeSize = codeSize; + this.method = method; hintPosition = 0; hintBCI = -1; } @Override public int getCodeSize() { - return codeSize; + return method.getCodeSize(); } @Override @@ -158,6 +162,11 @@ } @Override + public boolean isMature() { + return method.invocationCount() >= graalRuntime().getConfig().interpreterProfilingThreshold + GraalOptions.MatureProfilingInformationThreshold.getValue(); + } + + @Override public String toString() { return "HotSpotProfilingInfo<" + MetaUtil.profileToString(this, null, "; ") + ">"; } diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Sat Jun 08 15:44:39 2013 +0200 @@ -288,7 +288,7 @@ // case of a deoptimization. info = DefaultProfilingInfo.get(TriState.FALSE); } else { - info = new HotSpotProfilingInfo(methodData, codeSize); + info = new HotSpotProfilingInfo(methodData, this); } return info; } diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sat Jun 08 15:44:39 2013 +0200 @@ -919,7 +919,7 @@ } BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode()); BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode()); - append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.1)); + append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.01)); lastInstr = falseSucc; if (OmitHotExceptionStacktrace.getValue()) { @@ -943,7 +943,7 @@ private void emitBoundsCheck(ValueNode index, ValueNode length) { BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode()); BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode()); - append(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.9)); + append(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.99)); lastInstr = trueSucc; if (OmitHotExceptionStacktrace.getValue()) { diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InlineableElement.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InlineableElement.java Sat Jun 08 15:43:48 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2013, 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.nodes; - -public interface InlineableElement { - - int getNodeCount(); - - Iterable getInvokes(); -} diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Sat Jun 08 15:44:39 2013 +0200 @@ -35,7 +35,7 @@ * A graph that contains at least one distinguished node : the {@link #start() start} node. This * node is the start of the control flow of the graph. */ -public class StructuredGraph extends Graph implements InlineableElement { +public class StructuredGraph extends Graph { public static final int INVOCATION_ENTRY_BCI = -1; public static final long INVALID_GRAPH_ID = -1; diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Sat Jun 08 15:44:39 2013 +0200 @@ -56,9 +56,12 @@ } private boolean assertProbabilities() { + double total = 0; for (double d : keyProbabilities) { + total += d; assert d >= 0.0 : "Cannot have negative probabilities in switch node: " + d; } + assert total > 0.999 && total < 1.001; return true; } @@ -73,6 +76,32 @@ return sum; } + public void setProbability(Node successor, double value) { + double changeInProbability = 0; + int nonZeroProbabilityCases = 0; + for (int i = 0; i < keySuccessors.length; i++) { + if (successors.get(keySuccessors[i]) == successor) { + changeInProbability += keyProbabilities[i] - value; + keyProbabilities[i] = value; + } else if (keyProbabilities[i] > 0) { + nonZeroProbabilityCases++; + } + } + + if (nonZeroProbabilityCases > 0) { + double changePerEntry = changeInProbability / nonZeroProbabilityCases; + if (changePerEntry != 0) { + for (int i = 0; i < keyProbabilities.length; i++) { + if (keyProbabilities[i] > 0) { + keyProbabilities[i] = keyProbabilities[i] + changePerEntry; + } + } + } + } + + assertProbabilities(); + } + public ValueNode value() { return value; } diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java Sat Jun 08 15:44:39 2013 +0200 @@ -27,7 +27,7 @@ public interface GraphCache { - void put(StructuredGraph graph); + void put(StructuredGraph graph, boolean hasMatureProfilingInfo); StructuredGraph get(ResolvedJavaMethod method); diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Sat Jun 08 15:44:39 2013 +0200 @@ -159,7 +159,7 @@ String help = option.help; String location = pkg + "." + option.declaringClass + "." + option.field.getSimpleName(); String comma = i == info.options.size() - 1 ? "" : ","; - out.printf(" new %s(\"%s\", %s.class, \"%s\", \"%s\", %s)%s%n", OptionDescriptor.class.getSimpleName(), name, type, help, location, optionValue, comma); + out.printf(" new %s(\"%s\", %s.class, \"%s\", \"%s\", %s)%s\n", OptionDescriptor.class.getSimpleName(), name, type, help, location, optionValue, comma); i++; } out.println(" );"); diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Sat Jun 08 15:44:39 2013 +0200 @@ -40,7 +40,9 @@ import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; import com.oracle.graal.phases.common.InliningUtil.InlineInfo; +import com.oracle.graal.phases.common.InliningUtil.Inlineable; import com.oracle.graal.phases.common.InliningUtil.InlineableMacroNode; +import com.oracle.graal.phases.common.InliningUtil.InlineableGraph; import com.oracle.graal.phases.common.InliningUtil.InliningPolicy; import com.oracle.graal.phases.graph.*; @@ -154,10 +156,10 @@ MethodInvocation calleeInvocation = data.pushInvocation(info, parentAssumptions, invokeProbability, invokeRelevance); for (int i = 0; i < info.numberOfMethods(); i++) { - InlineableElement elem = getInlineableElement(info.methodAt(i), info.invoke(), calleeInvocation.assumptions()); + Inlineable elem = getInlineableElement(info.methodAt(i), info.invoke(), calleeInvocation.assumptions()); info.setInlinableElement(i, elem); - if (elem instanceof StructuredGraph) { - data.pushGraph((StructuredGraph) elem, invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i)); + if (elem instanceof InlineableGraph) { + data.pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i)); } else { assert elem instanceof InlineableMacroNode; data.pushDummyGraph(); @@ -215,12 +217,12 @@ } } - private InlineableElement getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, Assumptions assumptions) { + private Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, Assumptions assumptions) { Class macroNodeClass = InliningUtil.getMacroNodeClass(replacements, method); if (macroNodeClass != null) { return new InlineableMacroNode(macroNodeClass); } else { - return buildGraph(method, invoke, assumptions); + return new InlineableGraph(buildGraph(method, invoke, assumptions)); } } @@ -296,6 +298,8 @@ } private StructuredGraph parseBytecodes(StructuredGraph newGraph, Assumptions assumptions) { + boolean hasMatureProfilingInfo = newGraph.method().getProfilingInfo().isMature(); + if (plan != null) { plan.runPhases(PhasePosition.AFTER_PARSING, newGraph); } @@ -311,7 +315,7 @@ new CullFrameStatesPhase().apply(newGraph); } if (CacheGraphs.getValue() && cache != null) { - cache.put(newGraph.copy()); + cache.put(newGraph.copy(), hasMatureProfilingInfo); } return newGraph; } @@ -387,7 +391,7 @@ protected static int determineNodeCount(InlineInfo info) { int nodes = 0; for (int i = 0; i < info.numberOfMethods(); i++) { - InlineableElement elem = info.inlineableElementAt(i); + Inlineable elem = info.inlineableElementAt(i); if (elem != null) { nodes += elem.getNodeCount(); } @@ -398,10 +402,10 @@ protected static double determineInvokeProbability(InlineInfo info) { double invokeProbability = 0; for (int i = 0; i < info.numberOfMethods(); i++) { - InlineableElement callee = info.inlineableElementAt(i); + Inlineable callee = info.inlineableElementAt(i); Iterable invokes = callee.getInvokes(); if (invokes.iterator().hasNext()) { - NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure((StructuredGraph) callee).apply(); + NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(((InlineableGraph) callee).getGraph()).apply(); for (Invoke invoke : invokes) { invokeProbability += nodeProbabilities.get(invoke.asNode()); } @@ -433,15 +437,16 @@ } double inliningBonus = getInliningBonus(info); - + int nodes = determineNodeCount(info); int lowLevelGraphSize = previousLowLevelGraphSize(info); + if (SmallCompiledLowLevelGraphSize.getValue() > 0 && lowLevelGraphSize > SmallCompiledLowLevelGraphSize.getValue() * inliningBonus) { - return InliningUtil.logNotInlinedMethod(info, inliningDepth, "too large previous low-level graph: %d", lowLevelGraphSize); + return InliningUtil.logNotInlinedMethod(info, inliningDepth, "too large previous low-level graph (low-level-nodes: %d, relevance=%f, probability=%f, bonus=%f, nodes=%d)", + lowLevelGraphSize, relevance, probability, inliningBonus, nodes); } - int nodes = determineNodeCount(info); if (nodes < TrivialInliningSize.getValue() * inliningBonus) { - return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (nodes=%d)", nodes); + return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes); } /* @@ -452,16 +457,17 @@ */ double invokes = determineInvokeProbability(info); if (LimitInlinedInvokes.getValue() > 0 && fullyProcessed && invokes > LimitInlinedInvokes.getValue() * inliningBonus) { - return InliningUtil.logNotInlinedMethod(info, inliningDepth, "callee invoke probability is too high (%f)", invokes); + return InliningUtil.logNotInlinedMethod(info, inliningDepth, "callee invoke probability is too high (invokeP=%f, relevance=%f, probability=%f, bonus=%f, nodes=%d)", invokes, + relevance, probability, inliningBonus, nodes); } double maximumNodes = computeMaximumSize(relevance, (int) (MaximumInliningSize.getValue() * inliningBonus)); if (nodes <= maximumNodes) { - return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= max=%f)", relevance, probability, + return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus, nodes, maximumNodes); } - return InliningUtil.logNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > max=%f)", relevance, probability, inliningBonus, nodes, + return InliningUtil.logNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes); } } diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Sat Jun 08 15:44:39 2013 +0200 @@ -66,7 +66,37 @@ boolean isWorthInlining(InlineInfo info, int inliningDepth, double probability, double relevance, boolean fullyProcessed); } - public static class InlineableMacroNode implements InlineableElement { + public interface Inlineable { + + int getNodeCount(); + + Iterable getInvokes(); + } + + public static class InlineableGraph implements Inlineable { + + private final StructuredGraph graph; + + public InlineableGraph(StructuredGraph graph) { + this.graph = graph; + } + + @Override + public int getNodeCount() { + return graph.getNodeCount(); + } + + @Override + public Iterable getInvokes() { + return graph.getInvokes(); + } + + public StructuredGraph getGraph() { + return graph; + } + } + + public static class InlineableMacroNode implements Inlineable { private final Class macroNodeClass; @@ -238,13 +268,13 @@ ResolvedJavaMethod methodAt(int index); - InlineableElement inlineableElementAt(int index); + Inlineable inlineableElementAt(int index); double probabilityAt(int index); double relevanceAt(int index); - void setInlinableElement(int index, InlineableElement inlineableElement); + void setInlinableElement(int index, Inlineable inlineableElement); /** * Performs the inlining described by this object and returns the node that represents the @@ -277,10 +307,10 @@ return invoke; } - protected static void inline(Invoke invoke, ResolvedJavaMethod concrete, InlineableElement inlineable, Assumptions assumptions, boolean receiverNullCheck) { + protected static void inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, Assumptions assumptions, boolean receiverNullCheck) { StructuredGraph graph = invoke.asNode().graph(); - if (inlineable instanceof StructuredGraph) { - StructuredGraph calleeGraph = (StructuredGraph) inlineable; + if (inlineable instanceof InlineableGraph) { + StructuredGraph calleeGraph = ((InlineableGraph) inlineable).getGraph(); InliningUtil.inline(invoke, calleeGraph, receiverNullCheck); graph.getLeafGraphIds().add(calleeGraph.graphId()); @@ -331,7 +361,7 @@ private static class ExactInlineInfo extends AbstractInlineInfo { protected final ResolvedJavaMethod concrete; - private InlineableElement inlineableElement; + private Inlineable inlineableElement; public ExactInlineInfo(Invoke invoke, ResolvedJavaMethod concrete) { super(invoke); @@ -377,13 +407,13 @@ } @Override - public InlineableElement inlineableElementAt(int index) { + public Inlineable inlineableElementAt(int index) { assert index == 0; return inlineableElement; } @Override - public void setInlinableElement(int index, InlineableElement inlineableElement) { + public void setInlinableElement(int index, Inlineable inlineableElement) { assert index == 0; this.inlineableElement = inlineableElement; } @@ -398,7 +428,7 @@ private final ResolvedJavaMethod concrete; private final ResolvedJavaType type; - private InlineableElement inlineableElement; + private Inlineable inlineableElement; public TypeGuardInlineInfo(Invoke invoke, ResolvedJavaMethod concrete, ResolvedJavaType type) { super(invoke); @@ -418,7 +448,7 @@ } @Override - public InlineableElement inlineableElementAt(int index) { + public Inlineable inlineableElementAt(int index) { assert index == 0; return inlineableElement; } @@ -436,7 +466,7 @@ } @Override - public void setInlinableElement(int index, InlineableElement inlineableElement) { + public void setInlinableElement(int index, Inlineable inlineableElement) { assert index == 0; this.inlineableElement = inlineableElement; } @@ -491,7 +521,7 @@ private final ArrayList ptypes; private final ArrayList concretesProbabilities; private final double notRecordedTypeProbability; - private final InlineableElement[] inlineableElements; + private final Inlineable[] inlineableElements; public MultiTypeGuardInlineInfo(Invoke invoke, ArrayList concretes, ArrayList concretesProbabilities, ArrayList ptypes, ArrayList typesToConcretes, double notRecordedTypeProbability) { @@ -504,7 +534,7 @@ this.ptypes = ptypes; this.typesToConcretes = typesToConcretes; this.notRecordedTypeProbability = notRecordedTypeProbability; - this.inlineableElements = new InlineableElement[concretes.size()]; + this.inlineableElements = new Inlineable[concretes.size()]; this.methodProbabilities = computeMethodProbabilities(); this.maximumMethodProbability = maximumMethodProbability(); assert maximumMethodProbability > 0; @@ -540,7 +570,7 @@ } @Override - public InlineableElement inlineableElementAt(int index) { + public Inlineable inlineableElementAt(int index) { assert index >= 0 && index < concretes.size(); return inlineableElements[index]; } @@ -556,7 +586,7 @@ } @Override - public void setInlinableElement(int index, InlineableElement inlineableElement) { + public void setInlinableElement(int index, Inlineable inlineableElement) { assert index >= 0 && index < concretes.size(); inlineableElements[index] = inlineableElement; } @@ -907,16 +937,12 @@ @Override public void tryToDevirtualizeInvoke(MetaAccessProvider runtime, Assumptions assumptions) { if (hasSingleMethod()) { - tryToDevirtualizeSingleMethod(graph(), runtime); + devirtualizeWithTypeSwitch(graph(), InvokeKind.Special, concretes.get(0), runtime); } else { tryToDevirtualizeMultipleMethods(graph(), runtime); } } - private void tryToDevirtualizeSingleMethod(StructuredGraph graph, MetaAccessProvider runtime) { - devirtualizeWithTypeSwitch(graph, InvokeKind.Special, concretes.get(0), runtime); - } - private void tryToDevirtualizeMultipleMethods(StructuredGraph graph, MetaAccessProvider runtime) { MethodCallTargetNode methodCallTarget = (MethodCallTargetNode) invoke.callTarget(); if (methodCallTarget.invokeKind() == InvokeKind.Interface) { diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Sat Jun 08 15:44:39 2013 +0200 @@ -87,11 +87,7 @@ @Option(help = "") public static final OptionValue DeoptsToDisableOptimisticOptimization = new OptionValue<>(40); @Option(help = "") - public static final OptionValue MatureExecutionsBranch = new OptionValue<>(1); - @Option(help = "") - public static final OptionValue MatureExecutionsPerSwitchCase = new OptionValue<>(1); - @Option(help = "") - public static final OptionValue MatureExecutionsTypeProfile = new OptionValue<>(1); + public static final OptionValue MatureProfilingInformationThreshold = new OptionValue<>(100); // comilation queue @Option(help = "") diff -r f8a4c5011a10 -r b4325bc087c4 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Sat Jun 08 15:43:48 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Sat Jun 08 15:44:39 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.util.*; /** @@ -63,12 +64,104 @@ } public NodesToDoubles apply() { + adjustControlSplitProbabilities(); new PropagateProbability(graph.start()).apply(); computeLoopFactors(); new PropagateLoopFrequency(graph.start()).apply(); + assert verifyProbabilities(); return nodeProbabilities; } + /** + * Assume that paths with a DeoptimizeNode at their end are taken infrequently. + */ + private void adjustControlSplitProbabilities() { + HashSet result = new HashSet<>(); + NodeBitMap visitedNodes = new NodeBitMap(graph); + for (DeoptimizeNode n : graph.getNodes(DeoptimizeNode.class)) { + if (n.action().doesInvalidateCompilation()) { + findParentControlSplitNodes(result, n, visitedNodes); + } + } + + for (ControlSplitNode n : result) { + if (!allSuxVisited(n, visitedNodes)) { + modifyProbabilities(n, visitedNodes); + } + } + } + + private static void findParentControlSplitNodes(HashSet result, DeoptimizeNode n, NodeBitMap visitedNodes) { + ArrayDeque nodes = new ArrayDeque<>(); + nodes.push(n); + + Node currentNode; + do { + currentNode = nodes.pop(); + visitedNodes.mark(currentNode); + + for (Node pred : currentNode.cfgPredecessors()) { + FixedNode fixedPred = (FixedNode) pred; + if (allSuxVisited(fixedPred, visitedNodes) || fixedPred instanceof InvokeWithExceptionNode) { + nodes.push(fixedPred); + } else { + assert fixedPred instanceof ControlSplitNode : "only control splits can have more than one sux"; + result.add((ControlSplitNode) fixedPred); + } + } + } while (!nodes.isEmpty()); + } + + private static void modifyProbabilities(ControlSplitNode node, NodeBitMap visitedNodes) { + if (node instanceof IfNode) { + IfNode ifNode = (IfNode) node; + assert visitedNodes.isMarked(ifNode.falseSuccessor()) ^ visitedNodes.isMarked(ifNode.trueSuccessor()); + + if (visitedNodes.isMarked(ifNode.trueSuccessor())) { + if (ifNode.probability(ifNode.trueSuccessor()) > 0) { + ifNode.setTrueSuccessorProbability(0); + } + } else { + if (ifNode.probability(ifNode.trueSuccessor()) < 1) { + ifNode.setTrueSuccessorProbability(1); + } + } + } else if (node instanceof SwitchNode) { + SwitchNode switchNode = (SwitchNode) node; + for (Node sux : switchNode.successors()) { + if (visitedNodes.isMarked(sux)) { + switchNode.setProbability(sux, 0); + } + } + } else { + GraalInternalError.shouldNotReachHere(); + } + } + + private static boolean allSuxVisited(FixedNode fixedPred, NodeBitMap visitedNodes) { + for (Node sux : fixedPred.successors()) { + if (!visitedNodes.contains(sux)) { + return false; + } + } + return true; + } + + private boolean verifyProbabilities() { + if (doesNotAlwaysDeopt(graph)) { + for (DeoptimizeNode n : graph.getNodes(DeoptimizeNode.class)) { + if (n.action().doesInvalidateCompilation() && nodeProbabilities.get(n) > 0.01) { + throw new AssertionError(String.format("%s with reason %s and probability %f in graph %s", n, n.reason(), nodeProbabilities.get(n), graph)); + } + } + } + return true; + } + + private static boolean doesNotAlwaysDeopt(StructuredGraph graph) { + return graph.getNodes(ReturnNode.class).iterator().hasNext(); + } + private void computeLoopFactors() { for (LoopInfo info : loopInfos) { double frequency = info.loopFrequency(nodeProbabilities); diff -r f8a4c5011a10 -r b4325bc087c4 make/Makefile --- a/make/Makefile Sat Jun 08 15:43:48 2013 +0200 +++ b/make/Makefile Sat Jun 08 15:44:39 2013 +0200 @@ -516,6 +516,10 @@ $(EXPORT_JRE_LIB_DIR)/%.jar: $(SHARED_DIR)/%.jar $(install-file) +# Shared options files +$(EXPORT_JRE_LIB_DIR)/%.options: $(SHARED_DIR)/%.options + $(install-file) + # Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h) $(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/% $(install-file) diff -r f8a4c5011a10 -r b4325bc087c4 make/build-graal.xml --- a/make/build-graal.xml Sat Jun 08 15:43:48 2013 +0200 +++ b/make/build-graal.xml Sat Jun 08 15:44:39 2013 +0200 @@ -28,7 +28,7 @@ - + @@ -101,6 +101,14 @@ + + + + + + + + diff -r f8a4c5011a10 -r b4325bc087c4 make/solaris/makefiles/buildtree.make --- a/make/solaris/makefiles/buildtree.make Sat Jun 08 15:43:48 2013 +0200 +++ b/make/solaris/makefiles/buildtree.make Sat Jun 08 15:44:39 2013 +0200 @@ -229,7 +229,9 @@ echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \ - echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ + echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,altsrc,gpu/ptx) \\"; \ + echo "$(call gamma-path,commonsrc,gpu/ptx)"; \ echo; \ echo "Src_Dirs_I = \\"; \ echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \ @@ -244,8 +246,9 @@ echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(ARCH)/vm) \\"; \ echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ - echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \ - echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ + echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,altsrc,gpu) \\"; \ + echo "$(call gamma-path,commonsrc,gpu)"; \ [ -n "$(CFLAGS_BROWSE)" ] && \ echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \ [ -n "$(ENABLE_FULL_DEBUG_SYMBOLS)" ] && \ diff -r f8a4c5011a10 -r b4325bc087c4 make/solaris/makefiles/vm.make --- a/make/solaris/makefiles/vm.make Sat Jun 08 15:43:48 2013 +0200 +++ b/make/solaris/makefiles/vm.make Sat Jun 08 15:44:39 2013 +0200 @@ -194,7 +194,9 @@ COMPILER2_PATHS += $(GENERATED)/adfiles GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/graal) +GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/ptx) GRAAL_PATHS += $(HS_COMMON_SRC)/share/vm/graal +GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/ptx # Include dirs per type. Src_Dirs/CORE := $(CORE_PATHS) diff -r f8a4c5011a10 -r b4325bc087c4 mx/commands.py --- a/mx/commands.py Sat Jun 08 15:43:48 2013 +0200 +++ b/mx/commands.py Sat Jun 08 15:44:39 2013 +0200 @@ -232,6 +232,8 @@ machine = platform.uname()[4] if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']: return 'amd64' + if machine in ['sun4v']: + return 'sparc' if machine == 'i386' and mx.get_os() == 'darwin': try: # Support for Snow Leopard and earlier version of MacOSX @@ -343,6 +345,7 @@ def _installGraalJarInJdks(graalDist): graalJar = graalDist.path + graalOptions = join(_graal_home, 'graal.options') jdks = join(_graal_home, 'jdk' + str(mx.java().version)) if exists(jdks): for e in os.listdir(jdks): @@ -353,6 +356,9 @@ shutil.copyfile(graalJar, tmp) os.close(fd) shutil.move(tmp, join(jreLibDir, 'graal.jar')) + + if exists(graalOptions): + shutil.copy(graalOptions, join(jreLibDir, 'graal.options')) # run a command in the windows SDK Debug Shell def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo={}): @@ -458,7 +464,7 @@ out.element('property', {'name' : 'jar.dir', 'value' : '${shared.dir}'}) out.element('property', {'name' : 'jar.file', 'value' : '${jar.dir}/graal.jar'}) - out.element('target', {'name' : 'main', 'depends' : 'jar'}) + out.element('target', {'name' : 'main', 'depends' : 'options,jar'}) serviceMap = {}; def addService(service, provider): @@ -513,6 +519,16 @@ out.element('delete', {'dir' : '${classes.dir}'}) out.close('target') + out.open('target', {'name' : 'options', 'if' : 'graal.options.exists'}) + out.open('copy', {'todir' : '${jar.dir}'}) + out.element('filelist', {'dir' : '${gamma.dir}', 'files' : 'graal.options'}) + out.close('copy') + out.close('target') + + out.open('target', {'name' : 'check-graal-options-exists'}) + out.element('available', {'property' : 'graal.options.exists', 'file' : '${gamma.dir}/graal.options'}) + out.close('target') + out.open('target', {'name' : 'clean', 'depends' : 'cleanclasses'}) out.element('delete', {'file' : '${jar.file}'}) out.close('target') diff -r f8a4c5011a10 -r b4325bc087c4 src/cpu/sparc/vm/codeInstaller_sparc.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/sparc/vm/codeInstaller_sparc.hpp Sat Jun 08 15:44:39 2013 +0200 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013, 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. + */ +#ifndef CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP +#define CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP + +inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) { + fatal("CodeInstaller::pd_next_offset - sparc unimp"); + return 0; +} + +inline void CodeInstaller::pd_site_DataPatch(oop constant, oop kind, bool inlined, + address instruction, int alignment, char typeChar) { + fatal("CodeInstaller::pd_site_DataPatch - sparc unimp"); +} + +inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { + fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp"); +} + +inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { + fatal("CodeInstaller::pd_relocate_ForeignCall - sparc unimp"); +} + +inline void CodeInstaller::pd_relocate_JavaMethod(oop method, jint pc_offset) { + fatal("CodeInstaller::pd_relocate_JavaMethod - sparc unimp"); +} + +inline int32_t* CodeInstaller::pd_locate_operand(address instruction) { + fatal("CodeInstaller::pd_locate_operand - sparc unimp"); + return (int32_t*)0; +} + +#endif // CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP diff -r f8a4c5011a10 -r b4325bc087c4 src/cpu/sparc/vm/graalGlobals_sparc.hpp --- a/src/cpu/sparc/vm/graalGlobals_sparc.hpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/cpu/sparc/vm/graalGlobals_sparc.hpp Sat Jun 08 15:44:39 2013 +0200 @@ -31,6 +31,32 @@ // Sets the default values for platform dependent flags used by the Graal compiler. // (see graalGlobals.hpp) -define_pd_global(intx, GraalSafepointPollOffset, 0 ); +#if !defined(COMPILER1) && !defined(COMPILER2) +define_pd_global(bool, BackgroundCompilation, true ); +define_pd_global(bool, UseTLAB, true ); +define_pd_global(bool, ResizeTLAB, true ); +define_pd_global(bool, InlineIntrinsics, true ); +define_pd_global(bool, PreferInterpreterNativeStubs, false); +define_pd_global(bool, TieredCompilation, false); +define_pd_global(intx, BackEdgeThreshold, 100000); + +define_pd_global(intx, OnStackReplacePercentage, 933 ); +define_pd_global(intx, FreqInlineSize, 325 ); +define_pd_global(intx, NewSizeThreadIncrease, 4*K ); +define_pd_global(uintx,MetaspaceSize, 12*M ); +define_pd_global(bool, NeverActAsServerClassMachine, false); +define_pd_global(uint64_t,MaxRAM, 1ULL*G); +define_pd_global(bool, CICompileOSR, true ); +define_pd_global(bool, ProfileTraps, true ); +define_pd_global(bool, UseOnStackReplacement, true ); +define_pd_global(intx, CompileThreshold, 10000); +define_pd_global(intx, InitialCodeCacheSize, 16*M ); +define_pd_global(intx, ReservedCodeCacheSize, 64*M ); +define_pd_global(bool, ProfileInterpreter, true ); +define_pd_global(intx, CodeCacheExpansionSize, 64*K ); +define_pd_global(uintx,CodeCacheMinBlockLength, 4); +define_pd_global(intx, TypeProfileWidth, 8); +define_pd_global(intx, MethodProfileWidth, 4); +#endif #endif // CPU_SPARC_VM_GRAALGLOBALS_SPARC_HPP diff -r f8a4c5011a10 -r b4325bc087c4 src/cpu/sparc/vm/interpreterGenerator_sparc.hpp --- a/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp Sat Jun 08 15:44:39 2013 +0200 @@ -27,11 +27,16 @@ friend class AbstractInterpreterGenerator; + address generate_deopt_entry_for(TosState state, int step); + private: address generate_normal_entry(bool synchronized); address generate_native_entry(bool synchronized); - address generate_abstract_entry(void); +#ifdef GRAAL + address generate_execute_compiled_method_entry(); +#endif + address generate_abstract_entry(void); address generate_math_entry(AbstractInterpreter::MethodKind kind); address generate_empty_entry(void); address generate_accessor_entry(void); diff -r f8a4c5011a10 -r b4325bc087c4 src/cpu/sparc/vm/nativeInst_sparc.cpp --- a/src/cpu/sparc/vm/nativeInst_sparc.cpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/cpu/sparc/vm/nativeInst_sparc.cpp Sat Jun 08 15:44:39 2013 +0200 @@ -24,6 +24,8 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "code/codeCache.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_sparc.hpp" #include "oops/oop.inline.hpp" diff -r f8a4c5011a10 -r b4325bc087c4 src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Sat Jun 08 15:44:39 2013 +0200 @@ -1826,6 +1826,20 @@ verify_oop_args(masm, method, sig_bt, regs); vmIntrinsics::ID iid = method->intrinsic_id(); + +#ifdef GRAAL + if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { + // We are called from compiled code here. The three object arguments + // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The + // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail + // call to its verified entry point. + __ set(nmethod::verified_entry_point_offset(), O0); + __ JMP(O0, 0); + __ delayed()->nop(); + return; + } +#endif + // Now write the args into the outgoing interpreter space bool has_receiver = false; Register receiver_reg = noreg; diff -r f8a4c5011a10 -r b4325bc087c4 src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Sat Jun 08 15:44:39 2013 +0200 @@ -213,7 +213,7 @@ } -address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) { +address InterpreterGenerator::generate_deopt_entry_for(TosState state, int step) { address entry = __ pc(); __ get_constant_pool_cache(LcpoolCache); // load LcpoolCache { Label L; @@ -813,6 +813,19 @@ return generate_accessor_entry(); } +#ifdef GRAAL + +// Interpreter stub for calling a compiled method with 3 object arguments +address InterpreterGenerator::generate_execute_compiled_method_entry() { + address entry_point = __ pc(); + + __ stop("graal-sparc unimp"); + + return entry_point; +} + +#endif + // // Interpreter stub for calling a native method. (asm interpreter) // This sets up a somewhat different looking stack for calling the native method diff -r f8a4c5011a10 -r b4325bc087c4 src/cpu/x86/vm/codeInstaller_x86.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/x86/vm/codeInstaller_x86.hpp Sat Jun 08 15:44:39 2013 +0200 @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2013, 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. + */ +#ifndef CPU_SPARC_VM_CODEINSTALLER_X86_HPP +#define CPU_SPARC_VM_CODEINSTALLER_X86_HPP + +#include "compiler/disassembler.hpp" +#include "runtime/javaCalls.hpp" +#include "graal/graalEnv.hpp" +#include "graal/graalCompiler.hpp" +#include "graal/graalCodeInstaller.hpp" +#include "graal/graalJavaAccess.hpp" +#include "graal/graalCompilerToVM.hpp" +#include "graal/graalRuntime.hpp" +#include "asm/register.hpp" +#include "classfile/vmSymbols.hpp" +#include "code/vmreg.hpp" + +inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) { + if (inst->is_call() || inst->is_jump()) { + assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size"); + return (pc_offset + NativeCall::instruction_size); + } else if (inst->is_mov_literal64()) { + // mov+call instruction pair + jint offset = pc_offset + NativeMovConstReg::instruction_size; + u_char* call = (u_char*) (_instructions->start() + offset); + assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte"); + offset += 3; /* prefix byte + opcode byte + modrm byte */ + return (offset); + } else if (inst->is_call_reg()) { + // the inlined vtable stub contains a "call register" instruction + assert(method != NULL, "only valid for virtual calls"); + return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset()); + } else { + fatal("unsupported type of instruction for call site"); + } +} + +inline void CodeInstaller::pd_site_DataPatch(oop constant, oop kind, bool inlined, + address instruction, int alignment, char typeChar) { + switch (typeChar) { + case 'z': + case 'b': + case 's': + case 'c': + case 'i': + fatal("int-sized values not expected in DataPatch"); + break; + case 'f': + case 'j': + case 'd': { + if (inlined) { + address operand = Assembler::locate_operand(instruction, Assembler::imm_operand); + *((jlong*) operand) = Constant::primitive(constant); + } else { + address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand); + address next_instruction = Assembler::locate_next_instruction(instruction); + int size = _constants->size(); + if (alignment > 0) { + guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin"); + size = align_size_up(size, alignment); + } + // we don't care if this is a long/double/etc., the primitive field contains the right bits + address dest = _constants->start() + size; + _constants->set_end(dest + BytesPerLong); + *(jlong*) dest = Constant::primitive(constant); + + long disp = dest - next_instruction; + assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); + *((jint*) operand) = (jint) disp; + + _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); + TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size); + } + break; + } + case 'a': { + address operand = Assembler::locate_operand(instruction, Assembler::imm_operand); + Handle obj = Constant::object(constant); + + jobject value = JNIHandles::make_local(obj()); + *((jobject*) operand) = value; + _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); + TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand); + break; + } + default: + fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar)); + break; + } +} + +inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { + if (cb->is_nmethod()) { + nmethod* nm = (nmethod*) cb; + nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point()); + } else { + nativeJump_at((address)inst)->set_jump_destination(cb->code_begin()); + } + _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); +} + +inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { + if (inst->is_call()) { + // NOTE: for call without a mov, the offset must fit a 32-bit immediate + // see also CompilerToVM.getMaxCallTargetOffset() + NativeCall* call = nativeCall_at((address) (inst)); + call->set_destination((address) foreign_call_destination); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + } else if (inst->is_mov_literal64()) { + NativeMovConstReg* mov = nativeMovConstReg_at((address) (inst)); + mov->set_data((intptr_t) foreign_call_destination); + _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand); + } else { + NativeJump* jump = nativeJump_at((address) (inst)); + jump->set_jump_destination((address) foreign_call_destination); + _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); + } + TRACE_graal_3("relocating (foreign call) at %p", inst); +} + +inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) { +#ifdef ASSERT + Method* method = NULL; + // we need to check, this might also be an unresolved method + if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) { + method = getMethodFromHotSpotMethod(hotspot_method); + } +#endif + switch (_next_call_type) { + case MARK_INLINE_INVOKE: + break; + case MARK_INVOKEVIRTUAL: + case MARK_INVOKEINTERFACE: { + assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); + + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); + _instructions->relocate(call->instruction_address(), + virtual_call_Relocation::spec(_invoke_mark_pc), + Assembler::call32_operand); + break; + } + case MARK_INVOKESTATIC: { + assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); + + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_static_call_stub()); + _instructions->relocate(call->instruction_address(), + relocInfo::static_call_type, Assembler::call32_operand); + break; + } + case MARK_INVOKESPECIAL: { + assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); + _instructions->relocate(call->instruction_address(), + relocInfo::opt_virtual_call_type, Assembler::call32_operand); + break; + } + default: + fatal("invalid _next_call_type value"); + break; + } +} + +inline int32_t* CodeInstaller::pd_locate_operand(address instruction) { + return (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand); +} + +#endif // CPU_SPARC_VM_CODEINSTALLER_X86_HPP + diff -r f8a4c5011a10 -r b4325bc087c4 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Sat Jun 08 15:44:39 2013 +0200 @@ -314,6 +314,7 @@ template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue, "com/oracle/graal/hotspot/meta/HotSpotMonitorValue") \ template(com_oracle_graal_hotspot_debug_LocalImpl, "com/oracle/graal/hotspot/debug/LocalImpl") \ AMD64_ONLY(template(com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime,"com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime"))\ + SPARC_ONLY(template(com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime,"com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime"))\ /* graal.api.meta */ \ template(com_oracle_graal_api_meta_Constant, "com/oracle/graal/api/meta/Constant") \ template(com_oracle_graal_api_meta_ConstantPool, "com/oracle/graal/api/meta/ConstantPool") \ diff -r f8a4c5011a10 -r b4325bc087c4 src/share/vm/code/nmethod.cpp diff -r f8a4c5011a10 -r b4325bc087c4 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Sat Jun 08 15:44:39 2013 +0200 @@ -35,18 +35,23 @@ #include "code/vmreg.hpp" #ifdef TARGET_ARCH_x86 +# include "codeInstaller_x86.hpp" # include "vmreg_x86.inline.hpp" #endif #ifdef TARGET_ARCH_sparc +# include "codeInstaller_sparc.hpp" # include "vmreg_sparc.inline.hpp" #endif #ifdef TARGET_ARCH_zero +# include "codeInstaller_zero.hpp" # include "vmreg_zero.inline.hpp" #endif #ifdef TARGET_ARCH_arm +# include "codeInstaller_arm.hpp" # include "vmreg_arm.inline.hpp" #endif #ifdef TARGET_ARCH_ppc +# include "codeInstaller_ppc.hpp" # include "vmreg_ppc.inline.hpp" #endif @@ -199,8 +204,16 @@ } return value; #else +#ifdef TARGET_ARCH_sparc + ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_FloatRegister(number)->as_VMReg())); + if (type == T_DOUBLE) { + second = value; + } + return value; +#else ShouldNotReachHere("Platform currently does not support floating point values."); #endif +#endif } } else if (value->is_a(StackSlot::klass())) { if (type == T_DOUBLE) { @@ -704,36 +717,15 @@ assert((hotspot_method ? 1 : 0) + (foreign_call ? 1 : 0) == 1, "Call site needs exactly one type"); NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset); - jint next_pc_offset = 0x0; - if (inst->is_call() || inst->is_jump()) { - assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size"); - next_pc_offset = pc_offset + NativeCall::instruction_size; - } else if (inst->is_mov_literal64()) { - // mov+call instruction pair - next_pc_offset = pc_offset + NativeMovConstReg::instruction_size; - u_char* call = (u_char*) (_instructions->start() + next_pc_offset); - assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte"); - next_pc_offset += 3; /* prefix byte + opcode byte + modrm byte */ - } else if (inst->is_call_reg()) { - // the inlined vtable stub contains a "call register" instruction - assert(hotspot_method != NULL, "only valid for virtual calls"); - next_pc_offset = pc_offset + ((NativeCallReg *) inst)->next_instruction_offset(); - } else { - fatal("unsupported type of instruction for call site"); - } - + jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method); + if (target->is_a(SystemDictionary::HotSpotInstalledCode_klass())) { assert(inst->is_jump(), "jump expected"); CodeBlob* cb = (CodeBlob*) (address) HotSpotInstalledCode::codeBlob(target); assert(cb != NULL, "npe"); - if (cb->is_nmethod()) { - nmethod* nm = (nmethod*) cb; - nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point()); - } else { - nativeJump_at((address)inst)->set_jump_destination(cb->code_begin()); - } - _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); + + CodeInstaller::pd_relocate_CodeBlob(cb, inst); return; } @@ -750,65 +742,14 @@ if (foreign_call != NULL) { jlong foreign_call_destination = HotSpotForeignCallLinkage::address(foreign_call); - if (inst->is_call()) { - // NOTE: for call without a mov, the offset must fit a 32-bit immediate - // see also CompilerToVM.getMaxCallTargetOffset() - NativeCall* call = nativeCall_at((address) (inst)); - call->set_destination((address) foreign_call_destination); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - } else if (inst->is_mov_literal64()) { - NativeMovConstReg* mov = nativeMovConstReg_at((address) (inst)); - mov->set_data((intptr_t) foreign_call_destination); - _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand); - } else { - NativeJump* jump = nativeJump_at((address) (inst)); - jump->set_jump_destination((address) foreign_call_destination); - _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); - } - TRACE_graal_3("relocating (foreign call) at %p", inst); + + CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination); } else { // method != NULL assert(hotspot_method != NULL, "unexpected JavaMethod"); -#ifdef ASSERT - Method* method = NULL; - // we need to check, this might also be an unresolved method - if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) { - method = getMethodFromHotSpotMethod(hotspot_method); - } -#endif assert(debug_info != NULL, "debug info expected"); TRACE_graal_3("method call"); - switch (_next_call_type) { - case MARK_INLINE_INVOKE: - break; - case MARK_INVOKEVIRTUAL: - case MARK_INVOKEINTERFACE: { - assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); - - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); - _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc), Assembler::call32_operand); - break; - } - case MARK_INVOKESTATIC: { - assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); - - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - call->set_destination(SharedRuntime::get_resolve_static_call_stub()); - _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand); - break; - } - case MARK_INVOKESPECIAL: { - assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); - _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand); - break; - } - default: - fatal("invalid _next_call_type value"); - break; - } + CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset); } _next_call_type = MARK_INVOKE_INVALID; if (debug_info != NULL) { @@ -823,59 +764,15 @@ oop kind = Constant::kind(constant); address instruction = _instructions->start() + pc_offset; - char typeChar = Kind::typeChar(kind); switch (typeChar) { - case 'z': - case 'b': - case 's': - case 'c': - case 'i': - fatal("int-sized values not expected in DataPatch"); - break; case 'f': case 'j': - case 'd': { + case 'd': record_metadata_in_constant(constant, _oop_recorder); - if (inlined) { - address operand = Assembler::locate_operand(instruction, Assembler::imm_operand); - *((jlong*) operand) = Constant::primitive(constant); - } else { - address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand); - address next_instruction = Assembler::locate_next_instruction(instruction); - int size = _constants->size(); - if (alignment > 0) { - guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin"); - size = align_size_up(size, alignment); - } - // we don't care if this is a long/double/etc., the primitive field contains the right bits - address dest = _constants->start() + size; - _constants->set_end(dest + BytesPerLong); - *(jlong*) dest = Constant::primitive(constant); - - long disp = dest - next_instruction; - assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); - *((jint*) operand) = (jint) disp; - - _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); - TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size); - } - break; - } - case 'a': { - address operand = Assembler::locate_operand(instruction, Assembler::imm_operand); - Handle obj = Constant::object(constant); - - jobject value = JNIHandles::make_local(obj()); - *((jobject*) operand) = value; - _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); - TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand); - break; - } - default: - fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar)); break; } + CodeInstaller::pd_site_DataPatch(constant, kind, inlined, instruction, alignment, typeChar); } void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) { @@ -920,7 +817,8 @@ break; case MARK_POLL_NEAR: { NativeInstruction* ni = nativeInstruction_at(instruction); - int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand); + int32_t* disp = (int32_t*) pd_locate_operand(instruction); + // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand); int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni; *disp = (int32_t)new_disp; @@ -930,7 +828,8 @@ break; case MARK_POLL_RETURN_NEAR: { NativeInstruction* ni = nativeInstruction_at(instruction); - int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand); + int32_t* disp = (int32_t*) pd_locate_operand(instruction); + // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand); int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni; *disp = (int32_t)new_disp; diff -r f8a4c5011a10 -r b4325bc087c4 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Sat Jun 08 15:44:39 2013 +0200 @@ -75,6 +75,13 @@ Dependencies* _dependencies; ExceptionHandlerTable _exception_handler_table; + jint pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method); + void pd_site_DataPatch(oop constant, oop kind, bool inlined, address instruction, int alignment, char typeChar); + void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst); + void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination); + void pd_relocate_JavaMethod(oop method, jint pc_offset); + int32_t* pd_locate_operand(address instruction); + public: CodeInstaller(Handle& comp_result, GraalEnv::CodeInstallResult& result, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations); @@ -106,4 +113,20 @@ }; +#ifdef TARGET_ARCH_x86 +# include "codeInstaller_x86.hpp" +#endif +#ifdef TARGET_ARCH_sparc +# include "codeInstaller_sparc.hpp" +#endif +#ifdef TARGET_ARCH_zero +# error +#endif +#ifdef TARGET_ARCH_arm +# error +#endif +#ifdef TARGET_ARCH_ppc +# error +#endif + #endif // SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP diff -r f8a4c5011a10 -r b4325bc087c4 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Sat Jun 08 15:44:39 2013 +0200 @@ -51,7 +51,7 @@ uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end(); uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024; - guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)"); + AMD64_ONLY(guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)")); NOT_LP64(error("check TLAB allocation code for address space conflicts")); _deopted_leaf_graph_count = 0; diff -r f8a4c5011a10 -r b4325bc087c4 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Sat Jun 08 15:44:39 2013 +0200 @@ -658,8 +658,10 @@ set_boolean("useAESIntrinsics", UseAESIntrinsics); set_boolean("useTLAB", UseTLAB); set_boolean("useG1GC", UseG1GC); +#ifdef TARGET_ARCH_x86 set_int("useSSE", UseSSE); set_int("useAVX", UseAVX); +#endif set_int("codeEntryAlignment", CodeEntryAlignment); set_int("stackShadowPages", StackShadowPages); set_int("hubOffset", oopDesc::klass_offset_in_bytes()); @@ -695,9 +697,11 @@ set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER); set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); +#ifdef TARGET_ARCH_x86 set_boolean("isPollingPageFar", Assembler::is_polling_page_far()); + set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); +#endif set_int("classMirrorOffset", in_bytes(Klass::java_mirror_offset())); - set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); set_int("klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); set_int("klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset())); set_int("klassOffset", java_lang_Class::klass_offset_in_bytes()); @@ -734,6 +738,8 @@ set_int("typeProfileWidth", TypeProfileWidth); set_int("methodProfileWidth", MethodProfileWidth); + set_int("interpreterProfilingThreshold", InvocationCounter::get_ProfileLimit()); + set_int("tlabAlignmentReserve", (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); set_long("tlabIntArrayMarkWord", (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); set_long("heapTopAddress", (jlong)(address) Universe::heap()->top_addr()); @@ -742,7 +748,9 @@ set_int("threadTlabSizeOffset", in_bytes(JavaThread::tlab_size_offset())); set_int("threadAllocatedBytesOffset", in_bytes(JavaThread::allocated_bytes_offset())); set_int("threadLastJavaSpOffset", in_bytes(JavaThread::last_Java_sp_offset())); +#ifdef TARGET_ARCH_x86 set_int("threadLastJavaFpOffset", in_bytes(JavaThread::last_Java_fp_offset())); +#endif set_int("threadLastJavaPcOffset", in_bytes(JavaThread::last_Java_pc_offset())); set_int("threadObjectResultOffset", in_bytes(JavaThread::vm_result_offset())); set_int("tlabSlowAllocationsOffset", in_bytes(JavaThread::tlab_slow_allocations_offset())); diff -r f8a4c5011a10 -r b4325bc087c4 src/share/vm/graal/graalVMToCompiler.cpp --- a/src/share/vm/graal/graalVMToCompiler.cpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.cpp Sat Jun 08 15:44:39 2013 +0200 @@ -51,6 +51,9 @@ #ifdef AMD64 Symbol* name = vmSymbols::com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime(); #endif +#ifdef SPARC + Symbol* name = vmSymbols::com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime(); +#endif KlassHandle klass = loadClass(name); JavaValue result(T_OBJECT); diff -r f8a4c5011a10 -r b4325bc087c4 src/share/vm/interpreter/invocationCounter.hpp --- a/src/share/vm/interpreter/invocationCounter.hpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/share/vm/interpreter/invocationCounter.hpp Sat Jun 08 15:44:39 2013 +0200 @@ -95,9 +95,9 @@ Action action() const { return _action[state()]; } int count() const { return _counter >> number_of_noncount_bits; } - int get_InvocationLimit() const { return InterpreterInvocationLimit >> number_of_noncount_bits; } - int get_BackwardBranchLimit() const { return InterpreterBackwardBranchLimit >> number_of_noncount_bits; } - int get_ProfileLimit() const { return InterpreterProfileLimit >> number_of_noncount_bits; } + static int get_InvocationLimit() { return InterpreterInvocationLimit >> number_of_noncount_bits; } + static int get_BackwardBranchLimit() { return InterpreterBackwardBranchLimit >> number_of_noncount_bits; } + static int get_ProfileLimit() { return InterpreterProfileLimit >> number_of_noncount_bits; } // Test counter using scaled limits like the asm interpreter would do rather than doing // the shifts to normalize the counter. diff -r f8a4c5011a10 -r b4325bc087c4 src/share/vm/runtime/fieldDescriptor.cpp --- a/src/share/vm/runtime/fieldDescriptor.cpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/share/vm/runtime/fieldDescriptor.cpp Sat Jun 08 15:44:39 2013 +0200 @@ -27,9 +27,6 @@ #include "classfile/vmSymbols.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" -#include "oops/annotations.hpp" -#include "oops/instanceKlass.hpp" -#include "oops/fieldStreams.hpp" #include "runtime/fieldDescriptor.hpp" #include "runtime/handles.inline.hpp" #include "runtime/signature.hpp" diff -r f8a4c5011a10 -r b4325bc087c4 src/share/vm/runtime/fieldDescriptor.hpp --- a/src/share/vm/runtime/fieldDescriptor.hpp Sat Jun 08 15:43:48 2013 +0200 +++ b/src/share/vm/runtime/fieldDescriptor.hpp Sat Jun 08 15:44:39 2013 +0200 @@ -25,7 +25,10 @@ #ifndef SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP #define SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP +#include "oops/annotations.hpp" #include "oops/constantPool.hpp" +#include "oops/fieldStreams.hpp" +#include "oops/instanceKlass.hpp" #include "oops/symbol.hpp" #include "runtime/fieldType.hpp" #include "utilities/accessFlags.hpp"