# HG changeset patch # User Doug Simon # Date 1403645353 -7200 # Node ID 6140fd60abe959a61dcf534deb0a9d9f87d63584 # Parent 38bb9b5b8544d0e651224827445288b154bed46c# Parent 8fde32ece68efab884b258aa6bff9192b54a03a0 Merge. diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Tue Jun 24 23:29:13 2014 +0200 @@ -417,7 +417,7 @@ return builder -> { LIRKind writeKind = getLIRGeneratorTool().getLIRKind(root.value().stamp()); Value address = root.location().generateAddress(builder, getLIRGeneratorTool(), operand(root.object())); - Value v = operand(narrow.getInput()); + Value v = operand(narrow.getValue()); getLIRGeneratorTool().emitStore(writeKind, address, v, state(root)); return null; }; diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java Tue Jun 24 23:29:13 2014 +0200 @@ -64,4 +64,13 @@ } return false; } + + @Override + public Constant asConstant() { + if (alwaysNull()) { + return Constant.NULL_OBJECT; + } else { + return null; + } + } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatOptimizationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatOptimizationTest.java Tue Jun 24 23:29:13 2014 +0200 @@ -0,0 +1,85 @@ +/* + * 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; + +import org.junit.*; + +/** + * Check for incorrect elimination of 0.0 and -0.0 from computations. They can affect the sign of + * the result of an add or substract. + */ +public class FloatOptimizationTest extends GraalCompilerTest { + + @Test + public void test1() { + test("test1Snippet", -0.0); + } + + @SuppressWarnings("all") + public static double test1Snippet(double x) { + return x + 0.0; + } + + @Test + public void test2() { + test("test2Snippet", -0.0f); + } + + @SuppressWarnings("all") + public static double test2Snippet(float x) { + return x + 0.0f; + } + + @Test + public void test3() { + test("test3Snippet", -0.0); + } + + @SuppressWarnings("all") + public static double test3Snippet(double x) { + return x - -0.0; + } + + @Test + public void test4() { + test("test4Snippet", -0.0f); + } + + @SuppressWarnings("all") + public static double test4Snippet(float x) { + return x - -0.0f; + } + + @Override + protected void assertDeepEquals(String message, Object expected, Object actual, double delta) { + if (expected instanceof Double && actual instanceof Double) { + double e = (double) expected; + double a = (double) actual; + if (Double.doubleToRawLongBits(a) != Double.doubleToRawLongBits(e)) { + Assert.fail((message == null ? "" : message) + "raw double bits not equal " + Double.doubleToRawLongBits(a) + " != " + Double.doubleToRawLongBits(e)); + } + } else { + super.assertDeepEquals(message, expected, actual, delta); + } + } +} diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Tue Jun 24 23:29:13 2014 +0200 @@ -55,19 +55,19 @@ * This class traverses the HIR instructions and generates LIR instructions from them. */ @MatchableNode(nodeClass = ConstantNode.class, shareable = true) -@MatchableNode(nodeClass = FloatConvertNode.class, inputs = {"input"}) +@MatchableNode(nodeClass = FloatConvertNode.class, inputs = {"value"}) @MatchableNode(nodeClass = FloatSubNode.class, inputs = {"x", "y"}) @MatchableNode(nodeClass = FloatingReadNode.class, inputs = {"object", "location"}) @MatchableNode(nodeClass = IfNode.class, inputs = {"condition"}) @MatchableNode(nodeClass = IntegerSubNode.class, inputs = {"x", "y"}) @MatchableNode(nodeClass = LeftShiftNode.class, inputs = {"x", "y"}) -@MatchableNode(nodeClass = NarrowNode.class, inputs = {"input"}) +@MatchableNode(nodeClass = NarrowNode.class, inputs = {"value"}) @MatchableNode(nodeClass = ReadNode.class, inputs = {"object", "location"}) @MatchableNode(nodeClass = ReinterpretNode.class, inputs = {"value"}) -@MatchableNode(nodeClass = SignExtendNode.class, inputs = {"input"}) +@MatchableNode(nodeClass = SignExtendNode.class, inputs = {"value"}) @MatchableNode(nodeClass = UnsignedRightShiftNode.class, inputs = {"x", "y"}) @MatchableNode(nodeClass = WriteNode.class, inputs = {"object", "location", "value"}) -@MatchableNode(nodeClass = ZeroExtendNode.class, inputs = {"input"}) +@MatchableNode(nodeClass = ZeroExtendNode.class, inputs = {"value"}) @MatchableNode(nodeClass = AndNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = FloatAddNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = FloatEqualsNode.class, inputs = {"x", "y"}, commutative = true) diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchValue.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchValue.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchValue.java Tue Jun 24 23:29:13 2014 +0200 @@ -37,7 +37,7 @@ * This is the Value of a node which was matched as part of a complex match. The value isn't * actually useable but this marks it as having been evaluated. */ - @SuppressWarnings("serial") public static Value INTERIOR_MATCH = new Value(LIRKind.Illegal) { + @SuppressWarnings("serial") public static final Value INTERIOR_MATCH = new Value(LIRKind.Illegal) { @Override public String toString() { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Tue Jun 24 23:29:13 2014 +0200 @@ -68,9 +68,6 @@ for (int i = 0; i < names.length; i++) { for (NodeClass.Position position : nodeClass.getFirstLevelInputPositions()) { String name = nodeClass.getName(position); - if (name.endsWith("#NDF")) { - name = name.substring(0, name.length() - 4); - } if (name.equals(names[i])) { result[i] = position; break; diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Tue Jun 24 23:29:13 2014 +0200 @@ -559,12 +559,13 @@ assert assertTrue(result, "not found in usages, old input: %s", oldInput); } } + maybeNotifyChanged(this); if (newInput != null) { if (newInput.recordsUsages()) { - maybeNotifyChanged(this); newInput.addUsage(this); } - } else if (oldInput != null && oldInput.recordsUsages() && oldInput.usages().isEmpty()) { + } + if (oldInput != null && oldInput.recordsUsages() && oldInput.usages().isEmpty()) { maybeNotifyZeroInputs(oldInput); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 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 Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Tue Jun 24 23:29:13 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -298,9 +298,6 @@ } types.put(offset, inputAnnotation.value()); names.put(offset, field.getName()); - if (inputAnnotation.value() != InputType.Value) { - fieldNames.put(offset, field.getName() + "#NDF"); - } } else if (field.isAnnotationPresent(Node.Successor.class)) { if (SUCCESSOR_LIST_CLASS.isAssignableFrom(type)) { GraalInternalError.guarantee(Modifier.isFinal(field.getModifiers()), "NodeSuccessorList successor field % should be final", field); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeWorkList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeWorkList.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeWorkList.java Tue Jun 24 23:29:13 2014 +0200 @@ -50,6 +50,8 @@ public abstract void add(Node node); + public abstract boolean contains(Node node); + private abstract class QueueConsumingIterator implements Iterator { protected void dropDeleted() { @@ -140,6 +142,20 @@ } } + @Override + public boolean contains(Node node) { + if (inQueue != null) { + return inQueue.isMarked(node); + } else { + for (Node queuedNode : worklist) { + if (queuedNode == node) { + return true; + } + } + return false; + } + } + private boolean checkInfiniteWork(Node node) { if (lastPull == node) { if (firstNoChange == null) { @@ -186,6 +202,11 @@ } @Override + public boolean contains(Node node) { + return visited.isMarked(node); + } + + @Override public Iterator iterator() { return new QueueConsumingIterator() { @Override diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/SimplifierTool.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/SimplifierTool.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/SimplifierTool.java Tue Jun 24 23:29:13 2014 +0200 @@ -35,4 +35,6 @@ * Adds a node to the worklist independent of whether it has already been on the worklist. */ void addToWorkList(Node node); + + void addToWorkList(Iterable nodes); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Tue Jun 24 23:29:13 2014 +0200 @@ -63,7 +63,7 @@ result = ((PiNode) result).getOriginalNode(); } if (result instanceof CompressionNode) { - result = ((CompressionNode) result).getInput(); + result = ((CompressionNode) result).getValue(); } return result; } @@ -223,7 +223,7 @@ boolean canFormCompressedMemory(CompressionNode compress, ConstantLocationNode location) { HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig(); if (config.useCompressedOops && compress.getEncoding().shift <= 3 && NumUtil.isInt(location.getDisplacement())) { - Stamp compressedStamp = compress.getInput().stamp(); + Stamp compressedStamp = compress.getValue().stamp(); if (compressedStamp instanceof NarrowOopStamp) { return true; } else if (compressedStamp instanceof IntegerStamp) { @@ -236,7 +236,7 @@ private AMD64AddressValue makeCompressedAddress(CompressionNode compress, ConstantLocationNode location) { assert canFormCompressedMemory(compress, location); - AMD64AddressValue address = getGen().emitAddress(getGen().getProviders().getRegisters().getHeapBaseRegister().asValue(), location.getDisplacement(), operand(compress.getInput()), + AMD64AddressValue address = getGen().emitAddress(getGen().getProviders().getRegisters().getHeapBaseRegister().asValue(), location.getDisplacement(), operand(compress.getValue()), 1 << compress.getEncoding().shift); return address; } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java Tue Jun 24 23:29:13 2014 +0200 @@ -269,4 +269,12 @@ public boolean needsJavaFrameAnchor() { return canDeoptimize() || transition == Transition.LEAF_SP; } + + public CompilationResult getStubCompilationResult(final Backend backend) { + return stub.getCompilationResult(backend); + } + + public Stub getStub() { + return stub; + } } diff -r 38bb9b5b8544 -r 6140fd60abe9 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 Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Jun 24 23:29:13 2014 +0200 @@ -169,7 +169,7 @@ @Option(help = "The runtime configuration to use") static final OptionValue GraalRuntime = new OptionValue<>(""); - @Option(help = "File to which logging is sent. %p in the name will be replaced with a string the process, usually the process id.") + @Option(help = "File to which logging is sent. A %p in the name will be replaced with a string identifying the process, usually the process id.") public static final PrintStreamOption LogFile = new PrintStreamOption(); // @formatter:on } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java Tue Jun 24 23:29:13 2014 +0200 @@ -32,7 +32,7 @@ * This interface defines the contract a HotSpot backend LIR generator needs to fulfill in addition * to abstract methods from {@link LIRGenerator} and {@link NodeLIRBuilderTool}. */ -@MatchableNode(nodeClass = CompressionNode.class, inputs = {"input"}) +@MatchableNode(nodeClass = CompressionNode.class, inputs = {"value"}) public interface HotSpotNodeLIRBuilder { void emitPatchReturnAddress(ValueNode address); diff -r 38bb9b5b8544 -r 6140fd60abe9 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 Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Jun 24 23:29:13 2014 +0200 @@ -1424,9 +1424,9 @@ @HotSpotVMValue(expression = "GraalRuntime::dynamic_new_array", get = HotSpotVMValue.Type.ADDRESS) @Stable public long dynamicNewArrayAddress; @HotSpotVMValue(expression = "GraalRuntime::dynamic_new_instance", get = HotSpotVMValue.Type.ADDRESS) @Stable public long dynamicNewInstanceAddress; @HotSpotVMValue(expression = "GraalRuntime::thread_is_interrupted", get = HotSpotVMValue.Type.ADDRESS) @Stable public long threadIsInterruptedAddress; - @HotSpotVMValue(expression = "GraalRuntime::vm_message", get = HotSpotVMValue.Type.ADDRESS) @Stable public long vmMessageAddress; + @HotSpotVMValue(expression = "GraalRuntime::vm_message", signature = "(unsigned char, long, long, long, long)", get = HotSpotVMValue.Type.ADDRESS) @Stable public long vmMessageAddress; @HotSpotVMValue(expression = "GraalRuntime::identity_hash_code", get = HotSpotVMValue.Type.ADDRESS) @Stable public long identityHashCodeAddress; - @HotSpotVMValue(expression = "GraalRuntime::exception_handler_for_pc", get = HotSpotVMValue.Type.ADDRESS) @Stable public long exceptionHandlerForPcAddress; + @HotSpotVMValue(expression = "GraalRuntime::exception_handler_for_pc", signature = "(JavaThread*)", get = HotSpotVMValue.Type.ADDRESS) @Stable public long exceptionHandlerForPcAddress; @HotSpotVMValue(expression = "GraalRuntime::monitorenter", get = HotSpotVMValue.Type.ADDRESS) @Stable public long monitorenterAddress; @HotSpotVMValue(expression = "GraalRuntime::monitorexit", get = HotSpotVMValue.Type.ADDRESS) @Stable public long monitorexitAddress; @HotSpotVMValue(expression = "GraalRuntime::create_null_exception", get = HotSpotVMValue.Type.ADDRESS) @Stable public long createNullPointerExceptionAddress; @@ -1452,9 +1452,9 @@ @HotSpotVMValue(expression = "(jint) GraalCounterSize") @Stable public int graalCountersSize; - @HotSpotVMValue(expression = "Deoptimization::fetch_unroll_info", get = HotSpotVMValue.Type.ADDRESS) @Stable public long deoptimizationFetchUnrollInfo; + @HotSpotVMValue(expression = "Deoptimization::fetch_unroll_info", signature = "(JavaThread*)", get = HotSpotVMValue.Type.ADDRESS) @Stable public long deoptimizationFetchUnrollInfo; @HotSpotVMValue(expression = "Deoptimization::uncommon_trap", get = HotSpotVMValue.Type.ADDRESS) @Stable public long deoptimizationUncommonTrap; - @HotSpotVMValue(expression = "Deoptimization::unpack_frames", get = HotSpotVMValue.Type.ADDRESS) @Stable public long deoptimizationUnpackFrames; + @HotSpotVMValue(expression = "Deoptimization::unpack_frames", signature = "(JavaThread*, int)", get = HotSpotVMValue.Type.ADDRESS) @Stable public long deoptimizationUnpackFrames; @HotSpotVMConstant(name = "Deoptimization::Reason_none") @Stable public int deoptReasonNone; @HotSpotVMConstant(name = "Deoptimization::Reason_null_check") @Stable public int deoptReasonNullCheck; @@ -1599,4 +1599,35 @@ } } } + + /** + * Returns the name of the C/C++ function that is associated (via HotSpotVMValue annotation) + * with the HotSpotVMConfig object's field containing {@code foreignCalltargetAddress}; returns + * null if no field holds the provided address. + * + * @param foreignCallTargetAddress address of foreign call target + * @return C/C++ symbol name or null + */ + public String getCSymbol(long foreignCallTargetAddress) { + for (Field f : HotSpotVMConfig.class.getDeclaredFields()) { + if (f.isAnnotationPresent(HotSpotVMValue.class)) { + HotSpotVMValue annotation = f.getAnnotation(HotSpotVMValue.class); + + if (annotation.get() == HotSpotVMValue.Type.ADDRESS) { + try { + if (foreignCallTargetAddress == f.getLong(this)) { + return (annotation.expression() + annotation.signature()); + } + } catch (IllegalArgumentException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (IllegalAccessException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + } + } + return null; + } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Jun 24 23:29:13 2014 +0200 @@ -87,7 +87,7 @@ * @return the metaspace Method result or 0 is there is no unique concrete method for * {@code metaspaceMethod} */ - long findUniqueConcreteMethod(long metaspaceMethod); + long findUniqueConcreteMethod(long actualHolderMetaspaceKlass, long metaspaceMethod); /** * Returns the implementor for the given interface class. diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Jun 24 23:29:13 2014 +0200 @@ -68,7 +68,7 @@ public native boolean hasBalancedMonitors(long metaspaceMethod); @Override - public native long findUniqueConcreteMethod(long metaspaceMethod); + public native long findUniqueConcreteMethod(long actualHolderMetaspaceKlass, long metaspaceMethod); @Override public native long getKlassImplementor(long metaspaceKlass); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Tue Jun 24 23:29:13 2014 +0200 @@ -229,6 +229,12 @@ return runtime.getHostProviders().getMetaAccess().lookupJavaType((Class) obj); } } + if (constant instanceof HotSpotMetaspaceConstant) { + Object obj = HotSpotMetaspaceConstant.getMetaspaceObject(constant); + if (obj instanceof HotSpotResolvedObjectType) { + return (ResolvedJavaType) obj; + } + } return null; } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Tue Jun 24 23:29:13 2014 +0200 @@ -175,4 +175,9 @@ registerArrayCopy(Kind.Object, c.oopArraycopy, c.oopAlignedArraycopy, c.oopDisjointArraycopy, c.oopAlignedDisjointArraycopy); registerArrayCopy(Kind.Object, c.oopArraycopyUninit, c.oopAlignedArraycopyUninit, c.oopDisjointArraycopyUninit, c.oopAlignedDisjointArraycopyUninit, true); } + + public HotSpotForeignCallLinkage getForeignCall(ForeignCallDescriptor descriptor) { + assert foreignCalls != null : descriptor; + return foreignCalls.get(descriptor); + } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Tue Jun 24 23:29:13 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; @@ -40,6 +41,8 @@ IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization); + Stamp loadStamp(Stamp stamp, Kind kind); + ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value); ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value); diff -r 38bb9b5b8544 -r 6140fd60abe9 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 Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue Jun 24 23:29:13 2014 +0200 @@ -350,8 +350,8 @@ return runtime().getCompilerToVM().getStackTraceElement(metaspaceMethod, bci); } - public ResolvedJavaMethod uniqueConcreteMethod() { - if (holder.isInterface()) { + public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver) { + if (receiver.isInterface()) { // Cannot trust interfaces. Because of: // interface I { void foo(); } // class A { public void foo() {} } @@ -362,7 +362,7 @@ // seeing A.foo(). return null; } - final long uniqueConcreteMethod = runtime().getCompilerToVM().findUniqueConcreteMethod(metaspaceMethod); + final long uniqueConcreteMethod = runtime().getCompilerToVM().findUniqueConcreteMethod(receiver.getMetaspaceKlass(), metaspaceMethod); if (uniqueConcreteMethod == 0) { return null; } diff -r 38bb9b5b8544 -r 6140fd60abe9 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 Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Tue Jun 24 23:29:13 2014 +0200 @@ -459,7 +459,26 @@ @Override public ResolvedJavaMethod findUniqueConcreteMethod(ResolvedJavaMethod method) { - return ((HotSpotResolvedJavaMethod) method).uniqueConcreteMethod(); + HotSpotResolvedJavaMethod hmethod = (HotSpotResolvedJavaMethod) method; + HotSpotResolvedObjectType declaredHolder = hmethod.getDeclaringClass(); + /* + * Sometimes the receiver type in the graph hasn't stabilized to a subtype of declared + * holder, usually because of phis, so make sure that the type is related to the declared + * type before using it for lookup. + */ + if (!declaredHolder.isAssignableFrom(this) || this.isArray() || this.equals(declaredHolder)) { + return hmethod.uniqueConcreteMethod(declaredHolder); + } + /* + * The holder may be a subtype of the decaredHolder so make sure to resolve the method to + * the correct method for the subtype. + */ + HotSpotResolvedJavaMethod newMethod = (HotSpotResolvedJavaMethod) resolveMethod(hmethod, this); + if (newMethod != null && !hmethod.equals(newMethod)) { + hmethod = newMethod; + } + + return hmethod.uniqueConcreteMethod(this); } /** diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -152,12 +152,12 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (getInput().isConstant()) { - return ConstantNode.forConstant(stamp(), evalConst(getInput().asConstant()), tool.getMetaAccess(), graph()); - } else if (getInput() instanceof CompressionNode) { - CompressionNode other = (CompressionNode) getInput(); + if (getValue().isConstant()) { + return ConstantNode.forConstant(stamp(), evalConst(getValue().asConstant()), tool.getMetaAccess(), graph()); + } else if (getValue() instanceof CompressionNode) { + CompressionNode other = (CompressionNode) getValue(); if (op != other.op && encoding.equals(other.encoding)) { - return other.getInput(); + return other.getValue(); } } return this; @@ -167,8 +167,8 @@ public void generate(NodeLIRBuilderTool gen) { HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool(); boolean nonNull; - if (getInput().stamp() instanceof AbstractObjectStamp) { - nonNull = StampTool.isObjectNonNull(getInput().stamp()); + if (getValue().stamp() instanceof AbstractObjectStamp) { + nonNull = StampTool.isObjectNonNull(getValue().stamp()); } else { // metaspace pointers are never null nonNull = true; @@ -177,10 +177,10 @@ Value result; switch (op) { case Compress: - result = hsGen.emitCompress(gen.operand(getInput()), encoding, nonNull); + result = hsGen.emitCompress(gen.operand(getValue()), encoding, nonNull); break; case Uncompress: - result = hsGen.emitUncompress(gen.operand(getInput()), encoding, nonNull); + result = hsGen.emitUncompress(gen.operand(getValue()), encoding, nonNull); break; default: throw GraalInternalError.shouldNotReachHere(); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java Tue Jun 24 23:29:13 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.spi.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; +import com.oracle.graal.hotspot.meta.*; public class NarrowOopStamp extends AbstractObjectStamp { @@ -100,4 +101,13 @@ } return super.equals(other); } + + @Override + public Constant asConstant() { + if (alwaysNull()) { + return HotSpotCompressedNullConstant.COMPRESSED_NULL; + } else { + return null; + } + } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue Jun 24 23:29:13 2014 +0200 @@ -501,7 +501,7 @@ graph.addAfterFixed(graph.start(), invoke); StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod()); - InliningUtil.inline(invoke, inlineeGraph, false); + InliningUtil.inline(invoke, inlineeGraph, false, null); List rets = graph.getNodes(ReturnNode.class).snapshot(); for (ReturnNode ret : rets) { @@ -520,7 +520,7 @@ inlineeGraph = template(args).copySpecializedGraph(); // inlineeGraph = replacements.getSnippet(checkCounter.getMethod()); - InliningUtil.inline(invoke, inlineeGraph, false); + InliningUtil.inline(invoke, inlineeGraph, false, null); } } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Tue Jun 24 23:29:13 2014 +0200 @@ -64,6 +64,11 @@ protected InstalledCode code; /** + * Compilation result from which {@link #code} was created. + */ + protected CompilationResult compResult; + + /** * The registers destroyed by this stub. */ private Set destroyedRegisters; @@ -152,7 +157,7 @@ CallingConvention incomingCc = linkage.getIncomingCallingConvention(); TargetDescription target = codeCache.getTarget(); - final CompilationResult compResult = new CompilationResult(); + compResult = new CompilationResult(); try (Scope s0 = Debug.scope("StubCompilation", graph, providers.getCodeCache())) { Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); SchedulePhase schedule = emitFrontEnd(providers, target, graph, assumptions, null, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, @@ -182,6 +187,18 @@ } assert code != null : "error installing stub " + this; } + return code; } + + /** + * Gets the compilation result for this stub, compiling it first if necessary, and installing it + * in code. + */ + public synchronized CompilationResult getCompilationResult(final Backend backend) { + if (code == null) { + getCode(backend); + } + return compResult; + } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMValue.java --- a/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMValue.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMValue.java Tue Jun 24 23:29:13 2014 +0200 @@ -45,6 +45,13 @@ VALUE } + /** + * If {@link #expression} is a C++ function name, {@link #signature} represents the signature of + * the function. + * + */ + String signature() default ""; + Type get() default Type.VALUE; /** diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -67,11 +67,6 @@ return value; } - @Override - public boolean recordsUsages() { - return true; - } - /** * Gathers all the {@link ConstantNode}s that are inputs to the * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph. diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -560,11 +560,11 @@ } boolean negateConditionalCondition; ValueNode otherValue; - if (constant == conditional.x()) { - otherValue = conditional.y(); + if (constant == conditional.trueValue()) { + otherValue = conditional.falseValue(); negateConditionalCondition = false; - } else if (constant == conditional.y()) { - otherValue = conditional.x(); + } else if (constant == conditional.falseValue()) { + otherValue = conditional.trueValue(); negateConditionalCondition = true; } else { return null; diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -298,7 +298,7 @@ } } if (tool != null) { - otherPhi.usages().forEach(tool::addToWorkList); + tool.addToWorkList(otherPhi.usages()); } otherPhi.replaceAtUsages(phi); GraphUtil.killWithUnusedFloatingInputs(otherPhi); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -164,7 +164,7 @@ if (singleValue != null) { for (Node node : usages().snapshot()) { if (node instanceof ProxyNode && ((ProxyNode) node).proxyPoint() instanceof LoopExitNode && ((LoopExitNode) ((ProxyNode) node).proxyPoint()).loopBegin() == merge) { - node.usages().forEach(tool::addToWorkList); + tool.addToWorkList(node.usages()); graph().replaceFloating((FloatingNode) node, singleValue); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -35,17 +35,12 @@ /** * A node that attaches a type profile to a proxied input node. */ -public final class TypeProfileProxyNode extends FloatingNode implements Canonicalizable, IterableNodeType, ValueProxy { +public final class TypeProfileProxyNode extends UnaryNode implements Canonicalizable, IterableNodeType, ValueProxy { - @Input private ValueNode object; private final JavaTypeProfile profile; private transient ResolvedJavaType lastCheckedType; private transient JavaTypeProfile lastCheckedProfile; - public ValueNode getObject() { - return object; - } - public static ValueNode create(ValueNode object, JavaTypeProfile profile) { if (StampTool.isExactType(object)) { return object; @@ -61,9 +56,8 @@ return object.graph().addWithoutUnique(new TypeProfileProxyNode(object, profile)); } - private TypeProfileProxyNode(ValueNode object, JavaTypeProfile profile) { - super(object.stamp()); - this.object = object; + private TypeProfileProxyNode(ValueNode value, JavaTypeProfile profile) { + super(value.stamp(), value); this.profile = profile; } @@ -73,16 +67,16 @@ @Override public boolean inferStamp() { - return updateStamp(object.stamp()); + return updateStamp(getValue().stamp()); } @Override public Node canonical(CanonicalizerTool tool) { - if (StampTool.isExactType(object)) { + if (StampTool.isExactType(getValue())) { // The profile is useless - we know the type! - return object; - } else if (object instanceof TypeProfileProxyNode) { - TypeProfileProxyNode other = (TypeProfileProxyNode) object; + return getValue(); + } else if (getValue() instanceof TypeProfileProxyNode) { + TypeProfileProxyNode other = (TypeProfileProxyNode) getValue(); JavaTypeProfile otherProfile = other.getProfile(); if (otherProfile == lastCheckedProfile) { // We have already incorporated the knowledge about this profile => abort. @@ -93,33 +87,33 @@ if (newProfile.equals(otherProfile)) { // We are useless - just use the other proxy node. Debug.log("Canonicalize with other proxy node."); - return object; + return getValue(); } if (newProfile != this.profile) { Debug.log("Improved profile via other profile."); - return TypeProfileProxyNode.create(object, newProfile); + return TypeProfileProxyNode.create(getValue(), newProfile); } - } else if (StampTool.typeOrNull(object) != null) { - ResolvedJavaType type = StampTool.typeOrNull(object); + } else if (StampTool.typeOrNull(getValue()) != null) { + ResolvedJavaType type = StampTool.typeOrNull(getValue()); ResolvedJavaType uniqueConcrete = type.findUniqueConcreteSubtype(); if (uniqueConcrete != null) { // Profile is useless => remove. Debug.log("Profile useless, there is enough static type information available."); - return object; + return getValue(); } if (Objects.equals(type, lastCheckedType)) { // We have already incorporate the knowledge about this type => abort. return this; } lastCheckedType = type; - JavaTypeProfile newProfile = this.profile.restrict(type, StampTool.isObjectNonNull(object)); + JavaTypeProfile newProfile = this.profile.restrict(type, StampTool.isObjectNonNull(getValue())); if (newProfile != this.profile) { Debug.log("Improved profile via static type information."); if (newProfile.getTypes().length == 0) { // Only null profiling is not beneficial enough to keep the node around. - return object; + return getValue(); } - return TypeProfileProxyNode.create(object, newProfile); + return TypeProfileProxyNode.create(getValue(), newProfile); } } return this; @@ -127,6 +121,6 @@ @Override public ValueNode getOriginalNode() { - return object; + return getValue(); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -71,7 +71,7 @@ if (x() instanceof SignExtendNode) { SignExtendNode ext = (SignExtendNode) x(); if (rawY == ((1L << ext.getInputBits()) - 1)) { - ValueNode result = graph().unique(new ZeroExtendNode(ext.getInput(), ext.getResultBits())); + ValueNode result = graph().unique(new ZeroExtendNode(ext.getValue(), ext.getResultBits())); return result; } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -115,8 +115,8 @@ } else if (x() instanceof ConvertNode && y() instanceof ConvertNode) { ConvertNode convertX = (ConvertNode) x(); ConvertNode convertY = (ConvertNode) y(); - if (convertX.preservesOrder(condition()) && convertY.preservesOrder(condition()) && convertX.getInput().stamp().isCompatible(convertY.getInput().stamp())) { - return graph().unique(duplicateModified(convertX.getInput(), convertY.getInput())); + if (convertX.preservesOrder(condition()) && convertY.preservesOrder(condition()) && convertX.getValue().stamp().isCompatible(convertY.getValue().stamp())) { + return graph().unique(duplicateModified(convertX.getValue(), convertY.getValue())); } } @@ -126,20 +126,18 @@ protected abstract CompareNode duplicateModified(ValueNode newX, ValueNode newY); protected Node canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) { - if (nonConstant instanceof BinaryNode) { - if (nonConstant instanceof ConditionalNode) { - return optimizeConditional(constant, (ConditionalNode) nonConstant, tool.getConstantReflection(), mirrored ? condition().mirror() : condition()); - } else if (nonConstant instanceof NormalizeCompareNode) { - return optimizeNormalizeCmp(constant, (NormalizeCompareNode) nonConstant, mirrored); - } + if (nonConstant instanceof ConditionalNode) { + return optimizeConditional(constant, (ConditionalNode) nonConstant, tool.getConstantReflection(), mirrored ? condition().mirror() : condition()); + } else if (nonConstant instanceof NormalizeCompareNode) { + return optimizeNormalizeCmp(constant, (NormalizeCompareNode) nonConstant, mirrored); } else if (nonConstant instanceof ConvertNode) { ConvertNode convert = (ConvertNode) nonConstant; ConstantNode newConstant = canonicalConvertConstant(tool, convert, constant); if (newConstant != null) { if (mirrored) { - return graph().unique(duplicateModified(newConstant, convert.getInput())); + return graph().unique(duplicateModified(newConstant, convert.getValue())); } else { - return graph().unique(duplicateModified(convert.getInput(), newConstant)); + return graph().unique(duplicateModified(convert.getValue(), newConstant)); } } } @@ -150,7 +148,7 @@ if (convert.preservesOrder(condition())) { Constant reverseConverted = convert.reverse(constant); if (convert.convert(reverseConverted).equals(constant)) { - return ConstantNode.forConstant(convert.getInput().stamp(), reverseConverted, tool.getMetaAccess(), convert.graph()); + return ConstantNode.forConstant(convert.getValue().stamp(), reverseConverted, tool.getMetaAccess(), convert.graph()); } } return null; diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -37,9 +37,11 @@ * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note * that these nodes are not built directly from the bytecode but are introduced by canonicalization. */ -public final class ConditionalNode extends BinaryNode implements Canonicalizable, LIRLowerable { +public final class ConditionalNode extends FloatingNode implements Canonicalizable, LIRLowerable { @Input(InputType.Condition) private LogicNode condition; + @Input private ValueNode trueValue; + @Input private ValueNode falseValue; public LogicNode condition() { return condition; @@ -50,38 +52,40 @@ } public ConditionalNode(LogicNode condition, ValueNode trueValue, ValueNode falseValue) { - super(trueValue.stamp().meet(falseValue.stamp()), trueValue, falseValue); + super(trueValue.stamp().meet(falseValue.stamp())); assert trueValue.stamp().isCompatible(falseValue.stamp()); this.condition = condition; + this.trueValue = trueValue; + this.falseValue = falseValue; } @Override public boolean inferStamp() { - return updateStamp(x().stamp().meet(y().stamp())); + return updateStamp(trueValue.stamp().meet(falseValue.stamp())); } public ValueNode trueValue() { - return x(); + return trueValue; } public ValueNode falseValue() { - return y(); + return falseValue; } @Override - public Node canonical(CanonicalizerTool tool) { + public ValueNode canonical(CanonicalizerTool tool) { if (condition instanceof LogicNegationNode) { LogicNegationNode negated = (LogicNegationNode) condition; return graph().unique(new ConditionalNode(negated.getInput(), falseValue(), trueValue())); } // this optimizes the case where a value that can only be 0 or 1 is materialized to 0 or 1 - if (x().isConstant() && y().isConstant() && condition instanceof IntegerEqualsNode) { + if (trueValue().isConstant() && falseValue().isConstant() && condition instanceof IntegerEqualsNode) { IntegerEqualsNode equals = (IntegerEqualsNode) condition; if (equals.y().isConstant() && equals.y().asConstant().equals(Constant.INT_0) && equals.x().stamp() instanceof IntegerStamp) { IntegerStamp equalsXStamp = (IntegerStamp) equals.x().stamp(); if (equalsXStamp.upMask() == 1) { - if (x().asConstant().equals(Constant.INT_0) && y().asConstant().equals(Constant.INT_1)) { + if (trueValue().asConstant().equals(Constant.INT_0) && falseValue().asConstant().equals(Constant.INT_1)) { return IntegerConvertNode.convertUnsigned(equals.x(), stamp()); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -31,17 +31,10 @@ /** * Represents a conversion between primitive types. */ -public abstract class ConvertNode extends FloatingNode implements ArithmeticOperation { - - @Input private ValueNode input; +public abstract class ConvertNode extends UnaryNode implements ArithmeticOperation { - protected ConvertNode(Stamp stamp, ValueNode input) { - super(stamp); - this.input = input; - } - - public ValueNode getInput() { - return input; + protected ConvertNode(Stamp stamp, ValueNode value) { + super(stamp, value); } public abstract Constant convert(Constant c); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -55,12 +55,8 @@ } if (x().isConstant()) { return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - Constant c = y().asConstant(); - if ((c.getKind() == Kind.Float && c.asFloat() == 0.0f) || (c.getKind() == Kind.Double && c.asDouble() == 0.0)) { - return x(); - } } + // Constant 0.0 can't be eliminated since it can affect the sign of the result. return this; } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -95,7 +95,7 @@ @Override public boolean inferStamp() { - return updateStamp(createStamp(op, getInput())); + return updateStamp(createStamp(op, getValue())); } private static Constant convert(FloatConvert op, Constant value) { @@ -148,12 +148,12 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (getInput().isConstant()) { - return ConstantNode.forPrimitive(evalConst(getInput().asConstant()), graph()); - } else if (getInput() instanceof FloatConvertNode) { - FloatConvertNode other = (FloatConvertNode) getInput(); + if (getValue().isConstant()) { + return ConstantNode.forPrimitive(evalConst(getValue().asConstant()), graph()); + } else if (getValue() instanceof FloatConvertNode) { + FloatConvertNode other = (FloatConvertNode) getValue(); if (other.isLossless() && other.op == this.op.reverse()) { - return other.getInput(); + return other.getValue(); } } return this; @@ -164,6 +164,6 @@ } public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getInput()))); + builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getValue()))); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -55,23 +55,8 @@ } if (x().isConstant() && y().isConstant()) { return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - Constant c = y().asConstant(); - if (c.getKind() == Kind.Float) { - float f = c.asFloat(); - if (f == 0.0f) { - return x(); - } - return graph().unique(new FloatAddNode(stamp(), x(), ConstantNode.forFloat(-f, graph()), isStrictFP())); - } else { - assert c.getKind() == Kind.Double; - double d = c.asDouble(); - if (d == 0.0) { - return x(); - } - return graph().unique(new FloatAddNode(stamp(), x(), ConstantNode.forDouble(-d, graph()), isStrictFP())); - } } + // Constant 0.0 can't be eliminated since it can affect the sign of the result. return this; } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -82,9 +82,9 @@ } } if (x() instanceof NegateNode) { - return IntegerArithmeticNode.sub(graph(), y(), ((NegateNode) x()).x()); + return IntegerArithmeticNode.sub(graph(), y(), ((NegateNode) x()).getValue()); } else if (y() instanceof NegateNode) { - return IntegerArithmeticNode.sub(graph(), x(), ((NegateNode) y()).x()); + return IntegerArithmeticNode.sub(graph(), x(), ((NegateNode) y()).getValue()); } return this; } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -45,8 +45,8 @@ } public int getInputBits() { - if (getInput().stamp() instanceof IntegerStamp) { - return ((IntegerStamp) getInput().stamp()).getBits(); + if (getValue().stamp() instanceof IntegerStamp) { + return ((IntegerStamp) getValue().stamp()).getBits(); } else { return 0; } @@ -61,12 +61,12 @@ } protected ValueNode canonicalConvert() { - if (getInput().stamp() instanceof IntegerStamp) { - int inputBits = ((IntegerStamp) getInput().stamp()).getBits(); + if (getValue().stamp() instanceof IntegerStamp) { + int inputBits = ((IntegerStamp) getValue().stamp()).getBits(); if (inputBits == resultBits) { - return getInput(); - } else if (getInput().isConstant()) { - Constant ret = evalConst(getInput().asConstant()); + return getValue(); + } else if (getValue().isConstant()) { + Constant ret = evalConst(getValue().asConstant()); return ConstantNode.forIntegerBits(resultBits, ret.asLong(), graph()); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -112,7 +112,7 @@ return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } if (y() instanceof NegateNode) { - return IntegerArithmeticNode.add(graph(), x(), ((NegateNode) y()).x()); + return IntegerArithmeticNode.add(graph(), x(), ((NegateNode) y()).getValue()); } return this; } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -68,31 +68,31 @@ return ret; } - if (getInput() instanceof NarrowNode) { + if (getValue() instanceof NarrowNode) { // zzzzzzzz yyyyxxxx -(narrow)-> yyyyxxxx -(narrow)-> xxxx // ==> zzzzzzzz yyyyxxxx -(narrow)-> xxxx - NarrowNode other = (NarrowNode) getInput(); - return graph().unique(new NarrowNode(other.getInput(), getResultBits())); - } else if (getInput() instanceof IntegerConvertNode) { + NarrowNode other = (NarrowNode) getValue(); + return graph().unique(new NarrowNode(other.getValue(), getResultBits())); + } else if (getValue() instanceof IntegerConvertNode) { // SignExtendNode or ZeroExtendNode - IntegerConvertNode other = (IntegerConvertNode) getInput(); + IntegerConvertNode other = (IntegerConvertNode) getValue(); if (getResultBits() == other.getInputBits()) { // xxxx -(extend)-> yyyy xxxx -(narrow)-> xxxx // ==> no-op - return other.getInput(); + return other.getValue(); } else if (getResultBits() < other.getInputBits()) { // yyyyxxxx -(extend)-> zzzzzzzz yyyyxxxx -(narrow)-> xxxx // ==> yyyyxxxx -(narrow)-> xxxx - return graph().unique(new NarrowNode(other.getInput(), getResultBits())); + return graph().unique(new NarrowNode(other.getValue(), getResultBits())); } else { if (other instanceof SignExtendNode) { // sxxx -(sign-extend)-> ssssssss sssssxxx -(narrow)-> sssssxxx // ==> sxxx -(sign-extend)-> sssssxxx - return graph().unique(new SignExtendNode(other.getInput(), getResultBits())); + return graph().unique(new SignExtendNode(other.getValue(), getResultBits())); } else if (other instanceof ZeroExtendNode) { // xxxx -(zero-extend)-> 00000000 00000xxx -(narrow)-> 0000xxxx // ==> xxxx -(zero-extend)-> 0000xxxx - return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); + return graph().unique(new ZeroExtendNode(other.getValue(), getResultBits())); } } } @@ -102,11 +102,11 @@ @Override public boolean inferStamp() { - return updateStamp(StampTool.narrowingConversion(getInput().stamp(), getResultBits())); + return updateStamp(StampTool.narrowingConversion(getValue().stamp(), getResultBits())); } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitNarrow(builder.operand(getInput()), getResultBits())); + builder.setResult(this, gen.emitNarrow(builder.operand(getValue()), getResultBits())); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -34,27 +34,20 @@ /** * The {@code NegateNode} node negates its operand. */ -public final class NegateNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable, NarrowableArithmeticNode { - - @Input private ValueNode x; - - public ValueNode x() { - return x; - } +public final class NegateNode extends UnaryNode implements Canonicalizable, ArithmeticLIRLowerable, NarrowableArithmeticNode { @Override public boolean inferStamp() { - return updateStamp(StampTool.negate(x().stamp())); + return updateStamp(StampTool.negate(getValue().stamp())); } /** * Creates new NegateNode instance. * - * @param x the instruction producing the value that is input to this instruction + * @param value the instruction producing the value that is input to this instruction */ - public NegateNode(ValueNode x) { - super(StampTool.negate(x.stamp())); - this.x = x; + public NegateNode(ValueNode value) { + super(StampTool.negate(value.stamp()), value); } public Constant evalConst(Constant... inputs) { @@ -76,14 +69,14 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x.asConstant()), graph()); + if (getValue().isConstant()) { + return ConstantNode.forPrimitive(evalConst(getValue().asConstant()), graph()); } - if (x() instanceof NegateNode) { - return ((NegateNode) x()).x(); + if (getValue() instanceof NegateNode) { + return ((NegateNode) getValue()).getValue(); } - if (x() instanceof IntegerSubNode) { - IntegerSubNode sub = (IntegerSubNode) x; + if (getValue() instanceof IntegerSubNode) { + IntegerSubNode sub = (IntegerSubNode) getValue(); return IntegerArithmeticNode.sub(graph(), sub.y(), sub.x()); } return this; @@ -91,6 +84,6 @@ @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitNegate(builder.operand(x()))); + builder.setResult(this, gen.emitNegate(builder.operand(getValue()))); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -34,17 +34,11 @@ /** * Binary negation of long or integer values. */ -public final class NotNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable, NarrowableArithmeticNode { - - @Input private ValueNode x; - - public ValueNode x() { - return x; - } +public final class NotNode extends UnaryNode implements Canonicalizable, ArithmeticLIRLowerable, NarrowableArithmeticNode { @Override public boolean inferStamp() { - return updateStamp(StampTool.not(x().stamp())); + return updateStamp(StampTool.not(getValue().stamp())); } @Override @@ -59,23 +53,22 @@ * @param x the instruction producing the value that is input to this instruction */ public NotNode(ValueNode x) { - super(StampTool.not(x.stamp())); - this.x = x; + super(StampTool.not(x.stamp()), x); } @Override public Node canonical(CanonicalizerTool tool) { - if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant()), graph()); + if (getValue().isConstant()) { + return ConstantNode.forPrimitive(evalConst(getValue().asConstant()), graph()); } - if (x() instanceof NotNode) { - return ((NotNode) x()).x(); + if (getValue() instanceof NotNode) { + return ((NotNode) getValue()).getValue(); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitNot(builder.operand(x()))); + builder.setResult(this, gen.emitNot(builder.operand(getValue()))); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -36,22 +36,15 @@ * of a primitive value to some other incompatible stamp. The new stamp must have the same width as * the old stamp. */ -public class ReinterpretNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable { - - @Input private ValueNode value; - - public ValueNode value() { - return value; - } +public class ReinterpretNode extends UnaryNode implements Canonicalizable, ArithmeticLIRLowerable { private ReinterpretNode(Kind to, ValueNode value) { this(StampFactory.forKind(to), value); } public ReinterpretNode(Stamp to, ValueNode value) { - super(to); + super(to, value); assert to instanceof PrimitiveStamp; - this.value = value; } public Constant evalConst(Constant... inputs) { @@ -89,15 +82,15 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - return ConstantNode.forPrimitive(evalConst(value.asConstant()), graph()); + if (getValue().isConstant()) { + return ConstantNode.forPrimitive(evalConst(getValue().asConstant()), graph()); } - if (stamp().isCompatible(value.stamp())) { - return value; + if (stamp().isCompatible(getValue().stamp())) { + return getValue(); } - if (value instanceof ReinterpretNode) { - ReinterpretNode reinterpret = (ReinterpretNode) value; - return value.graph().unique(new ReinterpretNode(stamp(), reinterpret.value())); + if (getValue() instanceof ReinterpretNode) { + ReinterpretNode reinterpret = (ReinterpretNode) getValue(); + return getValue().graph().unique(new ReinterpretNode(stamp(), reinterpret.getValue())); } return this; } @@ -105,7 +98,7 @@ @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { LIRKind kind = gen.getLIRKind(stamp()); - builder.setResult(this, gen.emitReinterpret(kind, builder.operand(value()))); + builder.setResult(this, gen.emitReinterpret(kind, builder.operand(getValue()))); } public static ValueNode reinterpret(Kind toKind, ValueNode value) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -74,26 +74,26 @@ return ret; } - if (getInput() instanceof SignExtendNode) { + if (getValue() instanceof SignExtendNode) { // sxxx -(sign-extend)-> ssss sxxx -(sign-extend)-> ssssssss sssssxxx // ==> sxxx -(sign-extend)-> ssssssss sssssxxx - SignExtendNode other = (SignExtendNode) getInput(); - return graph().unique(new SignExtendNode(other.getInput(), getResultBits())); - } else if (getInput() instanceof ZeroExtendNode) { - ZeroExtendNode other = (ZeroExtendNode) getInput(); + SignExtendNode other = (SignExtendNode) getValue(); + return graph().unique(new SignExtendNode(other.getValue(), getResultBits())); + } else if (getValue() instanceof ZeroExtendNode) { + ZeroExtendNode other = (ZeroExtendNode) getValue(); if (other.getResultBits() > other.getInputBits()) { // sxxx -(zero-extend)-> 0000 sxxx -(sign-extend)-> 00000000 0000sxxx // ==> sxxx -(zero-extend)-> 00000000 0000sxxx - return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); + return graph().unique(new ZeroExtendNode(other.getValue(), getResultBits())); } } - if (getInput().stamp() instanceof IntegerStamp) { - IntegerStamp inputStamp = (IntegerStamp) getInput().stamp(); + if (getValue().stamp() instanceof IntegerStamp) { + IntegerStamp inputStamp = (IntegerStamp) getValue().stamp(); if ((inputStamp.upMask() & (1L << (getInputBits() - 1))) == 0L) { // 0xxx -(sign-extend)-> 0000 0xxx // ==> 0xxx -(zero-extend)-> 0000 0xxx - return graph().unique(new ZeroExtendNode(getInput(), getResultBits())); + return graph().unique(new ZeroExtendNode(getValue(), getResultBits())); } } @@ -102,11 +102,11 @@ @Override public boolean inferStamp() { - return updateStamp(StampTool.signExtend(getInput().stamp(), getResultBits())); + return updateStamp(StampTool.signExtend(getValue().stamp(), getResultBits())); } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitSignExtend(builder.operand(getInput()), getInputBits(), getResultBits())); + builder.setResult(this, gen.emitSignExtend(builder.operand(getValue()), getInputBits(), getResultBits())); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, 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.nodes.calc; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodes.*; + +/** + * The {@code UnaryNode} class is the base of arithmetic and bit logic operations with exactly one + * input. + */ +public abstract class UnaryNode extends FloatingNode { + + @Input private ValueNode value; + + public ValueNode getValue() { + return value; + } + + /** + * Creates a new UnaryNode instance. + * + * @param stamp the result type of this instruction + * @param value the input instruction + */ + public UnaryNode(Stamp stamp, ValueNode value) { + super(stamp); + this.value = value; + } +} diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -36,7 +36,6 @@ /** * Used by {@code NodeIntrinsic} in {@code UnsignedMathSubstitutions}. */ - @SuppressWarnings("unused") private UnsignedDivNode(Kind kind, ValueNode x, ValueNode y) { this(StampFactory.forKind(kind), x, y); } @@ -79,4 +78,10 @@ public boolean canDeoptimize() { return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0); } + + @NodeIntrinsic + public static native int unsignedDivide(@ConstantNodeParameter Kind kind, int a, int b); + + @NodeIntrinsic + public static native long unsignedDivide(@ConstantNodeParameter Kind kind, long a, long b); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -36,7 +36,6 @@ /** * Used by {@code NodeIntrinsic} in {@code UnsignedMathSubstitutions}. */ - @SuppressWarnings("unused") private UnsignedRemNode(Kind kind, ValueNode x, ValueNode y) { this(StampFactory.forKind(kind), x, y); } @@ -78,4 +77,10 @@ public boolean canDeoptimize() { return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0); } + + @NodeIntrinsic + public static native int unsignedRemainder(@ConstantNodeParameter Kind kind, int a, int b); + + @NodeIntrinsic + public static native long unsignedRemainder(@ConstantNodeParameter Kind kind, long a, long b); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -84,22 +84,22 @@ return ret; } - if (getInput() instanceof ZeroExtendNode) { + if (getValue() instanceof ZeroExtendNode) { // xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx // ==> xxxx -(zero-extend)-> 00000000 0000xxxx - ZeroExtendNode other = (ZeroExtendNode) getInput(); - return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); + ZeroExtendNode other = (ZeroExtendNode) getValue(); + return graph().unique(new ZeroExtendNode(other.getValue(), getResultBits())); } - if (getInput() instanceof NarrowNode) { - NarrowNode narrow = (NarrowNode) getInput(); - Stamp inputStamp = narrow.getInput().stamp(); + if (getValue() instanceof NarrowNode) { + NarrowNode narrow = (NarrowNode) getValue(); + Stamp inputStamp = narrow.getValue().stamp(); if (inputStamp instanceof IntegerStamp && inputStamp.isCompatible(stamp())) { IntegerStamp istamp = (IntegerStamp) inputStamp; long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(narrow.stamp())); if (((istamp.upMask() | istamp.downMask()) & ~mask) == 0) { // The original value is in the range of the masked zero extended result so // simply return the original input. - return narrow.getInput(); + return narrow.getValue(); } } } @@ -109,11 +109,11 @@ @Override public boolean inferStamp() { - return updateStamp(StampTool.zeroExtend(getInput().stamp(), getResultBits())); + return updateStamp(StampTool.zeroExtend(getValue().stamp(), getResultBits())); } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitZeroExtend(builder.operand(getInput()), getInputBits(), getResultBits())); + builder.setResult(this, gen.emitZeroExtend(builder.operand(getValue()), getInputBits(), getResultBits())); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -39,14 +39,12 @@ * This node represents the boxing of a primitive value. This corresponds to a call to the valueOf * methods in Integer, Long, etc. */ -public class BoxNode extends FloatingNode implements VirtualizableAllocation, Lowerable, Canonicalizable { +public class BoxNode extends UnaryNode implements VirtualizableAllocation, Lowerable, Canonicalizable { - @Input private ValueNode value; private final Kind boxingKind; public BoxNode(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) { - super(StampFactory.exactNonNull(resultType)); - this.value = value; + super(StampFactory.exactNonNull(resultType), value); this.boxingKind = boxingKind; } @@ -54,10 +52,6 @@ return boxingKind; } - public ValueNode getValue() { - return value; - } - @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -24,13 +24,16 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; /** * Loads a method from the virtual method table of a given hub. */ -public final class LoadMethodNode extends FixedWithNextNode implements Lowerable { +public final class LoadMethodNode extends FixedWithNextNode implements Lowerable, Canonicalizable { @Input private ValueNode hub; private final ResolvedJavaMethod method; @@ -55,6 +58,50 @@ tool.getLowerer().lower(this, tool); } + @Override + public Node canonical(CanonicalizerTool tool) { + if (hub instanceof LoadHubNode) { + ValueNode object = ((LoadHubNode) hub).object(); + ResolvedJavaType type = StampTool.typeOrNull(object); + if (StampTool.isExactType(object)) { + return resolveExactMethod(tool, type); + } + if (type != null && tool.assumptions().useOptimisticAssumptions()) { + ResolvedJavaMethod resolvedMethod = type.findUniqueConcreteMethod(method); + if (resolvedMethod != null && !type.isInterface() && method.getDeclaringClass().isAssignableFrom(type)) { + tool.assumptions().recordConcreteMethod(method, type, resolvedMethod); + return ConstantNode.forConstant(resolvedMethod.getEncoding(), tool.getMetaAccess(), graph()); + } + } + } + if (hub.isConstant()) { + return resolveExactMethod(tool, tool.getConstantReflection().asJavaType(hub.asConstant())); + } + + return this; + } + + /** + * Find the method which would be loaded. + * + * @param tool + * @param type the exact type of object being loaded from + * @return the method which would be invoked for {@code type} or null if it doesn't implement + * the method + */ + private Node resolveExactMethod(CanonicalizerTool tool, ResolvedJavaType type) { + ResolvedJavaMethod newMethod = type.resolveMethod(method, type); + if (newMethod == null) { + /* + * This really represent a misuse of LoadMethod since we're loading from a class which + * isn't known to implement the original method but for now at least fold it away. + */ + return ConstantNode.forConstant(Constant.NULL_OBJECT, null, graph()); + } else { + return ConstantNode.forConstant(newMethod.getEncoding(), tool.getMetaAccess(), graph()); + } + } + public ResolvedJavaMethod getMethod() { return method; } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -30,14 +30,12 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public class UnboxNode extends FloatingNode implements Virtualizable, Lowerable, Canonicalizable { +public class UnboxNode extends UnaryNode implements Virtualizable, Lowerable, Canonicalizable { - @Input private ValueNode value; private final Kind boxingKind; public UnboxNode(ValueNode value, Kind boxingKind) { - super(StampFactory.forKind(boxingKind.getStackKind())); - this.value = value; + super(StampFactory.forKind(boxingKind.getStackKind()), value); this.boxingKind = boxingKind; } @@ -45,10 +43,6 @@ return boxingKind; } - public ValueNode getValue() { - return value; - } - @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); @@ -56,7 +50,7 @@ @Override public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(value); + State state = tool.getObjectState(getValue()); if (state != null && state.getState() == EscapeState.Virtual) { ResolvedJavaType objectType = state.getVirtualObject().type(); ResolvedJavaType expectedType = tool.getMetaAccessProvider().lookupJavaType(boxingKind.toBoxedJavaClass()); @@ -68,14 +62,14 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - Constant constant = value.asConstant(); + if (getValue().isConstant()) { + Constant constant = getValue().asConstant(); Constant unboxed = tool.getConstantReflection().unboxPrimitive(constant); if (unboxed != null && unboxed.getKind() == boxingKind) { return ConstantNode.forConstant(unboxed, tool.getMetaAccess(), graph()); } - } else if (value instanceof BoxNode) { - BoxNode box = (BoxNode) value; + } else if (getValue() instanceof BoxNode) { + BoxNode box = (BoxNode) getValue(); if (boxingKind == box.getBoxingKind()) { return box.getValue(); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -141,9 +141,12 @@ ValueNode receiver = receiver(); ResolvedJavaType type = StampTool.typeOrNull(receiver); if (type != null && (invoke().stateAfter() != null || invoke().stateDuring() != null)) { - // either the holder class is exact, or the receiver object has an exact type + /* + * either the holder class is exact, or the receiver object has an exact type, or + * it's an array type + */ ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod, invoke().getContextType()); - if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver))) { + if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) { invokeKind = InvokeKind.Special; targetMethod = resolvedMethod; return this; diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Tue Jun 24 23:29:13 2014 +0200 @@ -195,7 +195,7 @@ return add(stamp1, (IntegerStamp) StampTool.negate(stamp2)); } - private static Stamp stampForMask(int bits, long downMask, long upMask) { + public static Stamp stampForMask(int bits, long downMask, long upMask) { long lowerBound; long upperBound; if (((upMask >>> (bits - 1)) & 1) == 0) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Tue Jun 24 23:29:13 2014 +0200 @@ -94,13 +94,13 @@ } else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) { // not a loop anymore if (tool != null) { - merge.phis().forEach(phi -> phi.usages().forEach(tool::addToWorkList)); + merge.phis().forEach(phi -> tool.addToWorkList(phi.usages())); } graph.reduceDegenerateLoopBegin((LoopBeginNode) merge); } else if (merge.phiPredecessorCount() == 1) { // not a merge anymore if (tool != null) { - merge.phis().forEach(phi -> phi.usages().forEach(tool::addToWorkList)); + merge.phis().forEach(phi -> tool.addToWorkList(phi.usages())); } graph.reduceTrivialMerge(merge); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Tue Jun 24 23:29:13 2014 +0200 @@ -234,7 +234,9 @@ METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); try (Scope s = Debug.scope("CanonicalizeNode", node)) { Node canonical = node.canonical(tool); - return performReplacement(node, canonical); + if (performReplacement(node, canonical)) { + return true; + } } catch (Throwable e) { throw Debug.handle(e); } @@ -248,8 +250,9 @@ } catch (Throwable e) { throw Debug.handle(e); } + return node.isDeleted(); } - return node.isDeleted(); + return false; } // @formatter:off @@ -378,6 +381,10 @@ workList.add(node); } + public void addToWorkList(Iterable nodes) { + workList.addAll(nodes); + } + @Override public void removeIfUnused(Node node) { GraphUtil.tryKillUnused(node); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java Tue Jun 24 23:29:13 2014 +0200 @@ -30,7 +30,7 @@ @Override protected void run(StructuredGraph graph) { for (TypeProfileProxyNode proxy : graph.getNodes(TypeProfileProxyNode.class)) { - graph.replaceFloating(proxy, proxy.getObject()); + graph.replaceFloating(proxy, proxy.getValue()); } assert graph.getNodes(TypeProfileProxyNode.class).count() == 0; } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java Tue Jun 24 23:29:13 2014 +0200 @@ -629,7 +629,7 @@ } TypeProfileProxyNode profile = (TypeProfileProxyNode) object; ObjectStamp outgoinStamp = (ObjectStamp) profile.stamp(); - ObjectStamp payloadStamp = (ObjectStamp) profile.getObject().stamp(); + ObjectStamp payloadStamp = (ObjectStamp) profile.getValue().stamp(); if (payloadStamp.nonNull() && !outgoinStamp.nonNull()) { profile.setStamp(FlowUtil.asNonNullStamp(outgoinStamp)); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Tue Jun 24 23:29:13 2014 +0200 @@ -223,8 +223,10 @@ * @param inlineGraph the graph that the invoke will be replaced with * @param receiverNullCheck true if a null check needs to be generated for non-static inlinings, * false if no such check is required + * @param canonicalizedNodes if non-null then append to this list any nodes which should be + * canonicalized after inlining */ - public static Map inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { + public static Map inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, List canonicalizedNodes) { final NodeInputList parameters = invoke.callTarget().arguments(); FixedNode invokeNode = invoke.asNode(); StructuredGraph graph = invokeNode.graph(); @@ -339,7 +341,7 @@ } MergeNode merge = graph.add(new MergeNode()); merge.setStateAfter(stateAfter); - ValueNode returnValue = mergeReturns(merge, returnDuplicates); + ValueNode returnValue = mergeReturns(merge, returnDuplicates, canonicalizedNodes); invokeNode.replaceAtUsages(returnValue); merge.setNext(n); } @@ -438,7 +440,7 @@ } } - public static ValueNode mergeReturns(MergeNode merge, List returnNodes) { + public static ValueNode mergeReturns(MergeNode merge, List returnNodes, List canonicalizedNodes) { PhiNode returnValuePhi = null; for (ReturnNode returnNode : returnNodes) { @@ -449,6 +451,9 @@ if (returnNode.result() != null) { if (returnValuePhi == null) { returnValuePhi = merge.graph().addWithoutUnique(new ValuePhiNode(returnNode.result().stamp().unrestricted(), merge)); + if (canonicalizedNodes != null) { + canonicalizedNodes.add(returnValuePhi); + } } returnValuePhi.addInput(returnNode.result()); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Tue Jun 24 23:29:13 2014 +0200 @@ -33,9 +33,6 @@ import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph; -import com.oracle.graal.phases.common.inlining.walker.CallsiteHolder; -import com.oracle.graal.phases.common.inlining.walker.CallsiteHolderDummy; -import com.oracle.graal.phases.common.inlining.walker.CallsiteHolderExplorable; import com.oracle.graal.phases.tiers.HighTierContext; public abstract class AbstractInlineInfo implements InlineInfo { @@ -57,22 +54,22 @@ } protected static Collection inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, Assumptions assumptions, boolean receiverNullCheck) { - Collection parameterUsages = new ArrayList<>(); + List canonicalizeNodes = new ArrayList<>(); if (inlineable instanceof InlineableGraph) { StructuredGraph calleeGraph = ((InlineableGraph) inlineable).getGraph(); - Map duplicateMap = InliningUtil.inline(invoke, calleeGraph, receiverNullCheck); - getInlinedParameterUsages(parameterUsages, calleeGraph, duplicateMap); + Map duplicateMap = InliningUtil.inline(invoke, calleeGraph, receiverNullCheck, canonicalizeNodes); + getInlinedParameterUsages(canonicalizeNodes, calleeGraph, duplicateMap); } else { assert inlineable instanceof InlineableMacroNode; Class macroNodeClass = ((InlineableMacroNode) inlineable).getMacroNodeClass(); FixedWithNextNode macroNode = InliningUtil.inlineMacroNode(invoke, concrete, macroNodeClass); - parameterUsages.add(macroNode); + canonicalizeNodes.add(macroNode); } InliningUtil.InlinedBytecodes.add(concrete.getCodeSize()); assumptions.recordMethodContents(concrete); - return parameterUsages; + return canonicalizeNodes; } public static void getInlinedParameterUsages(Collection parameterUsages, StructuredGraph calleeGraph, Map duplicateMap) { @@ -93,14 +90,14 @@ } } - public final CallsiteHolder buildCallsiteHolderForElement(int index, double invokeProbability, double invokeRelevance) { - Inlineable elem = inlineableElementAt(index); - if (elem instanceof InlineableGraph) { - InlineableGraph ig = (InlineableGraph) elem; - return new CallsiteHolderExplorable(ig.getGraph(), invokeProbability * probabilityAt(index), invokeRelevance * relevanceAt(index)); - } else { - assert elem instanceof InlineableMacroNode; - return CallsiteHolderDummy.DUMMY_CALLSITE_HOLDER; + public final int determineNodeCount() { + int nodes = 0; + for (int i = 0; i < numberOfMethods(); i++) { + Inlineable elem = inlineableElementAt(i); + if (elem != null) { + nodes += elem.getNodeCount(); + } } + return nodes; } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Tue Jun 24 23:29:13 2014 +0200 @@ -32,7 +32,6 @@ import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; -import com.oracle.graal.phases.common.inlining.walker.CallsiteHolder; import com.oracle.graal.phases.tiers.HighTierContext; import com.oracle.graal.phases.util.Providers; @@ -88,5 +87,5 @@ void populateInlinableElements(HighTierContext context, Assumptions calleeAssumptions, CanonicalizerPhase canonicalizer); - CallsiteHolder buildCallsiteHolderForElement(int index, double invokeProbability, double invokeRelevance); + int determineNodeCount(); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Tue Jun 24 23:29:13 2014 +0200 @@ -272,13 +272,16 @@ } } - Collection parameterUsages = new ArrayList<>(); + Collection canonicalizeNodes = new ArrayList<>(); // do the actual inlining for every invoke for (int i = 0; i < numberOfMethods; i++) { Invoke invokeForInlining = (Invoke) successors[i].next(); - parameterUsages.addAll(inline(invokeForInlining, methodAt(i), inlineableElementAt(i), assumptions, false)); + canonicalizeNodes.addAll(inline(invokeForInlining, methodAt(i), inlineableElementAt(i), assumptions, false)); } - return parameterUsages; + if (returnValuePhi != null) { + canonicalizeNodes.add(returnValuePhi); + } + return canonicalizeNodes; } private int getTypeCount(int concreteMethodIndex) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java Tue Jun 24 23:29:13 2014 +0200 @@ -32,6 +32,8 @@ public interface Inlineable { static Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, HighTierContext context, CanonicalizerPhase canonicalizer) { + assert method != null; + assert invoke != null; Class macroNodeClass = InliningUtil.getMacroNodeClass(context.getReplacements(), method); if (macroNodeClass != null) { return new InlineableMacroNode(macroNodeClass); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java Tue Jun 24 23:29:13 2014 +0200 @@ -100,17 +100,6 @@ return size; } - protected static int determineNodeCount(InlineInfo info) { - int nodes = 0; - for (int i = 0; i < info.numberOfMethods(); i++) { - Inlineable elem = info.inlineableElementAt(i); - if (elem != null) { - nodes += elem.getNodeCount(); - } - } - return nodes; - } - protected static double determineInvokeProbability(ToDoubleFunction probabilities, InlineInfo info) { double invokeProbability = 0; for (int i = 0; i < info.numberOfMethods(); i++) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java Tue Jun 24 23:29:13 2014 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.nodes.spi.Replacements; import com.oracle.graal.phases.common.inlining.InliningUtil; import com.oracle.graal.phases.common.inlining.info.InlineInfo; +import com.oracle.graal.phases.common.inlining.walker.MethodInvocation; import java.util.Map; import java.util.function.ToDoubleFunction; @@ -54,8 +55,12 @@ } @Override - public boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, InlineInfo info, int inliningDepth, double probability, double relevance, - boolean fullyProcessed) { + public boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) { + + final InlineInfo info = invocation.callee(); + final double probability = invocation.probability(); + final double relevance = invocation.relevance(); + if (InlineEverything.getValue()) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything"); return true; @@ -72,7 +77,7 @@ } double inliningBonus = getInliningBonus(info); - int nodes = determineNodeCount(info); + int nodes = info.determineNodeCount(); int lowLevelGraphSize = previousLowLevelGraphSize(info); if (SmallCompiledLowLevelGraphSize.getValue() > 0 && lowLevelGraphSize > SmallCompiledLowLevelGraphSize.getValue() * inliningBonus) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InlineEverythingPolicy.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InlineEverythingPolicy.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InlineEverythingPolicy.java Tue Jun 24 23:29:13 2014 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.nodes.FixedNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.spi.Replacements; -import com.oracle.graal.phases.common.inlining.info.InlineInfo; +import com.oracle.graal.phases.common.inlining.walker.MethodInvocation; import java.util.function.ToDoubleFunction; @@ -41,8 +41,7 @@ return true; } - public boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, InlineInfo info, int inliningDepth, double probability, double relevance, - boolean fullyProcessed) { + public boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) { return true; } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InliningPolicy.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InliningPolicy.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InliningPolicy.java Tue Jun 24 23:29:13 2014 +0200 @@ -25,7 +25,7 @@ import com.oracle.graal.nodes.FixedNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.spi.Replacements; -import com.oracle.graal.phases.common.inlining.info.InlineInfo; +import com.oracle.graal.phases.common.inlining.walker.MethodInvocation; import java.util.function.ToDoubleFunction; @@ -33,5 +33,5 @@ boolean continueInlining(StructuredGraph graph); - boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, InlineInfo info, int inliningDepth, double probability, double relevance, boolean fullyProcessed); + boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java Tue Jun 24 23:29:13 2014 +0200 @@ -24,12 +24,10 @@ import com.oracle.graal.api.meta.MetaUtil; import com.oracle.graal.api.meta.ResolvedJavaMethod; -import com.oracle.graal.nodes.FixedNode; -import com.oracle.graal.nodes.Invoke; -import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.*; import com.oracle.graal.phases.graph.FixedNodeProbabilityCache; -import java.util.LinkedList; +import java.util.*; import java.util.function.ToDoubleFunction; import static com.oracle.graal.compiler.common.GraalOptions.CapInheritedRelevance; @@ -52,19 +50,30 @@ */ public final class CallsiteHolderExplorable extends CallsiteHolder { + /** + * Graph in which inlining may be performed at one or more of the callsites containined in + * {@link #remainingInvokes} + */ private final StructuredGraph graph; + private final LinkedList remainingInvokes; private final double probability; private final double relevance; + /** + * @see #getFixedParams() + */ + private final Set fixedParams; + private final ToDoubleFunction probabilities; private final ComputeInliningRelevance computeInliningRelevance; - public CallsiteHolderExplorable(StructuredGraph graph, double probability, double relevance) { + public CallsiteHolderExplorable(StructuredGraph graph, double probability, double relevance, BitSet freshlyInstantiatedArguments) { assert graph != null; this.graph = graph; this.probability = probability; this.relevance = relevance; + this.fixedParams = fixedParamsAt(freshlyInstantiatedArguments); remainingInvokes = new InliningIterator(graph).apply(); if (remainingInvokes.isEmpty()) { probabilities = null; @@ -74,6 +83,65 @@ computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities); computeProbabilities(); } + assert repOK(); + } + + /** + * @see #getFixedParams() + */ + @SuppressWarnings("unchecked") + private Set fixedParamsAt(BitSet freshlyInstantiatedArguments) { + if (freshlyInstantiatedArguments == null || freshlyInstantiatedArguments.isEmpty()) { + return Collections.EMPTY_SET; + } + Set result = new HashSet<>(); + for (ParameterNode p : graph.getNodes(ParameterNode.class)) { + if (freshlyInstantiatedArguments.get(p.index())) { + result.add(p); + } + } + return result; + } + + /** + *

