# HG changeset patch # User Christian Humer # Date 1395259834 -3600 # Node ID ed3bfe43d7722d0a7bdc3f77fd5b5389600d7f2a # Parent affd2b3b0cbbf061d5d2b37d0bc812b39fd3fdc0# Parent c03d4de2344869c59bfc02b8926f14f2f7c9673b Merge. diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java Wed Mar 19 21:10:34 2014 +0100 @@ -102,4 +102,10 @@ * @return the register playing the role specified by {@code id} */ Register getRegisterForRole(int id); + + /** + * Determines if all {@link #getAllocatableRegisters() allocatable} registers are + * {@link #getCallerSaveRegisters() caller saved}. + */ + boolean areAllAllocatableRegistersCallerSaved(); } diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java Wed Mar 19 21:10:34 2014 +0100 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, 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.ea; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; + +/** + * Tests {@link AbstractNewObjectNode#simplify(com.oracle.graal.graph.spi.SimplifierTool)}. + * + */ +public class PoorMansEATest extends GraalCompilerTest { + public static class A { + public A obj; + } + + public static A test1Snippet() { + A a = new A(); + a.obj = a; + return null; + } + + @Test + public void test1() { + test("test1Snippet"); + } + + private void test(final String snippet) { + try (Scope s = Debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) { + StructuredGraph graph = parse(snippet); + Assumptions assumptions = new Assumptions(false); + HighTierContext highTierContext = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); + PhaseContext context = new PhaseContext(getProviders(), assumptions); + new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + + // remove framestates in order to trigger the simplification. + cleanup: for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) { + for (Node input : fs.inputs()) { + if (input instanceof NewInstanceNode) { + fs.replaceAtUsages(null); + fs.safeDelete(); + continue cleanup; + } + } + } + new CanonicalizerPhase(true).apply(graph, context); + } catch (Throwable e) { + throw Debug.handle(e); + } + } +} diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Mar 19 21:10:34 2014 +0100 @@ -289,9 +289,10 @@ if (Debug.isMeterEnabled()) { List ldp = compilationResult.getDataReferences(); - DebugMetric[] dms = new DebugMetric[Kind.values().length]; + Kind[] kindValues = Kind.values(); + DebugMetric[] dms = new DebugMetric[kindValues.length]; for (int i = 0; i < dms.length; i++) { - dms[i] = Debug.metric("DataPatches-" + Kind.values()[i].toString()); + dms[i] = Debug.metric("DataPatches-%s", kindValues[i]); } for (DataPatch dp : ldp) { diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Wed Mar 19 21:10:34 2014 +0100 @@ -70,11 +70,8 @@ super(allocator, unhandledFixedFirst, unhandledAnyFirst); // If all allocatable registers are caller saved, then no registers are live across a call - // site. - // The register allocator can save time not trying to find a register at a call site. - HashSet registers = new HashSet<>(Arrays.asList(allocator.frameMap.registerConfig.getAllocatableRegisters())); - registers.removeAll(Arrays.asList(allocator.frameMap.registerConfig.getCallerSaveRegisters())); - allocator.callKillsRegisters = registers.size() == 0; + // site. The register allocator can save time not trying to find a register at a call site. + allocator.callKillsRegisters = allocator.frameMap.registerConfig.areAllAllocatableRegistersCallerSaved(); moveResolver = new MoveResolver(allocator); spillIntervals = Util.uncheckedCast(new List[allocator.registers.length]); diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Wed Mar 19 21:10:34 2014 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.debug; import static com.oracle.graal.debug.Debug.Initialization.*; +import static java.util.FormattableFlags.*; import java.io.*; import java.util.*; @@ -167,9 +168,9 @@ * @return the scope entered by this method which will be exited when its {@link Scope#close()} * method is called */ - public static Scope scope(CharSequence name, Object... context) { + public static Scope scope(Object name, Object... context) { if (ENABLED) { - return DebugScope.getInstance().scope(name, null, context); + return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context); } else { return null; } @@ -380,13 +381,86 @@ * A disabled metric has virtually no overhead. */ public static DebugMetric metric(CharSequence name) { - if (enabledMetrics != null && enabledMetrics.contains(name.toString())) { - return new MetricImpl(name.toString(), false); - } else if (ENABLED) { - return new MetricImpl(name.toString(), true); - } else { + if (enabledMetrics == null && !ENABLED) { return VOID_METRIC; } + return createMetric("%s", name, null); + } + + public static String applyFormattingFlagsAndWidth(String s, int flags, int width) { + if (flags == 0 && width < 0) { + return s; + } + StringBuilder sb = new StringBuilder(s); + + // apply width and justification + int len = sb.length(); + if (len < width) { + for (int i = 0; i < width - len; i++) { + if ((flags & LEFT_JUSTIFY) == LEFT_JUSTIFY) { + sb.append(' '); + } else { + sb.insert(0, ' '); + } + } + } + + String res = sb.toString(); + if ((flags & UPPERCASE) == UPPERCASE) { + res = res.toUpperCase(); + } + return res; + } + + /** + * Creates a debug metric. Invoking this method is equivalent to: + * + *
+     * Debug.metric(format, arg, null)
+     * 
+ * + * except that the string formatting only happens if metering is enabled. + * + * @see #metric(String, Object, Object) + */ + public static DebugMetric metric(String format, Object arg) { + if (enabledMetrics == null && !ENABLED) { + return VOID_METRIC; + } + return createMetric(format, arg, null); + } + + /** + * Creates a debug metric. Invoking this method is equivalent to: + * + *
+     * Debug.metric(String.format(format, arg1, arg2))
+     * 
+ * + * except that the string formatting only happens if metering is enabled. In addition, each + * argument is subject to the following type based conversion before being passed as an argument + * to {@link String#format(String, Object...)}: + * + *
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * 
+ * + * @see #metric(CharSequence) + */ + public static DebugMetric metric(String format, Object arg1, Object arg2) { + if (enabledMetrics == null && !ENABLED) { + return VOID_METRIC; + } + return createMetric(format, arg1, arg2); + } + + private static DebugMetric createMetric(String format, Object arg1, Object arg2) { + String name = formatDebugName(format, arg1, arg2); + boolean conditional = enabledMetrics != null && enabledMetrics.contains(name); + return new MetricImpl(name, conditional); } /** @@ -533,13 +607,72 @@ * A disabled timer has virtually no overhead. */ public static DebugTimer timer(CharSequence name) { - if (enabledTimers != null && enabledTimers.contains(name.toString())) { - return new TimerImpl(name.toString(), false); - } else if (ENABLED) { - return new TimerImpl(name.toString(), true); - } else { + if (enabledTimers == null && !ENABLED) { + return VOID_TIMER; + } + return createTimer("%s", name, null); + } + + /** + * Creates a debug timer. Invoking this method is equivalent to: + * + *
+     * Debug.timer(format, arg, null)
+     * 
+ * + * except that the string formatting only happens if timing is enabled. + * + * @see #timer(String, Object, Object) + */ + public static DebugTimer timer(String format, Object arg) { + if (enabledTimers == null && !ENABLED) { return VOID_TIMER; } + return createTimer(format, arg, null); + } + + /** + * Creates a debug timer. Invoking this method is equivalent to: + * + *
+     * Debug.timer(String.format(format, arg1, arg2))
+     * 
+ * + * except that the string formatting only happens if timing is enabled. In addition, each + * argument is subject to the following type based conversion before being passed as an argument + * to {@link String#format(String, Object...)}: + * + *
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * 
+ * + * @see #timer(CharSequence) + */ + public static DebugTimer timer(String format, Object arg1, Object arg2) { + if (enabledTimers == null && !ENABLED) { + return VOID_TIMER; + } + return createTimer(format, arg1, arg2); + } + + public static Object convertFormatArg(Object arg) { + if (arg instanceof Class) { + return ((Class) arg).getSimpleName(); + } + return arg; + } + + private static String formatDebugName(String format, Object arg1, Object arg2) { + return String.format(format, convertFormatArg(arg1), convertFormatArg(arg2)); + } + + private static DebugTimer createTimer(String format, Object arg1, Object arg2) { + String name = formatDebugName(format, arg1, arg2); + boolean conditional = enabledTimers != null && enabledTimers.contains(name); + return new TimerImpl(name, conditional); } private static final DebugTimer VOID_TIMER = new DebugTimer() { diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Mar 19 21:10:34 2014 +0100 @@ -234,7 +234,7 @@ } isLeafNode = (this.inputOffsets.length == 0 && this.successorOffsets.length == 0); - nodeIterableCount = Debug.metric("NodeIterable_" + shortName); + nodeIterableCount = Debug.metric("NodeIterable_%s", shortName); } @Override diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Wed Mar 19 21:10:34 2014 +0100 @@ -48,6 +48,8 @@ */ private final Register[] callerSaved; + private final boolean allAllocatableAreCallerSaved; + private final HashMap categorized = new HashMap<>(); private final RegisterAttributes[] attributesMap; @@ -152,6 +154,7 @@ callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]); assert callerSaved.length == allocatable.length || RegisterPressure.getValue() != null; + allAllocatableAreCallerSaved = true; attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters); } @@ -161,6 +164,11 @@ } @Override + public boolean areAllAllocatableRegistersCallerSaved() { + return allAllocatableAreCallerSaved; + } + + @Override public Register getRegisterForRole(int index) { throw new UnsupportedOperationException(); } diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java Wed Mar 19 21:10:34 2014 +0100 @@ -74,6 +74,11 @@ } @Override + public boolean areAllAllocatableRegistersCallerSaved() { + throw GraalInternalError.unimplemented(); + } + + @Override public Register getRegisterForRole(int index) { throw GraalInternalError.unimplemented("PTXHotSpotRegisterConfig.getRegisterForRole()"); } diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Wed Mar 19 21:10:34 2014 +0100 @@ -144,6 +144,11 @@ } @Override + public boolean areAllAllocatableRegistersCallerSaved() { + return false; + } + + @Override public Register getRegisterForRole(int index) { throw new UnsupportedOperationException(); } diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java Wed Mar 19 21:10:34 2014 +0100 @@ -23,11 +23,15 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.debug.Debug.*; +import static java.util.FormattableFlags.*; + +import java.util.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; -public abstract class HotSpotMethod extends CompilerObject implements JavaMethod { +public abstract class HotSpotMethod extends CompilerObject implements JavaMethod, Formattable { private static final long serialVersionUID = 7167491397941960839L; protected String name; @@ -54,4 +58,9 @@ String fmt = String.format("HotSpotMethod<%%%c.%%n(%%p)%s>", h, suffix); return format(fmt, this); } + + public void formatTo(Formatter formatter, int flags, int width, int precision) { + String base = (flags & ALTERNATE) == ALTERNATE ? getName() : toString(); + formatter.format(applyFormattingFlagsAndWidth(base, flags & ~ALTERNATE, width)); + } } diff -r affd2b3b0cbb -r ed3bfe43d772 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 Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Wed Mar 19 21:10:34 2014 +0100 @@ -373,9 +373,8 @@ } /** - * Gets the compilation level of the currently installed code for this method. - * - * @return compilation level + * @param level + * @return true if the currently installed code was generated at {@code level}. */ public boolean hasCompiledCodeAtLevel(int level) { long compiledCode = getCompiledCode(); diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Mar 19 21:10:34 2014 +0100 @@ -363,6 +363,10 @@ @Override public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { assert method instanceof HotSpotMethod; + if (!isAbstract(method.getModifiers()) && method.getDeclaringClass().equals(this)) { + return method; + } + final long resolvedMetaspaceMethod = runtime().getCompilerToVM().resolveMethod(metaspaceKlass(), method.getName(), ((HotSpotSignature) method.getSignature()).getMethodDescriptor()); if (resolvedMetaspaceMethod == 0) { return null; diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java --- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java Wed Mar 19 21:10:34 2014 +0100 @@ -24,7 +24,6 @@ package com.oracle.graal.hsail; import com.oracle.graal.api.code.*; - import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; @@ -168,6 +167,11 @@ } @Override + public boolean areAllAllocatableRegistersCallerSaved() { + return false; + } + + @Override public CalleeSaveLayout getCalleeSaveLayout() { return null; } diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java Wed Mar 19 21:10:34 2014 +0100 @@ -73,7 +73,7 @@ return; } } - for (Node usage : usages().snapshot()) { + for (Node usage : usages().distinct().snapshot()) { List snapshot = usage.inputs().snapshot(); graph().removeFixed((FixedWithNextNode) usage); for (Node input : snapshot) { diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Wed Mar 19 21:10:34 2014 +0100 @@ -36,35 +36,7 @@ */ public abstract class BasePhase { - /** - * Phase name lazily computed from the phase class. - */ - class Name extends LazyName { - - @Override - public String createString() { - String s = BasePhase.this.getClass().getSimpleName(); - return s.substring(0, s.length() - "Phase".length()); - } - } - - /** - * Lazily computed debug value name composed of a prefix and a phase's name. - */ - class DebugValueName extends LazyName { - final String prefix; - - public DebugValueName(String prefix) { - this.prefix = prefix; - } - - @Override - public String createString() { - return prefix + name; - } - } - - private final CharSequence name; + private CharSequence name; private final DebugTimer phaseTimer; private final DebugMetric phaseMetric; @@ -77,17 +49,15 @@ } protected BasePhase() { - name = new Name(); - assert checkName(name.toString()); - phaseTimer = Debug.timer(new DebugValueName("PhaseTime_")); - phaseMetric = Debug.metric(new DebugValueName("PhaseCount_")); + phaseTimer = Debug.timer("PhaseTime_%s", getClass()); + phaseMetric = Debug.metric("PhaseCount_%s", getClass()); } protected BasePhase(String name) { assert checkName(name); this.name = name; - phaseTimer = Debug.timer(new DebugValueName("PhaseTime_")); - phaseMetric = Debug.metric(new DebugValueName("PhaseCount_")); + phaseTimer = Debug.timer("PhaseTime_%s", getClass()); + phaseMetric = Debug.metric("PhaseCount_%s", getClass()); } protected CharSequence getDetailedName() { @@ -99,7 +69,7 @@ } public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { - try (TimerCloseable a = phaseTimer.start(); Scope s = Debug.scope(name, this)) { + try (TimerCloseable a = phaseTimer.start(); Scope s = Debug.scope(getClass(), this)) { BasePhase.this.run(graph, context); phaseMetric.increment(); if (dumpGraph) { @@ -112,6 +82,13 @@ } public final CharSequence getName() { + if (name == null) { + String s = BasePhase.this.getClass().getSimpleName(); + if (s.endsWith("Phase")) { + s = s.substring(0, s.length() - "Phase".length()); + } + name = s; + } return name; } diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Wed Mar 19 21:10:34 2014 +0100 @@ -29,8 +29,12 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.virtual.phases.ea.*; /** * Tests {@link ArraysSubstitutions}. @@ -350,4 +354,90 @@ } } + @Test + public void testConstants() { + test("testConstantsSnippet"); + } + + public static final int[] constantArray1 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; + public static final int[] constantArray2 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public static boolean testConstantsSnippet() { + constantArray2[0] = 10; + try { + return Arrays.equals(constantArray1, constantArray2); + } finally { + constantArray2[0] = 1; + } + } + + @Test + public void testCanonicalLength() { + StructuredGraph graph = parse("testCanonicalLengthSnippet"); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + + Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 0); + } + + public static final int[] constantArray3 = new int[]{1, 2, 3}; + + public static boolean testCanonicalLengthSnippet() { + return Arrays.equals(constantArray1, constantArray3); + } + + @Test + public void testCanonicalEqual() { + StructuredGraph graph = parse("testCanonicalEqualSnippet"); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + + Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 1); + } + + public static boolean testCanonicalEqualSnippet() { + return Arrays.equals(constantArray1, constantArray1); + } + + @Test + public void testVirtualEqual() { + StructuredGraph graph = parse("testVirtualEqualSnippet"); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + + Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 1); + } + + public static boolean testVirtualEqualSnippet() { + int[] array1 = new int[]{1, 2, 3, 4}; + int[] array2 = new int[]{1, 2, 3, 4}; + return Arrays.equals(array1, array2); + } + + @Test + public void testVirtualNotEqual() { + StructuredGraph graph = parse("testVirtualNotEqualSnippet"); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + + Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 0); + } + + public static boolean testVirtualNotEqualSnippet(int x) { + int[] array1 = new int[]{1, 2, 100, x}; + int[] array2 = new int[]{1, 2, 3, 4}; + return Arrays.equals(array1, array2); + } } diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Mar 19 21:10:34 2014 +0100 @@ -99,7 +99,7 @@ FrameStateProcessing frameStateProcessing = method.getAnnotation(Snippet.class).removeAllFrameStates() ? FrameStateProcessing.Removal : FrameStateProcessing.CollapseFrameForSingleSideEffect; StructuredGraph newGraph = makeGraph(method, recursiveEntry, recursiveEntry, inliningPolicy(method), frameStateProcessing); - Debug.metric(new MethodDebugValueName("SnippetNodeCount", method)).add(newGraph.getNodeCount()); + Debug.metric("SnippetNodeCount[%#s]", method).add(newGraph.getNodeCount()); if (!UseSnippetGraphCache) { return newGraph; } diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Wed Mar 19 21:10:34 2014 +0100 @@ -24,6 +24,8 @@ import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.debug.Debug.*; +import static java.util.FormattableFlags.*; import java.io.*; import java.lang.reflect.*; @@ -97,8 +99,8 @@ protected SnippetInfo(ResolvedJavaMethod method) { this.method = method; - instantiationCounter = Debug.metric(new MethodDebugValueName("SnippetInstantiationCount", method)); - instantiationTimer = Debug.timer(new MethodDebugValueName("SnippetInstantiationTime", method)); + instantiationCounter = Debug.metric("SnippetInstantiationCount[%#s]", method); + instantiationTimer = Debug.timer("SnippetInstantiationTime[%#s]", method); assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method); int count = method.getSignature().getParameterCount(false); constantParameters = new boolean[count]; @@ -176,7 +178,7 @@ * {@link SnippetTemplate#instantiate instantiated} * */ - public static class Arguments { + public static class Arguments implements Formattable { protected final SnippetInfo info; protected final CacheKey cacheKey; @@ -243,6 +245,30 @@ result.append(">"); return result.toString(); } + + public void formatTo(Formatter formatter, int flags, int width, int precision) { + if ((flags & ALTERNATE) == 0) { + formatter.format(applyFormattingFlagsAndWidth(toString(), flags, width)); + } else { + StringBuilder sb = new StringBuilder(); + sb.append(info.method.getName()).append('('); + String sep = ""; + for (int i = 0; i < info.getParameterCount(); i++) { + if (info.isConstantParameter(i)) { + sb.append(sep); + if (info.names[i] != null) { + sb.append(info.names[i]); + } else { + sb.append(i); + } + sb.append('=').append(values[i]); + sep = ", "; + } + } + sb.append(")"); + formatter.format(applyFormattingFlagsAndWidth(sb.toString(), flags & ~ALTERNATE, width)); + } + } } /** @@ -440,38 +466,13 @@ return false; } - private static String debugValueName(String category, Arguments args) { - if (Debug.isEnabled()) { - StringBuilder result = new StringBuilder(category).append('['); - SnippetInfo info = args.info; - result.append(info.method.getName()).append('('); - String sep = ""; - for (int i = 0; i < info.getParameterCount(); i++) { - if (info.isConstantParameter(i)) { - result.append(sep); - if (info.names[i] != null) { - result.append(info.names[i]); - } else { - result.append(i); - } - result.append('=').append(args.values[i]); - sep = ", "; - } - } - result.append(")]"); - return result.toString(); - - } - return null; - } - /** * Creates a snippet template. */ protected SnippetTemplate(final Providers providers, Arguments args) { StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method); - instantiationTimer = Debug.timer(debugValueName("SnippetTemplateInstantiationTime", args)); - instantiationCounter = Debug.metric(debugValueName("SnippetTemplateInstantiationCount", args)); + instantiationTimer = Debug.timer("SnippetTemplateInstantiationTime[%#s]", args); + instantiationCounter = Debug.metric("SnippetTemplateInstantiationCount[%#s]", args); ResolvedJavaMethod method = snippetGraph.method(); Signature signature = method.getSignature(); @@ -665,7 +666,7 @@ } } - Debug.metric(debugValueName("SnippetTemplateNodeCount", args)).add(nodes.size()); + Debug.metric("SnippetTemplateNodeCount[%#s]", args).add(nodes.size()); args.info.notifyNewTemplate(); Debug.dump(snippet, "SnippetTemplate final state"); } diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Wed Mar 19 21:10:34 2014 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.replacements.nodes; -import java.util.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; @@ -31,12 +29,14 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; /** * Compares two arrays with the same length. */ -public class ArrayEqualsNode extends FixedWithNextNode implements LIRGenLowerable, Canonicalizable { +public class ArrayEqualsNode extends FixedWithNextNode implements LIRGenLowerable, Canonicalizable, Virtualizable { /** {@link Kind} of the arrays to compare. */ private final Kind kind; @@ -65,42 +65,45 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (!array1.isConstant() || !array2.isConstant()) { - return this; + if (usages().isEmpty()) { + return null; } + if (GraphUtil.unproxify(array1) == GraphUtil.unproxify(array2)) { + return ConstantNode.forBoolean(true, graph()); + } + return this; + } - Object a1 = array1.asConstant().asObject(); - Object a2 = array2.asConstant().asObject(); - boolean x; - switch (kind) { - case Boolean: - x = Arrays.equals((boolean[]) a1, (boolean[]) a2); - break; - case Byte: - x = Arrays.equals((byte[]) a1, (byte[]) a2); - break; - case Char: - x = Arrays.equals((char[]) a1, (char[]) a2); - break; - case Short: - x = Arrays.equals((short[]) a1, (short[]) a2); - break; - case Int: - x = Arrays.equals((int[]) a1, (int[]) a2); - break; - case Long: - x = Arrays.equals((long[]) a1, (long[]) a2); - break; - case Float: - x = Arrays.equals((float[]) a1, (float[]) a2); - break; - case Double: - x = Arrays.equals((double[]) a1, (double[]) a2); - break; - default: - throw GraalInternalError.shouldNotReachHere("unknown kind " + kind); + public void virtualize(VirtualizerTool tool) { + State state1 = tool.getObjectState(array1); + if (state1 != null) { + State state2 = tool.getObjectState(array2); + if (state2 != null) { + if (state1.getVirtualObject() == state2.getVirtualObject()) { + // the same virtual objects will always have the same contents + tool.replaceWithValue(ConstantNode.forBoolean(true, graph())); + } else if (state1.getVirtualObject().entryCount() == state2.getVirtualObject().entryCount()) { + int entryCount = state1.getVirtualObject().entryCount(); + boolean allEqual = true; + for (int i = 0; i < entryCount; i++) { + ValueNode entry1 = state1.getEntry(i); + ValueNode entry2 = state2.getEntry(i); + if (entry1 != entry2) { + // the contents might be different + allEqual = false; + } + if (entry1.stamp().alwaysDistinct(entry2.stamp())) { + // the contents are different + tool.replaceWithValue(ConstantNode.forBoolean(false, graph())); + return; + } + } + if (allEqual) { + tool.replaceWithValue(ConstantNode.forBoolean(true, graph())); + } + } + } } - return ConstantNode.forBoolean(x, graph()); } @NodeIntrinsic diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Mar 19 21:10:34 2014 +0100 @@ -250,7 +250,7 @@ StructuredGraph graph = truffleCache.lookup(targetMethod, arguments, assumptions, canonicalizer); if (targetMethod.getAnnotation(ExplodeLoop.class) != null) { - assert graph.hasLoops(); + assert graph.hasLoops() : graph + " does not contain a loop"; final StructuredGraph graphCopy = graph.copy(); final List modifiedNodes = new ArrayList<>(); for (ParameterNode param : graphCopy.getNodes(ParameterNode.class)) { diff -r affd2b3b0cbb -r ed3bfe43d772 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Wed Mar 19 19:54:07 2014 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Wed Mar 19 21:10:34 2014 +0100 @@ -335,15 +335,6 @@ ObjectState[] objStates = new ObjectState[states.size()]; boolean materialized; do { - Iterator> iter = newState.objectStates.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - if (!virtualObjTemp.contains(entry.getValue())) { - iter.remove(); - } - } - mergeEffects.clear(); - afterMergeEffects.clear(); materialized = false; for (VirtualObjectNode object : virtualObjTemp) { for (int i = 0; i < objStates.length; i++) { @@ -389,6 +380,11 @@ materialized |= processPhi(phi, states, virtualObjTemp); } } + if (materialized) { + newState.objectStates.clear(); + mergeEffects.clear(); + afterMergeEffects.clear(); + } } while (materialized); } diff -r affd2b3b0cbb -r ed3bfe43d772 mx/mx_graal.py --- a/mx/mx_graal.py Wed Mar 19 19:54:07 2014 +0100 +++ b/mx/mx_graal.py Wed Mar 19 21:10:34 2014 +0100 @@ -83,6 +83,12 @@ JDK_UNIX_PERMISSIONS = 0755 +def isVMSupported(vm): + if 'client' in vm and len(platform.mac_ver()[0]) != 0: + # Client VM not supported: java launcher on Mac OS X translates '-client' to '-server' + return False + return True + def _get_vm(): """ Gets the configured VM, presenting a dialogue if there is no currently configured VM. @@ -569,6 +575,10 @@ mx.log('only product build of original VM exists') continue + if not isVMSupported(vm): + mx.log('The ' + vm + ' VM is not supported on this platform - skipping') + continue + vmDir = join(_vmLibDirInJdk(jdk), vm) if not exists(vmDir): if mx.get_os() != 'windows': @@ -718,8 +728,8 @@ if vm is None: vm = _get_vm() - if 'client' in vm and len(platform.mac_ver()[0]) != 0: - mx.abort("Client VM not supported: java launcher on Mac OS X translates '-client' to '-server'") + if not isVMSupported(vm): + mx.abort('The ' + vm + ' is not supported on this platform') if cwd is None: cwd = _vm_cwd @@ -927,6 +937,10 @@ allStart = time.time() for v in vms: + if not isVMSupported(v): + mx.log('The ' + v + ' VM is not supported on this platform - skipping') + continue + for vmbuild in builds: if v == 'original' and vmbuild != 'product': continue @@ -1043,6 +1057,9 @@ for vmbuild in ['product', 'fastdebug']: for theVm in ['client', 'server']: + if not isVMSupported(theVm): + mx.log('The' + theVm + ' VM is not supported on this platform') + continue with VM(theVm, vmbuild): t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild) dacapo(['pmd']) diff -r affd2b3b0cbb -r ed3bfe43d772 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Wed Mar 19 19:54:07 2014 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Wed Mar 19 21:10:34 2014 +0100 @@ -539,7 +539,12 @@ Handle receiverHandle(thread, receiver); MutexLockerEx ml(thread->threadObj() == (void*)receiver ? NULL : Threads_lock); JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle()); - return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0); + if (receiverThread == NULL) { + // The other thread may exit during this process, which is ok so return false. + return JNI_FALSE; + } else { + return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0); + } JRT_END // JVM_InitializeGraalRuntime