+ * Parameters for which the callsite targeting {@link #graph()} provides "fixed" arguments. That + * callsite isn't referenced by this instance. Instead, it belongs to the graph of the caller of + * this {@link CallsiteHolderExplorable} + *

+ * + *

+ * Constant arguments don't contribute to fixed-params: those params have been removed already, + * see {@link com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph}. + *

+ * + *

+ * Instead, fixed-params are those receiving freshly instantiated arguments (possibly + * instantiated several levels up in the call-hierarchy) + *

+ * */ + public Set getFixedParams() { + return fixedParams; + } + + public boolean repOK() { + for (Invoke invoke : remainingInvokes) { + if (!invoke.asNode().isAlive() || !containsInvoke(invoke)) { + assert false; + return false; + } + if (!allArgsNonNull(invoke)) { + assert false; + return false; + } + } + for (ParameterNode fixedParam : fixedParams) { + if (!containsParam(fixedParam)) { + assert false; + return false; + } + } + return true; } @Override @@ -99,6 +167,16 @@ remainingInvokes.push(invoke); } + public static boolean allArgsNonNull(Invoke invoke) { + for (ValueNode arg : invoke.callTarget().arguments()) { + if (arg == null) { + assert false; + return false; + } + } + return true; + } + public boolean containsInvoke(Invoke invoke) { for (Invoke i : graph().getInvokes()) { if (i == invoke) { @@ -108,6 +186,15 @@ return false; } + public boolean containsParam(ParameterNode param) { + for (ParameterNode p : graph.getNodes(ParameterNode.class)) { + if (p == param) { + return true; + } + } + return false; + } + public void computeProbabilities() { computeInliningRelevance.compute(); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Tue Jun 24 23:29:13 2014 +0200 @@ -34,7 +34,9 @@ import com.oracle.graal.graph.Graph; import com.oracle.graal.graph.Node; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.AbstractNewObjectNode; import com.oracle.graal.nodes.java.MethodCallTargetNode; +import com.oracle.graal.nodes.virtual.VirtualObjectNode; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.common.inlining.InliningUtil; @@ -110,8 +112,12 @@ this.maxGraphs = 1; Assumptions rootAssumptions = context.getAssumptions(); - invocationQueue.push(new MethodInvocation(null, rootAssumptions, 1.0, 1.0)); - graphQueue.push(new CallsiteHolderExplorable(rootGraph, 1.0, 1.0)); + invocationQueue.push(new MethodInvocation(null, rootAssumptions, 1.0, 1.0, null)); + graphQueue.push(new CallsiteHolderExplorable(rootGraph, 1.0, 1.0, null)); + } + + public static boolean isFreshInstantiation(ValueNode arg) { + return (arg instanceof AbstractNewObjectNode) || (arg instanceof VirtualObjectNode); } private String checkTargetConditionsHelper(ResolvedJavaMethod method) { @@ -419,7 +425,7 @@ Assumptions callerAssumptions = parentInvocation.assumptions(); metricInliningConsidered.increment(); - if (inliningPolicy.isWorthInlining(probabilities, context.getReplacements(), calleeInfo, inliningDepth, calleeInvocation.probability(), calleeInvocation.relevance(), true)) { + if (inliningPolicy.isWorthInlining(probabilities, context.getReplacements(), calleeInvocation, inliningDepth, true)) { doInline(callerCallsiteHolder, calleeInvocation, callerAssumptions); return true; } @@ -468,11 +474,53 @@ info.populateInlinableElements(context, calleeAssumptions, canonicalizer); double invokeProbability = callsiteHolder.invokeProbability(invoke); double invokeRelevance = callsiteHolder.invokeRelevance(invoke); - MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance); + MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance, freshlyInstantiatedArguments(invoke, callsiteHolder.getFixedParams())); pushInvocationAndGraphs(methodInvocation); } } + /** + *

+ * A freshly instantiated argument is either: + *

    + *
  • an {@link InliningData#isFreshInstantiation(com.oracle.graal.nodes.ValueNode)}
  • + *
  • a fixed-param, ie a {@link ParameterNode} receiving a freshly instantiated argument
  • + *
+ *

+ * + * @return the positions of freshly instantiated arguments in the argument list of the + * invoke, or null if no such positions exist. + */ + public static BitSet freshlyInstantiatedArguments(Invoke invoke, Set fixedParams) { + assert fixedParams != null; + assert paramsAndInvokeAreInSameGraph(invoke, fixedParams); + BitSet result = null; + int argIdx = 0; + for (ValueNode arg : invoke.callTarget().arguments()) { + assert arg != null; + if (isFreshInstantiation(arg) || fixedParams.contains(arg)) { + if (result == null) { + result = new BitSet(); + } + result.set(argIdx); + } + argIdx++; + } + return result; + } + + private static boolean paramsAndInvokeAreInSameGraph(Invoke invoke, Set fixedParams) { + if (fixedParams.isEmpty()) { + return true; + } + for (ParameterNode p : fixedParams) { + if (p.graph() != invoke.asNode().graph()) { + return false; + } + } + return true; + } + public int graphCount() { return graphQueue.size(); } @@ -523,10 +571,8 @@ InlineInfo info = methodInvocation.callee(); maxGraphs += info.numberOfMethods(); assert graphQueue.size() <= maxGraphs; - double invokeProbability = methodInvocation.probability(); - double invokeRelevance = methodInvocation.relevance(); for (int i = 0; i < info.numberOfMethods(); i++) { - CallsiteHolder ch = info.buildCallsiteHolderForElement(i, invokeProbability, invokeRelevance); + CallsiteHolder ch = methodInvocation.buildCallsiteHolderForElement(i); assert (ch == DUMMY_CALLSITE_HOLDER) || !contains(ch.graph()); graphQueue.push(ch); assert graphQueue.size() <= maxGraphs; @@ -636,8 +682,7 @@ final MethodInvocation currentInvocation = currentInvocation(); - final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(probabilities, context.getReplacements(), currentInvocation.callee(), inliningDepth(), - currentInvocation.probability(), currentInvocation.relevance(), false)); + final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(probabilities, context.getReplacements(), currentInvocation, inliningDepth(), false)); if (backtrack) { int remainingGraphs = currentInvocation.totalGraphs() - currentInvocation.processedGraphs(); assert remainingGraphs > 0; diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Tue Jun 24 23:29:13 2014 +0200 @@ -28,6 +28,11 @@ import com.oracle.graal.nodes.CallTargetNode; import com.oracle.graal.nodes.java.MethodCallTargetNode; import com.oracle.graal.phases.common.inlining.info.InlineInfo; +import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; +import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph; +import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; + +import java.util.BitSet; /** *

@@ -49,11 +54,39 @@ private int processedGraphs; - public MethodInvocation(InlineInfo info, Assumptions assumptions, double probability, double relevance) { + /** + *

+ * The immutable positions of freshly instantiated arguments (ie, positions in + * callee.invoke.callTarget.arguments). + *

+ * + *

+ * A freshly instantiated argument is either: + *

    + *
  • an {@link InliningData#isFreshInstantiation(com.oracle.graal.nodes.ValueNode)}
  • + *
  • a fixed-param of the graph containing the callsite (ie, of callee.graph() + * that contains callee.invoke)
  • + *
+ *

+ * + *

+ * Given those positions, the + * {@link com.oracle.graal.phases.common.inlining.walker.CallsiteHolderExplorable} instantiated + * in {@link #buildCallsiteHolderForElement(int)} can determine which of its parameters + * are fixed. + *

+ */ + private final BitSet freshlyInstantiatedArguments; + + private final int sizeFreshArgs; + + public MethodInvocation(InlineInfo info, Assumptions assumptions, double probability, double relevance, BitSet freshlyInstantiatedArguments) { this.callee = info; this.assumptions = assumptions; this.probability = probability; this.relevance = relevance; + this.freshlyInstantiatedArguments = freshlyInstantiatedArguments; + this.sizeFreshArgs = freshlyInstantiatedArguments == null ? 0 : freshlyInstantiatedArguments.cardinality(); } public void incrementProcessedGraphs() { @@ -90,6 +123,27 @@ return callee == null; } + public BitSet getFreshlyInstantiatedArguments() { + return freshlyInstantiatedArguments; + } + + public int getSizeFreshArgs() { + return sizeFreshArgs; + } + + public CallsiteHolder buildCallsiteHolderForElement(int index) { + Inlineable elem = callee.inlineableElementAt(index); + if (elem instanceof InlineableGraph) { + InlineableGraph ig = (InlineableGraph) elem; + final double invokeProbability = probability * callee.probabilityAt(index); + final double invokeRelevance = relevance * callee.relevanceAt(index); + return new CallsiteHolderExplorable(ig.getGraph(), invokeProbability, invokeRelevance, freshlyInstantiatedArguments); + } else { + assert elem instanceof InlineableMacroNode; + return CallsiteHolderDummy.DUMMY_CALLSITE_HOLDER; + } + } + @Override public String toString() { if (isRoot()) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Tue Jun 24 23:29:13 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -299,6 +299,7 @@ for (Position pos : directInputPositions) { writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1); writePoolObject(nodeClass.getName(pos)); + writePoolObject(nodeClass.getInputType(pos)); } Collection directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions(); writeShort((char) directSuccessorPositions.size()); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Tue Jun 24 23:29:13 2014 +0200 @@ -181,8 +181,8 @@ StructuredGraph graph = convert.graph(); Arguments args = new Arguments(key, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("input", convert.getInput()); - args.add("result", graph.unique(new AMD64FloatConvertNode(convert.stamp(), convert.getOp(), convert.getInput()))); + args.add("input", convert.getValue()); + args.add("result", graph.unique(new AMD64FloatConvertNode(convert.stamp(), convert.getOp(), convert.getValue()))); SnippetTemplate template = template(args); Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getOp(), graph, convert, template, args); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -36,15 +36,13 @@ * of the {@link FloatConvertNode} which, on AMD64 needs a {@link AMD64FloatConvertNode} plus some * fixup code that handles the corner cases that differ between AMD64 and Java. */ -public class AMD64FloatConvertNode extends FloatingNode implements ArithmeticLIRLowerable { +public class AMD64FloatConvertNode extends UnaryNode implements ArithmeticLIRLowerable { private final FloatConvert op; - @Input private ValueNode value; public AMD64FloatConvertNode(Stamp stamp, FloatConvert op, ValueNode value) { - super(stamp); + super(stamp, value); this.op = op; - this.value = value; } public Constant evalConst(Constant... inputs) { @@ -53,6 +51,6 @@ } public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitFloatConvert(op, builder.operand(value))); + builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getValue()))); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Tue Jun 24 23:29:13 2014 +0200 @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2012, 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.replacements.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.inlining.*; +import com.oracle.graal.phases.tiers.*; + +public class BitOpNodesTest extends GraalCompilerTest { + + private static final int INT_CONSTANT_1 = 0x80100010; + private static final int INT_CONSTANT_2 = 0x00011110; + private static final int INT_CONSTANT_3 = 0x00000000; + + private static final long LONG_CONSTANT_1 = 0x8000000000100010L; + private static final long LONG_CONSTANT_2 = 0x0000000000011110L; + private static final long LONG_CONSTANT_3 = 0x0000000000000000L; + + public static long dummyField; + + /* + * Tests for BitCountNode canonicalizations. + */ + + public static int bitCountIntConstantSnippet() { + return Integer.bitCount(INT_CONSTANT_1) + Integer.bitCount(INT_CONSTANT_2) + Integer.bitCount(INT_CONSTANT_3); + } + + @Test + public void testBitCountIntConstant() { + ValueNode result = parseAndInline("bitCountIntConstantSnippet"); + Assert.assertEquals(7, result.asConstant().asInt()); + } + + public static int bitCountLongConstantSnippet() { + return Long.bitCount(LONG_CONSTANT_1) + Long.bitCount(LONG_CONSTANT_2) + Long.bitCount(LONG_CONSTANT_3); + } + + public static int bitCountIntSnippet(int v) { + return Integer.bitCount(v & 0xFFFFFF | 0xFF); + } + + @Test + public void testBitCountInt() { + ValueNode result = parseAndInline("bitCountIntSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 8, 24), result.stamp()); + } + + public static int bitCountIntEmptySnippet(int v) { + return Integer.bitCount(v & 0xFFFFFF); + } + + @Test + public void testBitCountIntEmpty() { + ValueNode result = parseAndInline("bitCountIntEmptySnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 0, 24), result.stamp()); + } + + @Test + public void testBitCountLongConstant() { + ValueNode result = parseAndInline("bitCountLongConstantSnippet"); + Assert.assertEquals(7, result.asConstant().asInt()); + } + + public static int bitCountLongSnippet(long v) { + return Long.bitCount(v & 0xFFFFFFFFFFL | 0xFFL); + } + + @Test + public void testBitCountLong() { + ValueNode result = parseAndInline("bitCountLongSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 8, 40), result.stamp()); + } + + public static int bitCountLongEmptySnippet(long v) { + return Long.bitCount(v & 0xFFFFFFFFFFL); + } + + @Test + public void testBitCountLongEmpty() { + ValueNode result = parseAndInline("bitCountLongEmptySnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 0, 40), result.stamp()); + } + + /* + * Tests for BitScanForwardNode + */ + + public static int scanForwardIntConstantSnippet() { + return Integer.numberOfTrailingZeros(INT_CONSTANT_1) + Integer.numberOfTrailingZeros(INT_CONSTANT_2) + Integer.numberOfTrailingZeros(INT_CONSTANT_3); + } + + @Test + public void testScanForwardIntConstant() { + ValueNode result = parseAndInline("scanForwardIntConstantSnippet"); + Assert.assertEquals(40, result.asConstant().asInt()); + } + + public static int scanForwardIntSnippet(int v) { + return Integer.numberOfTrailingZeros(v & 0xFFF0 | 0xFF00); + } + + @Test + public void testScanForwardInt() { + ValueNode result = parseAndInline("scanForwardIntSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 4, 8), result.stamp()); + } + + public static int scanForwardLongConstantSnippet() { + return Long.numberOfTrailingZeros(LONG_CONSTANT_1) + Long.numberOfTrailingZeros(LONG_CONSTANT_2) + Long.numberOfTrailingZeros(LONG_CONSTANT_3); + } + + @Test + public void testScanForwardLongConstant() { + ValueNode result = parseAndInline("scanForwardLongConstantSnippet"); + Assert.assertEquals(72, result.asConstant().asInt()); + } + + public static int scanForwardLongSnippet(long v) { + return Long.numberOfTrailingZeros(v & 0xFFFF000000L | 0xFF00000000L); + } + + @Test + public void testScanForwardLong() { + ValueNode result = parseAndInline("scanForwardLongSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 32), result.stamp()); + } + + public static int scanForwardLongEmptySnippet(long v) { + int result = Long.numberOfTrailingZeros(v & 0xFFFF000000L); + dummyField = result; + return result; + } + + @Test + public void testScanForwardLongEmpty() { + ValueNode result = parseAndInline("scanForwardLongEmptySnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, -1, 64), result.stamp()); + } + + /* + * Tests for BitScanReverseNode + */ + + public static int scanReverseIntConstantSnippet() { + return Integer.numberOfLeadingZeros(INT_CONSTANT_1) + Integer.numberOfLeadingZeros(INT_CONSTANT_2) + Integer.numberOfLeadingZeros(INT_CONSTANT_3); + } + + @Test + public void testScanReverseIntConstant() { + ValueNode result = parseAndInline("scanReverseIntConstantSnippet"); + Assert.assertEquals(47, result.asConstant().asInt()); + } + + public static int scanReverseIntSnippet(int v) { + return Integer.numberOfLeadingZeros(v & 0xFFF0 | 0xFF0); + } + + @Test + public void testScanReverseInt() { + ValueNode result = parseAndInline("scanReverseIntSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 16, 20), result.stamp()); + } + + public static int scanReverseLongConstantSnippet() { + return Long.numberOfLeadingZeros(LONG_CONSTANT_1) + Long.numberOfLeadingZeros(LONG_CONSTANT_2) + Long.numberOfLeadingZeros(LONG_CONSTANT_3); + } + + @Test + public void testScanReverseLongConstant() { + ValueNode result = parseAndInline("scanReverseLongConstantSnippet"); + Assert.assertEquals(111, result.asConstant().asInt()); + } + + public static int scanReverseLongSnippet(long v) { + int result = Long.numberOfLeadingZeros(v & 0xFFF0); + dummyField = result; + return result; + } + + @Test + public void testScanReverseLong() { + ValueNode result = parseAndInline("scanReverseLongSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 48, 64), result.stamp()); + } + + public static int scanReverseLongEmptySnippet(long v) { + int result = Long.numberOfLeadingZeros(v & 0xFFFF000000L); + dummyField = result; + return result; + } + + @Test + public void testScanReverseLongEmpty() { + ValueNode result = parseAndInline("scanReverseLongEmptySnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 64), result.stamp()); + } + + private ValueNode parseAndInline(String name) { + StructuredGraph graph = parse(name); + HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); + canonicalizer.apply(graph, context); + new InliningPhase(canonicalizer).apply(graph, context); + canonicalizer.apply(graph, context); + Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); + return graph.getNodes(ReturnNode.class).first().result(); + } +} diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Tue Jun 24 23:29:13 2014 +0200 @@ -114,7 +114,7 @@ SignExtendNode convert = (SignExtendNode) location.getIndex(); Assert.assertEquals(convert.getInputBits(), 32); Assert.assertEquals(convert.getResultBits(), 64); - Assert.assertEquals(graph.getParameter(1), convert.getInput()); + Assert.assertEquals(graph.getParameter(1), convert.getValue()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } @@ -138,7 +138,7 @@ SignExtendNode convert = (SignExtendNode) location.getIndex(); Assert.assertEquals(convert.getInputBits(), 32); Assert.assertEquals(convert.getResultBits(), 64); - Assert.assertEquals(graph.getParameter(1), convert.getInput()); + Assert.assertEquals(graph.getParameter(1), convert.getValue()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Tue Jun 24 23:29:13 2014 +0200 @@ -125,7 +125,7 @@ SignExtendNode convert = (SignExtendNode) location.getIndex(); Assert.assertEquals(convert.getInputBits(), 32); Assert.assertEquals(convert.getResultBits(), 64); - Assert.assertEquals(graph.getParameter(1), convert.getInput()); + Assert.assertEquals(graph.getParameter(1), convert.getValue()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } @@ -154,7 +154,7 @@ SignExtendNode convert = (SignExtendNode) location.getIndex(); Assert.assertEquals(convert.getInputBits(), 32); Assert.assertEquals(convert.getResultBits(), 64); - Assert.assertEquals(graph.getParameter(1), convert.getInput()); + Assert.assertEquals(graph.getParameter(1), convert.getValue()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Tue Jun 24 23:29:13 2014 +0200 @@ -109,7 +109,7 @@ StructuredGraph graph = loadField.graph(); ResolvedJavaField field = loadField.field(); ValueNode object = loadField.isStatic() ? staticFieldBase(graph, field) : loadField.object(); - Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind(), true); + Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind()); ConstantLocationNode location = createFieldLocation(graph, field, false); assert location != null : "Field that is loaded must not be eliminated"; @@ -158,7 +158,7 @@ StructuredGraph graph = loadIndexed.graph(); Kind elementKind = loadIndexed.elementKind(); LocationNode location = createArrayLocation(graph, elementKind, loadIndexed.index(), false); - Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind, true); + Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind); ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), location, loadStamp, BarrierType.NONE)); ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead); @@ -503,6 +503,10 @@ protected abstract LocationIdentity initLocationIdentity(); + public Stamp loadStamp(Stamp stamp, Kind kind) { + return loadStamp(stamp, kind, true); + } + protected Stamp loadStamp(Stamp stamp, Kind kind, @SuppressWarnings("unused") boolean compressible) { switch (kind) { case Boolean: @@ -580,7 +584,7 @@ SignExtendNode extend = (SignExtendNode) offset; if (extend.getResultBits() == 64) { signExtend = true; - offset = extend.getInput(); + offset = extend.getValue(); } } if (offset instanceof IntegerAddNode) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Tue Jun 24 23:29:13 2014 +0200 @@ -208,7 +208,7 @@ ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); ReplacementsImpl repl = new ReplacementsImpl(providers, snippetReflection, new Assumptions(false), providers.getCodeCache().getTarget()); StructuredGraph calleeGraph = repl.makeGraph(method, null, method, null, FrameStateProcessing.CollapseFrameForSingleSideEffect); - InliningUtil.inline(invoke, calleeGraph, false); + InliningUtil.inline(invoke, calleeGraph, false, null); } protected void pushStructure(Structure structure) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java Tue Jun 24 23:29:13 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -22,7 +22,9 @@ */ package com.oracle.graal.replacements; +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.replacements.nodes.*; @ClassSubstitution(Integer.class) @@ -53,4 +55,14 @@ public static int bitCount(int i) { return BitCountNode.bitCount(i); } + + @MethodSubstitution + public static int divideUnsigned(int dividend, int divisor) { + return UnsignedDivNode.unsignedDivide(Kind.Int, dividend, divisor); + } + + @MethodSubstitution + public static int remainderUnsigned(int dividend, int divisor) { + return UnsignedRemNode.unsignedRemainder(Kind.Int, dividend, divisor); + } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java Tue Jun 24 23:29:13 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -22,7 +22,9 @@ */ package com.oracle.graal.replacements; +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.replacements.nodes.*; @ClassSubstitution(Long.class) @@ -53,4 +55,14 @@ public static int bitCount(long i) { return BitCountNode.bitCount(i); } + + @MethodSubstitution + public static long divideUnsigned(long dividend, long divisor) { + return UnsignedDivNode.unsignedDivide(Kind.Long, dividend, divisor); + } + + @MethodSubstitution + public static long remainderUnsigned(long dividend, long divisor) { + return UnsignedRemNode.unsignedRemainder(Kind.Long, dividend, divisor); + } } diff -r 38bb9b5b8544 -r 6140fd60abe9 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 Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Tue Jun 24 23:29:13 2014 +0200 @@ -589,7 +589,7 @@ if (isInlinable(substitutedMethod)) { final StructuredGraph originalGraph = buildInitialGraph(substitutedMethod); Mark mark = graph.getMark(); - InliningUtil.inline(callTarget.invoke(), originalGraph, true); + InliningUtil.inline(callTarget.invoke(), originalGraph, true, null); for (MethodCallTargetNode inlinedCallTarget : graph.getNewNodes(mark).filter(MethodCallTargetNode.class)) { if (doNotInline == null) { doNotInline = new HashSet<>(); @@ -623,7 +623,7 @@ targetGraph = parseGraph(callee, policy, inliningDepth + 1); } Object beforeInlineData = beforeInline(callTarget, targetGraph); - InliningUtil.inline(callTarget.invoke(), targetGraph, true); + InliningUtil.inline(callTarget.invoke(), targetGraph, true, null); Debug.dump(graph, "after inlining %s", callee); afterInline(graph, targetGraph, beforeInlineData); } diff -r 38bb9b5b8544 -r 6140fd60abe9 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 Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Tue Jun 24 23:29:13 2014 +0200 @@ -705,7 +705,7 @@ this.memoryMap = memMaps.get(0); } else { MergeNode merge = snippet.add(new MergeNode()); - ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes); + ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes, null); this.returnNode = snippet.add(new ReturnNode(returnValue)); this.memoryMap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps); merge.setNext(this.returnNode); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -30,19 +30,25 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public class BitCountNode extends FloatingNode implements LIRLowerable, Canonicalizable { - - @Input private ValueNode value; +public class BitCountNode extends UnaryNode implements LIRLowerable, Canonicalizable { public BitCountNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits())); - this.value = value; + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; + } + + @Override + public boolean inferStamp() { + IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); + assert (valueStamp.downMask() & IntegerStamp.defaultMask(valueStamp.getBits())) == valueStamp.downMask(); + assert (valueStamp.upMask() & IntegerStamp.defaultMask(valueStamp.getBits())) == valueStamp.upMask(); + return updateStamp(StampFactory.forInteger(Kind.Int, bitCount(valueStamp.downMask()), bitCount(valueStamp.upMask()))); } @Override public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - Constant c = value.asConstant(); + if (getValue().isConstant()) { + Constant c = getValue().asConstant(); if (c.getKind() == Kind.Int) { return ConstantNode.forInt(Integer.bitCount(c.asInt()), graph()); } else if (c.getKind() == Kind.Long) { @@ -64,7 +70,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Value result = gen.getLIRGeneratorTool().emitBitCount(gen.operand(value)); + Value result = gen.getLIRGeneratorTool().emitBitCount(gen.operand(getValue())); gen.setResult(this, result); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -24,32 +24,34 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public class BitScanForwardNode extends FloatingNode implements LIRLowerable, Canonicalizable { - - @Input private ValueNode value; +public class BitScanForwardNode extends UnaryNode implements LIRLowerable { public BitScanForwardNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits())); - this.value = value; + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } @Override - public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - Constant c = value.asConstant(); - if (c.getKind() == Kind.Int) { - return ConstantNode.forInt(Integer.numberOfTrailingZeros(c.asInt()), graph()); - } else if (c.getKind() == Kind.Long) { - return ConstantNode.forInt(Long.numberOfTrailingZeros(c.asLong()), graph()); - } + public boolean inferStamp() { + IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); + int min; + int max; + long mask = IntegerStamp.defaultMask(valueStamp.getBits()); + int firstAlwaysSetBit = scan(valueStamp.downMask() & mask); + if (firstAlwaysSetBit == -1) { + int lastMaybeSetBit = BitScanReverseNode.scan(valueStamp.upMask() & mask); + min = -1; + max = lastMaybeSetBit; + } else { + int firstMaybeSetBit = scan(valueStamp.upMask() & mask); + min = firstMaybeSetBit; + max = firstAlwaysSetBit; } - return this; + return updateStamp(StampFactory.forInteger(Kind.Int, min, max)); } @NodeIntrinsic @@ -71,7 +73,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Value result = gen.getLIRGeneratorTool().emitBitScanForward(gen.operand(value)); + Value result = gen.getLIRGeneratorTool().emitBitScanForward(gen.operand(getValue())); gen.setResult(this, result); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -24,32 +24,32 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public class BitScanReverseNode extends FloatingNode implements LIRLowerable, Canonicalizable { - - @Input private ValueNode value; +public class BitScanReverseNode extends UnaryNode implements LIRLowerable { public BitScanReverseNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits())); - this.value = value; + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } @Override - public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - Constant c = value.asConstant(); - if (c.getKind() == Kind.Int) { - return ConstantNode.forInt(31 - Integer.numberOfLeadingZeros(c.asInt()), graph()); - } else if (c.getKind() == Kind.Long) { - return ConstantNode.forInt(63 - Long.numberOfLeadingZeros(c.asLong()), graph()); - } + public boolean inferStamp() { + IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); + int min; + int max; + long mask = IntegerStamp.defaultMask(valueStamp.getBits()); + int lastAlwaysSetBit = scan(valueStamp.downMask() & mask); + if (lastAlwaysSetBit == -1) { + min = -1; + } else { + min = lastAlwaysSetBit; } - return this; + int lastMaybeSetBit = scan(valueStamp.upMask() & mask); + max = lastMaybeSetBit; + return updateStamp(StampFactory.forInteger(Kind.Int, min, max)); } @NodeIntrinsic @@ -78,7 +78,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Value result = gen.getLIRGeneratorTool().emitBitScanReverse(gen.operand(value)); + Value result = gen.getLIRGeneratorTool().emitBitScanReverse(gen.operand(getValue())); gen.setResult(this, result); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -142,7 +142,7 @@ ((Lowerable) nonNullReceiver).lower(tool); } } - InliningUtil.inline(invoke, replacementGraph, false); + InliningUtil.inline(invoke, replacementGraph, false, null); Debug.dump(graph(), "After inlining replacement %s", replacementGraph); } else { invoke.lower(tool); diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -24,33 +24,31 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; -public class ReverseBytesNode extends FloatingNode implements LIRLowerable, Canonicalizable { - - @Input private ValueNode value; +public class ReverseBytesNode extends UnaryNode implements LIRLowerable { public ReverseBytesNode(ValueNode value) { - super(StampFactory.forKind(value.getKind())); - assert getKind().isNumericInteger(); - this.value = value; + super(StampFactory.forKind(value.getKind()), value); + assert getKind() == Kind.Int || getKind() == Kind.Long; } @Override - public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - long v = value.asConstant().asLong(); - if (getKind().getStackKind() == Kind.Int) { - return ConstantNode.forInt(Integer.reverseBytes((int) v), graph()); - } else if (getKind() == Kind.Long) { - return ConstantNode.forLong(Long.reverseBytes(v), graph()); - } + public boolean inferStamp() { + IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); + Stamp newStamp; + if (getKind() == Kind.Int) { + long mask = IntegerStamp.defaultMask(Kind.Int.getBitCount()); + newStamp = StampTool.stampForMask(valueStamp.getBits(), reverse((int) valueStamp.downMask()) & mask, reverse((int) valueStamp.upMask()) & mask); + } else if (getKind() == Kind.Long) { + newStamp = StampTool.stampForMask(valueStamp.getBits(), reverse(valueStamp.downMask()), reverse(valueStamp.upMask())); + } else { + return false; } - return this; + return updateStamp(newStamp); } @NodeIntrinsic @@ -65,7 +63,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Value result = gen.getLIRGeneratorTool().emitByteSwap(gen.operand(value)); + Value result = gen.getLIRGeneratorTool().emitByteSwap(gen.operand(getValue())); gen.setResult(this, result); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 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 Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Tue Jun 24 23:29:13 2014 +0200 @@ -214,7 +214,7 @@ expansionLogger.preExpand(methodCallTargetNode, inlineGraph); } List canonicalizedNodes = methodCallTargetNode.invoke().asNode().usages().snapshot(); - Map inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false); + Map inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false, canonicalizedNodes); if (TraceTruffleExpansion.getValue()) { expansionLogger.postExpand(inlined); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Tue Jun 24 23:29:13 2014 +0200 @@ -244,7 +244,7 @@ ", must annotate such calls with @CompilerDirectives.SlowPath!")); } Invoke invoke = methodCallTargetNode.invoke(); - InliningUtil.inline(invoke, inlineGraph, true); + InliningUtil.inline(invoke, inlineGraph, true, null); } private boolean tryCutOffRuntimeExceptions(MethodCallTargetNode methodCallTargetNode) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Tue Jun 24 23:29:13 2014 +0200 @@ -154,7 +154,7 @@ } private static String formatSourceSection(SourceSection sourceSection) { - return sourceSection != null ? sourceSection.toString() : "n/a"; + return sourceSection != null ? sourceSection.getShortDescription() : "n/a"; } public CompilationResult compileMethodHelper(StructuredGraph graph, Assumptions assumptions, String name, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Tue Jun 24 23:29:13 2014 +0200 @@ -54,7 +54,7 @@ } else { StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTarget.targetMethod()); if (inlineGraph != null) { - InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, true); + InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, true, null); Debug.dump(graph, "After inlining %s", methodCallTarget.targetMethod().toString()); } } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Tue Jun 24 23:29:13 2014 +0200 @@ -109,6 +109,16 @@ } /** + * Has a {@link Probe} been created that is uniquely associated with a particular source code + * location. + * + * @return a probe uniquely associated with an extent of guest language source code. + */ + public final boolean hasProbe(SourceSection sourceSection) { + return probeManager.hasProbe(sourceSection); + } + + /** * Returns all existing probes with specific tag, or all probes if {@code tag = null}; empty * collection if no probes found. */ diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Tue Jun 24 23:29:13 2014 +0200 @@ -72,6 +72,13 @@ */ public static NodeCost TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost")); + /** + * Enables the dumping of Node creations and AST rewrites in JSON format. + *

+ * Can be set with {@code -Dtruffle.TraceASTJSON=true}. + */ + public static final boolean TraceASTJSON = Boolean.getBoolean("truffle.TraceASTJSON"); + private static NodeCost parseNodeInfoKind(String kind) { if (kind == null) { return null; diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java Tue Jun 24 23:29:13 2014 +0200 @@ -119,6 +119,11 @@ return probe; } + public boolean hasProbe(SourceSection sourceSection) { + assert sourceSection != null; + return srcToProbe.get(sourceSection) != null; + } + public Collection findProbesTaggedAs(PhylumTag tag) { final List probes = new ArrayList<>(); for (Probe probe : srcToProbe.values()) { diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Tue Jun 24 23:29:13 2014 +0200 @@ -31,6 +31,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.source.*; +import com.oracle.truffle.api.utilities.*; /** * Abstract base class for all Truffle nodes. @@ -58,12 +59,15 @@ } protected Node() { - CompilerAsserts.neverPartOfCompilation(); + this(null); } protected Node(SourceSection sourceSection) { CompilerAsserts.neverPartOfCompilation(); this.sourceSection = sourceSection; + if (TruffleOptions.TraceASTJSON) { + JSONHelper.dumpNewNode(this); + } } /** @@ -169,6 +173,9 @@ } boolean isInserted = newChild.parent == null; newChild.parent = this; + if (TruffleOptions.TraceASTJSON) { + JSONHelper.dumpNewChild(this, newChild); + } newChild.adoptHelper(); if (isInserted) { newChild.onAdopt(); @@ -273,6 +280,9 @@ this.parent.adoptUnadoptedHelper(newNode); } reportReplace(this, newNode, reason); + if (TruffleOptions.TraceASTJSON) { + JSONHelper.dumpReplaceChild(this, newNode, reason); + } onReplace(newNode, reason); } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java Tue Jun 24 23:29:13 2014 +0200 @@ -0,0 +1,122 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.utilities; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; + +/** + * Helper function that allows to dump the AST during creation to a JSON format. + */ +public class JSONHelper { + + private static StringBuilder AstJsonDumpBuilder = new StringBuilder(); + + public static void dumpNewChild(Node parentNode, Node childNode) { + if (AstJsonDumpBuilder != null) { + AstJsonDumpBuilder.append("{ \"action\": \"insertNode\", \"parentId\": \"" + getID(parentNode) + "\", \"newId\": \"" + getID(childNode) + "\" },\n"); + } + } + + public static void dumpReplaceChild(Node oldNode, Node newNode, CharSequence reason) { + if (AstJsonDumpBuilder != null) { + AstJsonDumpBuilder.append("{ \"action\": \"replaceNode\", \"oldId\": \"" + getID(oldNode) + "\", \"newId\": \"" + getID(newNode) + "\", \"reason\": " + quote(reason) + " },\n"); + } + } + + public static void dumpNewNode(Node newNode) { + if (AstJsonDumpBuilder != null) { + AstJsonDumpBuilder.append("{ \"action\": \"createNode\", \"newId\": \"" + getID(newNode) + "\", \"type\": \"" + getType(newNode) + "\", \"description\": \"" + newNode.getDescription() + + "\", \"language\": \"" + newNode.getLanguage() + "\"" + getSourceSectionInfo(newNode) + " },\n"); + } + } + + private static String getSourceSectionInfo(Node newNode) { + SourceSection sourceSection = newNode.getSourceSection(); + if (sourceSection != null) { + return ", \"identifier\": \"" + sourceSection.getIdentifier() + "\" "; + } else { + return ""; + } + } + + public static String getResult() { + return AstJsonDumpBuilder.toString(); + } + + private static String getID(Node newChild) { + return String.valueOf(newChild.hashCode()); + } + + private static String getType(Node node) { + return node.getClass().getSimpleName(); + } + + private static String quote(CharSequence value) { + StringBuilder builder = new StringBuilder(value.length() + 2); + builder.append('"'); + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + switch (c) { + case '"': + builder.append("\\\""); + break; + case '\\': + builder.append("\\\\"); + break; + case '\b': + builder.append("\\b"); + break; + case '\f': + builder.append("\\f"); + break; + case '\n': + builder.append("\\n"); + break; + case '\r': + builder.append("\\r"); + break; + case '\t': + builder.append("\\t"); + break; + default: { + if (c < ' ') { + builder.append("\\u00"); + builder.append(Character.forDigit((c >> 4) & 0xF, 16)); + builder.append(Character.forDigit(c & 0xF, 16)); + } else { + builder.append(c); + } + } + } + } + builder.append('"'); + return builder.toString(); + } + + public static void restart() { + AstJsonDumpBuilder = new StringBuilder(); + } +} diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -41,10 +41,6 @@ @Children private final SLStatementNode[] bodyNodes; public SLBlockNode(SLStatementNode[] bodyNodes) { - /* - * It is a Truffle requirement to call adoptChildren(), which performs all the necessary - * steps to add the new children to the node tree. - */ this.bodyNodes = bodyNodes; } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -50,10 +50,6 @@ private final BranchProfile nullTaken = new BranchProfile(); public SLFunctionBodyNode(SLStatementNode bodyNode) { - /* - * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps - * to add the new child to the node tree. - */ this.bodyNode = bodyNode; } diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -53,10 +53,6 @@ private final BranchProfile elseTaken = new BranchProfile(); public SLIfNode(SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) { - /* - * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps - * to add the new child to the node tree. - */ this.conditionNode = conditionNode; this.thenPartNode = thenPartNode; this.elsePartNode = elsePartNode; diff -r 38bb9b5b8544 -r 6140fd60abe9 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java Tue Jun 24 23:24:02 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java Tue Jun 24 23:29:13 2014 +0200 @@ -51,10 +51,6 @@ private final BranchProfile breakTaken = new BranchProfile(); public SLWhileNode(SLExpressionNode conditionNode, SLStatementNode bodyNode) { - /* - * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps - * to add the new child to the node tree. - */ this.conditionNode = conditionNode; this.bodyNode = bodyNode; } diff -r 38bb9b5b8544 -r 6140fd60abe9 mx/mx_graal.py --- a/mx/mx_graal.py Tue Jun 24 23:24:02 2014 +0200 +++ b/mx/mx_graal.py Tue Jun 24 23:29:13 2014 +0200 @@ -1868,6 +1868,20 @@ def isGraalEnabled(vm): return vm != 'original' and not vm.endswith('nograal') +def jol(args): + """Java Object Layout""" + jolurl = "http://lafo.ssw.uni-linz.ac.at/truffle/jol/jol-internals.jar" + joljar = "lib/jol-internals.jar" + if not exists(joljar): + mx.download(joljar, [jolurl]) + + candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s)) + if len(candidates) > 10: + print "Found %d candidates. Please be more precise." % (len(candidates)) + return + + vm(['-javaagent:' + joljar, '-cp', os.pathsep.join([mx.classpath(), joljar]), "org.openjdk.jol.MainObjectInternals"] + candidates) + def site(args): """create a website containing javadoc and the project dependency graph""" @@ -2094,7 +2108,8 @@ 'vmfg': [vmfg, '[-options] class [args...]'], 'deoptalot' : [deoptalot, '[n]'], 'longtests' : [longtests, ''], - 'sl' : [sl, '[SL args|@VM options]'] + 'sl' : [sl, '[SL args|@VM options]'], + 'jol' : [jol, ''], } mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append']) diff -r 38bb9b5b8544 -r 6140fd60abe9 mxtool/mx.py --- a/mxtool/mx.py Tue Jun 24 23:24:02 2014 +0200 +++ b/mxtool/mx.py Tue Jun 24 23:29:13 2014 +0200 @@ -4488,7 +4488,7 @@ return kwargs.pop(0) return None -def findclass(args, logToConsole=True): +def findclass(args, logToConsole=True, matcher=lambda string, classname: string in classname): """find all classes matching a given substring""" matches = [] for entry, filename in classpath_walk(includeBootClasspath=True): @@ -4499,7 +4499,7 @@ classname = filename.replace(os.sep, '.') classname = classname[:-len('.class')] for a in args: - if a in classname: + if matcher(a, classname): matches.append(classname) if logToConsole: log(classname) diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java Tue Jun 24 23:29:13 2014 +0200 @@ -68,29 +68,31 @@ private final int from; private final int to; private final String label; + private final String type; private State state; public InputEdge(char toIndex, int from, int to) { - this((char) 0, toIndex, from, to, null); + this((char) 0, toIndex, from, to, null, null); } public InputEdge(char fromIndex, char toIndex, int from, int to) { - this(fromIndex, toIndex, from, to, null); + this(fromIndex, toIndex, from, to, null, null); } - public InputEdge(char fromIndex, char toIndex, int from, int to, String label) { + public InputEdge(char fromIndex, char toIndex, int from, int to, String label, String type) { this.toIndex = toIndex; this.fromIndex = fromIndex; this.from = from; this.to = to; this.state = State.SAME; this.label = label; + this.type = type; } static WeakHashMap> immutableCache = new WeakHashMap<>(); - public static synchronized InputEdge createImmutable(char fromIndex, char toIndex, int from, int to, String label) { - InputEdge edge = new InputEdge(fromIndex, toIndex, from, to, label, State.IMMUTABLE); + public static synchronized InputEdge createImmutable(char fromIndex, char toIndex, int from, int to, String label, String type) { + InputEdge edge = new InputEdge(fromIndex, toIndex, from, to, label, type, State.IMMUTABLE); WeakReference result = immutableCache.get(edge); if (result != null) { InputEdge edge2 = result.get(); @@ -102,13 +104,14 @@ return edge; } - public InputEdge(char fromIndex, char toIndex, int from, int to, String label, State state) { + public InputEdge(char fromIndex, char toIndex, int from, int to, String label, String type, State state) { this.toIndex = toIndex; this.fromIndex = fromIndex; this.from = from; this.to = to; this.state = state; this.label = label; + this.type = type; } public State getState() { @@ -145,6 +148,10 @@ public String getLabel() { return label; } + + public String getType() { + return type; + } @Override public boolean equals(Object o) { diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java Tue Jun 24 23:29:13 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -215,12 +215,20 @@ } } + private static class TypedPort extends Port { + public final EnumValue type; + private TypedPort(boolean isList, String name, EnumValue type) { + super(isList, name); + this.type = type; + } + } + private static class NodeClass { public final String className; public final String nameTemplate; - public final List inputs; + public final List inputs; public final List sux; - private NodeClass(String className, String nameTemplate, List inputs, List sux) { + private NodeClass(String className, String nameTemplate, List inputs, List sux) { this.className = className; this.nameTemplate = nameTemplate; this.inputs = inputs; @@ -464,11 +472,12 @@ String className = readString(); String nameTemplate = readString(); int inputCount = readShort(); - List inputs = new ArrayList<>(inputCount); + List inputs = new ArrayList<>(inputCount); for (int i = 0; i < inputCount; i++) { boolean isList = readByte() != 0; String name = readPoolObject(String.class); - inputs.add(new Port(isList, name)); + EnumValue inputType = readPoolObject(EnumValue.class); + inputs.add(new TypedPort(isList, name, inputType)); } int suxCount = readShort(); List sux = new ArrayList<>(suxCount); @@ -726,20 +735,20 @@ } int edgesStart = edges.size(); int portNum = 0; - for (Port p : nodeClass.inputs) { + for (TypedPort p : nodeClass.inputs) { if (p.isList) { int size = readShort(); for (int j = 0; j < size; j++) { int in = readInt(); if (in >= 0) { - edges.add(new Edge(in, id, (char) (preds + portNum), p.name + "[" + j + "]", true)); + edges.add(new Edge(in, id, (char) (preds + portNum), p.name + "[" + j + "]", p.type.toString(Length.S), true)); portNum++; } } } else { int in = readInt(); if (in >= 0) { - edges.add(new Edge(in, id, (char) (preds + portNum), p.name, true)); + edges.add(new Edge(in, id, (char) (preds + portNum), p.name, p.type.toString(Length.S), true)); portNum++; } } @@ -752,14 +761,14 @@ for (int j = 0; j < size; j++) { int sux = readInt(); if (sux >= 0) { - edges.add(new Edge(id, sux, (char) portNum, p.name + "[" + j + "]", false)); + edges.add(new Edge(id, sux, (char) portNum, p.name + "[" + j + "]", "Successor", false)); portNum++; } } } else { int sux = readInt(); if (sux >= 0) { - edges.add(new Edge(id, sux, (char) portNum, p.name, false)); + edges.add(new Edge(id, sux, (char) portNum, p.name, "Successor", false)); portNum++; } } @@ -780,7 +789,7 @@ for (Edge e : edges) { char fromIndex = e.input ? 1 : e.num; char toIndex = e.input ? e.num : 0; - graph.addEdge(InputEdge.createImmutable(fromIndex, toIndex, e.from, e.to, e.label)); + graph.addEdge(InputEdge.createImmutable(fromIndex, toIndex, e.from, e.to, e.label, e.type)); } } @@ -845,14 +854,16 @@ final int to; final char num; final String label; + final String type; final boolean input; public Edge(int from, int to) { - this(from, to, (char) 0, null, false); + this(from, to, (char) 0, null, null, false); } - public Edge(int from, int to, char num, String label, boolean input) { + public Edge(int from, int to, char num, String label, String type, boolean input) { this.from = from; this.to = to; this.label = label != null ? label.intern() : label; + this.type = type != null ? type.intern() : type; this.num = num; this.input = input; } diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java Tue Jun 24 23:29:13 2014 +0200 @@ -410,7 +410,7 @@ throw new SAXException(e); } - InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label); + InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label, ""); return start(conn); } diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java --- a/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java Tue Jun 24 23:29:13 2014 +0200 @@ -211,7 +211,7 @@ if (nodeFrom == null || nodeTo == null) { System.out.println("Unexpected edge : " + from + " -> " + to); } else { - InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); + InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId(), e.getLabel(), e.getType()); if (!newEdges.contains(newEdge)) { markAsDeleted(newEdge); newEdges.add(newEdge); @@ -231,7 +231,7 @@ if (nodeFrom == null || nodeTo == null) { System.out.println("Unexpected edge : " + from + " -> " + to); } else { - InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); + InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId(), e.getLabel(), e.getType()); if (!newEdges.contains(newEdge)) { markAsNew(newEdge); newEdges.add(newEdge); diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java --- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java Tue Jun 24 23:29:13 2014 +0200 @@ -97,7 +97,7 @@ for (InputSlot s : f.getInputSlots()) { for (Connection c : s.getConnections()) { - Connection newConn = diagram.createConnection(slot, c.getOutputSlot(), c.getLabel()); + Connection newConn = diagram.createConnection(slot, c.getOutputSlot(), c.getLabel(), c.getType()); newConn.setColor(c.getColor()); newConn.setStyle(c.getStyle()); } @@ -154,7 +154,7 @@ } } for (Connection c : nextSlot.getConnections()) { - Connection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel()); + Connection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel(), c.getType()); newConn.setColor(c.getColor()); newConn.setStyle(c.getStyle()); } diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java --- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Tue Jun 24 23:29:13 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -31,6 +31,7 @@ import com.sun.hotspot.igv.graph.Figure; import com.sun.hotspot.igv.graph.InputSlot; import java.awt.Color; +import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; @@ -41,9 +42,8 @@ */ public class GraalEdgeColorFilter extends AbstractFilter { - private Color successorColor = Color.BLUE; - private Color usageColor = Color.RED; - private Color memoryColor = Color.GREEN; + private HashMap usageColor = new HashMap<>(); + private Color otherUsageColor = Color.BLACK; public GraalEdgeColorFilter() { } @@ -56,66 +56,43 @@ @Override public void apply(Diagram d) { List

figures = d.getFigures(); - Pattern ndf = Pattern.compile(".*#NDF(\\[[0-9]*\\])?"); for (Figure f : figures) { - Properties p = f.getProperties(); - int predCount; - String predCountString = p.get("predecessorCount"); - if (predCountString != null) { - predCount = Integer.parseInt(predCountString); - } else if (Boolean.parseBoolean(p.get("hasPredecessor"))) { - predCount = 1; - } else { - predCount = 0; - } for (InputSlot is : f.getInputSlots()) { - Color color; - ConnectionStyle style = ConnectionStyle.NORMAL; - if (is.getPosition() < predCount) { - color = successorColor; - style = ConnectionStyle.BOLD; - } else { - color = usageColor; - } - - is.setColor(color); for (Connection c : is.getConnections()) { - if (c.getLabel() == null || !ndf.matcher(c.getLabel()).matches()) { - c.setColor(color); - if (c.getStyle() != ConnectionStyle.DASHED) { - c.setStyle(style); + String type = c.getType(); + if (type == "Association" && "EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))) { + type = "Successor"; + } + + if (type != null) { + Color typeColor = usageColor.get(type); + if (typeColor == null) { + c.setColor(otherUsageColor); + } else { + c.setColor(typeColor); } - } else if ("EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class")) - || "EndNode".equals(c.getOutputSlot().getProperties().get("class"))) { - c.setColor(successorColor); - c.setStyle(ConnectionStyle.BOLD); + if (c.getStyle() != ConnectionStyle.DASHED && type == "Successor") { + c.setStyle(ConnectionStyle.BOLD); + } } } } } } - public Color getUsageColor() { - return usageColor; - } - - public void setUsageColor(Color usageColor) { - this.usageColor = usageColor; - } - - public void setMemoryColor(Color memoryColor) { - this.memoryColor = memoryColor; + public Color getUsageColor(String type) { + return usageColor.get(type); } - public Color getMemoryColor() { - return memoryColor; + public void setUsageColor(String type, Color usageColor) { + this.usageColor.put(type, usageColor); } - - public Color getSuccessorColor() { - return successorColor; + + public Color getOtherUsageColor() { + return otherUsageColor; } - - public void setSuccessorColor(Color successorColor) { - this.successorColor = successorColor; + + public void setOtherUsageColor(Color otherUsageColor) { + this.otherUsageColor = otherUsageColor; } } diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter --- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter Tue Jun 24 23:29:13 2014 +0200 @@ -1,4 +1,5 @@ var f = new com.sun.hotspot.igv.graal.filters.GraalEdgeColorFilter(); -f.setUsageColor(blue); -f.setSuccessorColor(red); +f.setUsageColor("Successor", red); +f.setUsageColor("Value", blue); +f.setUsageColor("Memory", new Color(0.0, 0.5, 0.0)); f.apply(graph); diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java --- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java Tue Jun 24 23:29:13 2014 +0200 @@ -55,11 +55,13 @@ private ConnectionStyle style; private List controlPoints; private String label; + private String type; - protected Connection(InputSlot inputSlot, OutputSlot outputSlot, String label) { + protected Connection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) { this.inputSlot = inputSlot; this.outputSlot = outputSlot; this.label = label; + this.type = type; this.inputSlot.connections.add(this); this.outputSlot.connections.add(this); controlPoints = new ArrayList<>(); @@ -105,6 +107,10 @@ public String getLabel() { return label; } + + public String getType() { + return type; + } public void remove() { inputSlot.getFigure().removePredecessor(outputSlot.getFigure()); @@ -116,10 +122,12 @@ public String getToolTipText() { StringBuilder builder = new StringBuilder(); if (label != null) { - builder.append(label).append(": from "); - } else { - builder.append("From "); + builder.append(label).append(": "); } + if (type != null) { + builder.append(type).append(" "); + } + builder.append("from "); builder.append(getOutputSlot().getFigure().getSource().getSourceNodes().get(0).getId()); builder.append(" to "); builder.append(getInputSlot().getFigure().getSource().getSourceNodes().get(0).getId()); diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java --- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java Tue Jun 24 23:29:13 2014 +0200 @@ -82,10 +82,10 @@ return f; } - public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label) { + public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) { assert inputSlot.getFigure().getDiagram() == this; assert outputSlot.getFigure().getDiagram() == this; - return new Connection(inputSlot, outputSlot, label); + return new Connection(inputSlot, outputSlot, label, type); } public Map> calcSourceToFigureRelation() { @@ -145,7 +145,7 @@ } InputSlot inputSlot = toFigure.getInputSlots().get(toIndex); - Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel()); + Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel(), e.getType()); if (e.getState() == InputEdge.State.NEW) { c.setStyle(Connection.ConnectionStyle.BOLD); diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/vm/compiler/compileBroker.cpp Tue Jun 24 23:29:13 2014 +0200 @@ -383,7 +383,7 @@ st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp } // print compiler name if requested - if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level)); + if (CIPrintCompilerName) st->print("%s:", CompileBroker::compiler_name(comp_level)); st->print("%4d ", compile_id); // print compilation number // For unloaded methods the transition to zombie occurs after the @@ -805,7 +805,19 @@ #if defined(COMPILERGRAAL) _compilers[1] = graal; - c2_count = UseGraalCompilationQueue ? 0 : FLAG_IS_DEFAULT(GraalThreads) ? c2_count : GraalThreads; + if (UseGraalCompilationQueue) { + c2_count = 0; + } else { + if (FLAG_IS_DEFAULT(GraalThreads)) { + if (!TieredCompilation && FLAG_IS_DEFAULT(BootstrapGraal) || BootstrapGraal) { + // Graal will bootstrap so give it the same number of threads + // as we would give the Java based compilation queue. + c2_count = os::active_processor_count(); + } + } else { + c2_count = GraalThreads; + } + } #endif // COMPILERGRAAL #ifdef COMPILER2 diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Tue Jun 24 23:29:13 2014 +0200 @@ -125,7 +125,9 @@ if (!UseGraalCompilationQueue) { ResourceMark rm; HandleMark hm; - tty->print("Bootstrapping Graal"); + if (PrintBootstrap) { + tty->print("Bootstrapping Graal"); + } jlong start = os::javaTimeMillis(); Array* objectMethods = InstanceKlass::cast(SystemDictionary::Object_klass())->methods(); @@ -147,14 +149,17 @@ os::sleep(THREAD, sleep_time, true); sleep_time = 100; qsize = CompileBroker::queue_size(CompLevel_full_optimization); - while (z < (_compiled / 100)) { + if (PrintBootstrap) { + while (z < (_compiled / 100)) { ++z; tty->print_raw("."); + } } - } while (qsize != 0); - tty->print_cr(" in %d ms (compiled %d methods)", os::javaTimeMillis() - start, _compiled); + if (PrintBootstrap) { + tty->print_cr(" in %d ms (compiled %d methods)", os::javaTimeMillis() - start, _compiled); + } } else { TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/CompilationQueue", THREAD); diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Jun 24 23:29:13 2014 +0200 @@ -194,9 +194,9 @@ return (jlong) (address) method(); } -C2V_VMENTRY(jlong, findUniqueConcreteMethod, (JNIEnv *, jobject, jlong metaspace_method)) +C2V_VMENTRY(jlong, findUniqueConcreteMethod, (JNIEnv *, jobject, jlong metaspace_klass, jlong metaspace_method)) methodHandle method = asMethod(metaspace_method); - KlassHandle holder = method->method_holder(); + KlassHandle holder = asKlass(metaspace_klass); assert(!holder->is_interface(), "should be handled in Java code"); ResourceMark rm; MutexLocker locker(Compile_lock); @@ -1003,7 +1003,7 @@ {CC"exceptionTableStart", CC"("METASPACE_METHOD")J", FN_PTR(exceptionTableStart)}, {CC"exceptionTableLength", CC"("METASPACE_METHOD")I", FN_PTR(exceptionTableLength)}, {CC"hasBalancedMonitors", CC"("METASPACE_METHOD")Z", FN_PTR(hasBalancedMonitors)}, - {CC"findUniqueConcreteMethod", CC"("METASPACE_METHOD")"METASPACE_METHOD, FN_PTR(findUniqueConcreteMethod)}, + {CC"findUniqueConcreteMethod", CC"("METASPACE_KLASS METASPACE_METHOD")"METASPACE_METHOD, FN_PTR(findUniqueConcreteMethod)}, {CC"getKlassImplementor", CC"("METASPACE_KLASS")"METASPACE_KLASS, FN_PTR(getKlassImplementor)}, {CC"getStackTraceElement", CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)}, {CC"methodIsIgnoredBySecurityStackWalk", CC"("METASPACE_METHOD")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)}, diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/vm/graal/graalGlobals.hpp --- a/src/share/vm/graal/graalGlobals.hpp Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/vm/graal/graalGlobals.hpp Tue Jun 24 23:29:13 2014 +0200 @@ -52,6 +52,9 @@ COMPILERGRAAL_PRESENT(product(bool, BootstrapGraal, true, \ "Bootstrap Graal before running Java main method")) \ \ + COMPILERGRAAL_PRESENT(product(bool, PrintBootstrap, true, \ + "Print Graal bootstrap progress and summary")) \ + \ COMPILERGRAAL_PRESENT(product(intx, GraalThreads, 1, \ "Force number of Graal compiler threads to use")) \ \ diff -r 38bb9b5b8544 -r 6140fd60abe9 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Tue Jun 24 23:24:02 2014 +0200 +++ b/src/share/vm/runtime/sharedRuntime.cpp Tue Jun 24 23:29:13 2014 +0200 @@ -886,7 +886,7 @@ // If there's no PcDesc then we'll die way down inside of // deopt instead of just getting normal error reporting, // so only go there if it will succeed. - target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_null_check); + return deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_null_check); } else { #endif target_pc = nm->continuation_for_implicit_exception(pc); @@ -910,7 +910,7 @@ #endif #ifdef GRAAL if (nm->is_compiled_by_graal() && nm->pc_desc_at(pc) != NULL) { - target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check); + return deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check); } else { #endif target_pc = nm->continuation_for_implicit_exception(pc); @@ -928,11 +928,17 @@ assert(exception_kind == IMPLICIT_NULL || exception_kind == IMPLICIT_DIVIDE_BY_ZERO, "wrong implicit exception kind"); - // for AbortVMOnException flag - NOT_PRODUCT(Exceptions::debug_check_abort("java.lang.NullPointerException")); if (exception_kind == IMPLICIT_NULL) { +#ifndef PRODUCT + // for AbortVMOnException flag + Exceptions::debug_check_abort("java.lang.NullPointerException"); +#endif //PRODUCT Events::log_exception(thread, "Implicit null exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc); } else { +#ifndef PRODUCT + // for AbortVMOnException flag + Exceptions::debug_check_abort("java.lang.ArithmeticException"); +#endif //PRODUCT Events::log_exception(thread, "Implicit division by zero exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc); } return target_pc;